Initial commit

This commit is contained in:
Martin Linkwitz - NUC
2026-04-02 14:25:39 +02:00
parent ea3b0f29ea
commit c7adbcd1c7
110 changed files with 189727 additions and 33726 deletions

Binary file not shown.

View File

@@ -1,7 +1,7 @@
{
"configuration": "pinout=48pin_standard,eeprom=keep,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader",
"board": "MegaCoreX:megaavr:809",
"sketch": "Switch.ino",
"port": "COM6",
"programmer": "jtag2updi"
{
"configuration": "pinout=48pin_standard,eeprom=keep,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader",
"board": "MegaCoreX:megaavr:809",
"sketch": "Switch.ino",
"port": "COM6",
"programmer": "jtag2updi"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,255 +1,232 @@
#include "MeyCan.h";
#include <SPI.h>;
#include <mcp2515.h>;
PinState *MeyPin = NULL;
CanInterface *CanBusses = NULL;
uint16_t myDeviceId;
byte _deviceTypeId = 0;
byte _majorHardwareVersion = 0;
byte _minorHardwareVersion = 0;
void SetupMeyPin(PinState *state)
{
pinMode(state->pin_id, OUTPUT);
digitalWrite(state->pin_id, LOW);
state->pin_state = false;
}
void InitCanInterface(MCP2515 *interface, can_frame *frame) // can_frame is NULL. Reuse ForEach Method for smaller footprint
{
interface->reset();
interface->setBitrate(CAN_500KBPS, MCP_8MHZ); //Sets CAN at speed 500KBPS and Clock 8MHz
interface->setNormalMode();
SendVersionPackage(interface);
}
void ForEachCanInterface(void (*handle)(MCP2515 *canInterace))
{
CanBusses->ForEachInterface(handle);
}
void SetupMeyCan(byte majorHardwareVersion, byte minorHardwareVersion, byte deviceTypeId)
{
_majorHardwareVersion = majorHardwareVersion;
_minorHardwareVersion = minorHardwareVersion;
_deviceTypeId = deviceTypeId;
CalculateMyDeviceId();
if (MeyPin != NULL);
MeyPin->ForEach(SetupMeyPin);
if (CanBusses != NULL)
{
CanBusses->ForEach(InitCanInterface, NULL);
}
}
void AddCanInterface(byte pinId)
{
MCP2515* newCanInterface = new MCP2515(pinId);
CanInterface* canInterface = new CanInterface();
canInterface->interface = newCanInterface;
if (CanBusses == NULL)
CanBusses = canInterface;
else
CanBusses->AddCanInterface(canInterface);
}
void SetMeyPin(byte index, byte meyPinId, byte pinId)
{
PinState* newState = new PinState();
newState->Init(pinId, (byte) meyPinId);
if (MeyPin == NULL)
MeyPin = newState;
else
MeyPin->AddPinState(newState);
}
bool CheckPinStatus(PinState * state)
{
if (!state->is_input)
return false;
bool newValue = ReadPin(state);
if (newValue != state->pin_state)
{
delay(10);
newValue = ReadPin(state);
if (newValue != state->pin_state)
{
state->pin_state = newValue;
SendSwitchedTriggeredCanPackage(state->meyPinId, state->pin_state);
}
}
return false;
}
void CheckMeyPinsTriggered()
{
MeyPin->ForEach(CheckPinStatus);
}
bool ReadPin(PinState * state)
{
if (state->pin_id == PIN_PD2)
return digitalReadFast(PIN_PD2);
else if (state->pin_id == PIN_PC7)
return digitalReadFast(PIN_PC7);
else if (state->pin_id == PIN_PD1)
return digitalReadFast(PIN_PD1);
else if (state->pin_id == PIN_PD0)
return digitalReadFast(PIN_PD0);
else if (state->pin_id == PIN_PD6)
return digitalReadFast(PIN_PD6);
else if (state->pin_id == PIN_PD5)
return digitalReadFast(PIN_PD5);
else if (state->pin_id == PIN_PD4)
return digitalReadFast(PIN_PD4);
else if (state->pin_id == PIN_PD3)
return digitalReadFast(PIN_PD3);
else
return digitalRead(state->pin_id);
}
void HandleFrame(can_frame *frame, MCP2515 *source)
{
CanBusses->ForEach(DoSendCanPkg, frame, source);
HandleTriggerMeypinCanPackage(frame);
}
void HandleTriggerMeypinCanPackage(can_frame *frame)
{
if (GetPackageType(frame->can_id) == TRIGGER_SWITCH_CAN_ID)
{
uint16_t adressedDeviceId = ((uint16_t )frame->data[0] << 8) | frame->data[1] ;
if (adressedDeviceId != myDeviceId) return;
byte meyPinId = frame->data[2];
bool state = frame->data[3] > 0;
PinState *adressedPin = MeyPin->Find(meyPinId);
if (adressedPin != NULL)
{
if (adressedPin->is_input == true)
{
pinMode(adressedPin->pin_id, OUTPUT);
adressedPin->is_input = false;
}
bool pinChanged = adressedPin->pin_state != state;
adressedPin->pin_state = state;
if (pinChanged) {
digitalWrite(adressedPin->pin_id, state);
SendSwitchedTriggeredCanPackage(adressedPin->meyPinId, state);
}
}
}
}
byte CircularShift(byte b)
{
return (b << 1) | (b >> 7 & 1);
}
uint16_t GetDeviceId(uint32_t canFrameId)
{
return canFrameId & 0xFFFF;
}
uint16_t GetPackageType(uint32_t canFrameId)
{
return (canFrameId / 0x10000) & 0xFFF;
}
byte GetDeviceIdLow() {
return (SIGROW.SERNUM0 ^
CircularShift(SIGROW.SERNUM2) << 1 ^
CircularShift( CircularShift(SIGROW.SERNUM4)) ^
CircularShift( CircularShift( CircularShift(SIGROW.SERNUM6))) ^
CircularShift( CircularShift( CircularShift( CircularShift(SIGROW.SERNUM8)))));
}
byte GetDeviceIdHigh() {
return (SIGROW.SERNUM1 ^
CircularShift(SIGROW.SERNUM3) << 1 ^
CircularShift( CircularShift(SIGROW.SERNUM5)) ^
CircularShift( CircularShift( CircularShift(SIGROW.SERNUM7))) ^
CircularShift( CircularShift( CircularShift( CircularShift(SIGROW.SERNUM9)))));
}
uint32_t CreateCanId(uint16_t commandId)
{
return ((((uint32_t)commandId) & 0xFFF) * 0x10000) | myDeviceId | CAN_EFF_FLAG;
}
void SendVersionPackage(MCP2515 *interface)
{
can_frame toSend;
toSend.can_id = CreateCanId(HELP_PACKAGE_CAN_ID);
toSend.can_dlc = 5;
toSend.data[0] = SOFTWARE_VERSION_HIGH;
toSend.data[1] = SOFTWARE_VERSION_LOW;
toSend.data[2] = _majorHardwareVersion;
toSend.data[3] = _minorHardwareVersion;
toSend.data[4] = _deviceTypeId;
DoSendCanPkg(interface, &toSend);
}
void BroadcastTriggerMeyPinCanPackage(uint16_t targetCanId, byte pinId, byte state)
{
can_frame toSend;
toSend.can_id = CreateCanId(TRIGGER_SWITCH_CAN_ID);
toSend.can_dlc = 4;
toSend.data[0] = (targetCanId & 0xFF00) >> 8;
toSend.data[1] = targetCanId & 0xFF;
toSend.data[2] = pinId;
toSend.data[3] = state;
HandleFrame(&toSend, NULL);
}
void SendSwitchedTriggeredCanPackage(byte pinId, int state)
{
can_frame toSend;
toSend.can_id = CreateCanId(SWITCH_TRIGGERED_CAN_ID);
toSend.can_dlc = 2;
toSend.data[0] = pinId;
toSend.data[1] = state;
DoSendCanPkg(&toSend);
}
void DoSendCanPkg(can_frame *frame)
{
if (CanBusses != NULL)
CanBusses->ForEach(DoSendCanPkg, frame);
}
void DoSendCanPkg(MCP2515 *interface, can_frame *frame)
{
byte cnt = 0;
while (interface->sendMessage(frame))
{
if (++cnt > 10) return;
}
}
void CalculateMyDeviceId()
{
myDeviceId = (GetDeviceIdHigh() << 8) | GetDeviceIdLow();
}
#include "MeyCan.h";
#include <SPI.h>;
#include <mcp2515.h>;
PinState *MeyPin = NULL;
CanInterface *CanBusses = NULL;
uint16_t myDeviceId;
byte _deviceTypeId = 0;
byte _majorHardwareVersion = 0;
byte _minorHardwareVersion = 0;
void (*LocalPinChangedHandler)(can_frame *frame);
void SetupMeyPin(PinState *state) {
pinMode(state->pin_id, OUTPUT);
digitalWrite(state->pin_id, LOW);
state->pin_state = false;
}
void InitCanInterface(MCP2515 *interface, can_frame *frame) // can_frame is NULL. Reuse ForEach Method for smaller footprint
{
interface->reset();
interface->setBitrate(CAN_1000KBPS, MCP_8MHZ); //Sets CAN at speed 500KBPS and Clock 8MHz
interface->setNormalMode();
SendVersionPackage(interface);
}
void ForEachCanInterface(void (*handle)(MCP2515 *canInterace)) {
CanBusses->ForEachInterface(handle);
}
void SetupMeyCan(byte majorHardwareVersion, byte minorHardwareVersion, byte deviceTypeId) {
_majorHardwareVersion = majorHardwareVersion;
_minorHardwareVersion = minorHardwareVersion;
_deviceTypeId = deviceTypeId;
if (MeyPin != NULL)
;
MeyPin->ForEach(SetupMeyPin);
if (CanBusses != NULL) {
CanBusses->ForEach(InitCanInterface, NULL);
}
}
void AddCanInterface(byte pinId) {
MCP2515 *newCanInterface = new MCP2515(pinId);
CanInterface *canInterface = new CanInterface();
canInterface->interface = newCanInterface;
if (CanBusses == NULL)
CanBusses = canInterface;
else
CanBusses->AddCanInterface(canInterface);
}
void AddLocalPinChangedHandler(void (*localPinChangedHandler)(can_frame *frame)) {
LocalPinChangedHandler = localPinChangedHandler;
}
void SetDevicedId(byte high, byte low) {
myDeviceId = (high << 8) | low;
}
void SetMeyPin(byte meyPinId, byte pinId) {
PinState *newState = new PinState();
newState->Init(pinId, (byte)meyPinId);
if (MeyPin == NULL)
MeyPin = newState;
else
MeyPin->AddPinState(newState);
}
bool CheckPinStatus(PinState *state) {
if (!state->is_input)
return false;
bool newValue = ReadPin(state);
if (newValue != state->pin_state) {
delay(10);
newValue = ReadPin(state);
if (newValue != state->pin_state) {
state->pin_state = newValue;
SendSwitchedTriggeredCanPackage(state->meyPinId, state->pin_state);
}
}
return false;
}
void CheckMeyPinsTriggered() {
MeyPin->ForEach(CheckPinStatus);
}
bool ReadPin(PinState *state) {
return digitalRead(state->pin_id);
}
void HandleFrame(can_frame *frame, MCP2515 *source) {
CanBusses->ForEach(DoSendCanPkg, frame, source);
HandleTriggerMeypinCanPackage(frame);
}
void HandleTriggerMeypinCanPackage(can_frame *frame) {
if (GetPackageType(frame->can_id) == TRIGGER_SWITCH_CAN_ID) {
uint16_t adressedDeviceId = ((uint16_t)frame->data[0] << 8) | frame->data[1];
if (adressedDeviceId != myDeviceId) return;
byte meyPinId = frame->data[2];
bool state = frame->data[3] > 0;
PinState *adressedPin = MeyPin->Find(meyPinId);
if (adressedPin != NULL) {
if (adressedPin->is_input == true) {
pinMode(adressedPin->pin_id, OUTPUT);
adressedPin->is_input = false;
}
bool pinChanged = adressedPin->pin_state != state;
adressedPin->pin_state = state;
if (pinChanged) {
digitalWrite(adressedPin->pin_id, state);
SendSwitchedTriggeredCanPackage(adressedPin->meyPinId, state);
}
}
}
}
byte CircularShift(byte b) {
return (b << 1) | (b >> 7 & 1);
}
uint16_t GetDeviceId(uint32_t canFrameId) {
return canFrameId & 0xFFFF;
}
uint16_t GetPackageType(uint32_t canFrameId) {
return (canFrameId / 0x10000) & 0xFFF;
}
uint32_t CreateCanId(uint16_t commandId) {
return ((((uint32_t)commandId) & 0xFFF) * 0x10000) | myDeviceId | CAN_EFF_FLAG;
}
void SendVersionPackage(MCP2515 *interface) {
can_frame toSend;
toSend.can_id = CreateCanId(HELP_PACKAGE_CAN_ID);
toSend.can_dlc = 5;
toSend.data[0] = SOFTWARE_VERSION_HIGH;
toSend.data[1] = SOFTWARE_VERSION_LOW;
toSend.data[2] = _majorHardwareVersion;
toSend.data[3] = _minorHardwareVersion;
toSend.data[4] = _deviceTypeId;
DoSendCanPkg(interface, &toSend);
}
void BroadcastTriggerMeyPinCanPackage(uint16_t targetCanId, byte pinId, byte state) {
can_frame toSend;
toSend.can_id = CreateCanId(TRIGGER_SWITCH_CAN_ID);
toSend.can_dlc = 4;
toSend.data[0] = (targetCanId & 0xFF00) >> 8;
toSend.data[1] = targetCanId & 0xFF;
toSend.data[2] = pinId;
toSend.data[3] = state;
HandleFrame(&toSend, NULL);
}
void BroadcastDebugPackage(uint8_t length, byte *data) {
can_frame toSend;
toSend.can_id = CreateCanId(DEBUG_PKG_CAN_ID);
toSend.can_dlc = length;
for (int i = 0; i < length; i++) {
toSend.data[i] = data[i];
}
HandleFrame(&toSend, NULL);
}
void BroadcastDebugPackage(byte b0, byte b1) {
byte data[2];
data[0] = b0;
data[1] = b1;
BroadcastDebugPackage(2, data);
}
void BroadcastDebugPackage(byte b0, byte b1, byte b2) {
byte data[3];
data[0] = b0;
data[1] = b1;
data[2] = b2;
BroadcastDebugPackage(3, data);
}
void SendSwitchedTriggeredCanPackage(byte pinId, int state) {
can_frame toSend;
toSend.can_id = CreateCanId(SWITCH_TRIGGERED_CAN_ID);
toSend.can_dlc = 2;
toSend.data[0] = pinId;
toSend.data[1] = state;
DoSendCanPkg(&toSend);
if (LocalPinChangedHandler) {
LocalPinChangedHandler(&toSend);
}
}
void DoSendCanPkg(can_frame *frame) {
if (CanBusses != NULL)
CanBusses->ForEach(DoSendCanPkg, frame);
}
void DoSendCanPkg(MCP2515 *interface, can_frame *frame) {
byte cnt = 0;
while (interface->sendMessage(frame)) {
if (++cnt > 10) return;
}
}

View File

@@ -1,128 +1,139 @@
#ifndef MEYCAN_H
#define MEYCAN_H
#include <SPI.h>
#include <mcp2515.h>
typedef struct CanInterface
{
MCP2515 *interface;
CanInterface *next = NULL;
void ForEachInterface(void (*handle)( MCP2515 *interface))
{
if (this->interface != NULL)
handle(this->interface);
if (this->next != NULL)
this->next->ForEachInterface(handle);
}
void ForEach(void (*handle)( MCP2515 *interface, can_frame *frame), can_frame *frame, MCP2515* exclude = NULL)
{
if (this->interface != NULL && this->interface != exclude)
handle(this->interface, frame);
if (this->next != NULL)
this->next->ForEach(handle, frame, exclude);
}
void AddCanInterface(CanInterface *newCanInterface)
{
if (next == NULL)
{
this->next = newCanInterface;
newCanInterface->next = NULL;
} else {
next->AddCanInterface(newCanInterface);
}
}
};
typedef struct PinState
{
int pin_id;
bool pin_state;
bool is_input;
byte meyPinId;
PinState *next = NULL;
PinState() {}
void Init(int pin_id, byte meyPinId)
{
this->pin_id = pin_id;
this->pin_state = true;
this->is_input = true;
this->meyPinId = meyPinId;
}
void AddPinState(PinState *nextPinState)
{
if (next == NULL)
{
this->next = nextPinState;
nextPinState->next = NULL;
} else {
next->AddPinState(nextPinState);
}
}
PinState* Find(byte meyPinId)
{
if (this->meyPinId == meyPinId)
return this;
if (this->next != NULL)
return this->next->Find(meyPinId);
return NULL;
}
void ForEach(void (*handle)(PinState *theState))
{
handle(this);
if (this->next != NULL)
this->next->ForEach(handle);
}
};
const byte SOFTWARE_VERSION_HIGH = 5;
const byte SOFTWARE_VERSION_LOW = 0;
const byte HARDWARE_VERSION_HIGH = 7;
const byte HARDWARE_VERSION_LOW = 0;
const uint16_t HELP_PACKAGE_CAN_ID = 0x0FFFUL;
const uint16_t SWITCH_TRIGGERED_CAN_ID = 0x0050;
const uint16_t TRIGGER_SWITCH_CAN_ID = 0x0055;
void AddCanInterface(byte pinId);
void SetMeyPin(byte index, byte meyPinId, byte pinId);
void SetupMeyCan(byte majorHardwareVersion, byte minorHardwareVersion, byte deviceTypeId);
void ForEachCanInterface(void (*handle)(MCP2515 *canInterace));
bool ReadPin(PinState *state);
bool CheckPinStatus(PinState * state);
void CheckMeyPinsTriggered(); /* checks weather a meypin triggered and sends a can pkg is neccessary */
void HandleFrame(can_frame *frame, MCP2515 *source);
void HandleTriggerMeypinCanPackage(can_frame *frame);
byte CircularShift(byte b);
uint16_t GetDeviceId(uint32_t canFrameId);
uint16_t GetPackageType(uint32_t canFrameId);
byte GetDeviceIdLow();
byte GetDeviceIdHigh();
uint32_t CreateCanId(uint16_t commandId);
void SendVersionPackage(MCP2515 *interface);
void SendSwitchedTriggeredCanPackage(byte pinId, int state);
void BroadcastTriggerMeyPinCanPackage(uint16_t targetCanId, byte pinId, byte state);
void DoSendCanPkg(can_frame *frame);
void DoSendCanPkg(MCP2515 *interface, can_frame *frame);
void CalculateMyDeviceId();
#endif
#ifndef MEYCAN_H
#define MEYCAN_H
#include <SPI.h>
#include <mcp2515.h>
typedef struct CanInterface
{
MCP2515 *interface;
CanInterface *next = NULL;
void ForEachInterface(void (*handle)( MCP2515 *interface))
{
if (this->interface != NULL)
handle(this->interface);
if (this->next != NULL)
this->next->ForEachInterface(handle);
}
void ForEach(void (*handle)( MCP2515 *interface, can_frame *frame), can_frame *frame, MCP2515* exclude = NULL)
{
if (this->interface != NULL && this->interface != exclude)
handle(this->interface, frame);
if (this->next != NULL)
this->next->ForEach(handle, frame, exclude);
}
void AddCanInterface(CanInterface *newCanInterface)
{
if (next == NULL)
{
this->next = newCanInterface;
newCanInterface->next = NULL;
} else {
next->AddCanInterface(newCanInterface);
}
}
};
typedef struct PinState
{
int pin_id;
bool pin_state;
bool is_input;
byte meyPinId;
PinState *next = NULL;
PinState() {}
void Init(int pin_id, byte meyPinId)
{
this->pin_id = pin_id;
this->pin_state = true;
this->is_input = true;
this->meyPinId = meyPinId;
}
void AddPinState(PinState *nextPinState)
{
if (next == NULL)
{
this->next = nextPinState;
nextPinState->next = NULL;
} else {
next->AddPinState(nextPinState);
}
}
PinState* Find(byte meyPinId)
{
if (this->meyPinId == meyPinId)
return this;
if (this->next != NULL)
return this->next->Find(meyPinId);
return NULL;
}
void ForEach(void (*handle)(PinState *theState))
{
handle(this);
if (this->next != NULL)
this->next->ForEach(handle);
}
};
const byte SOFTWARE_VERSION_HIGH = 5;
const byte SOFTWARE_VERSION_LOW = 0;
const byte HARDWARE_VERSION_HIGH = 7;
const byte HARDWARE_VERSION_LOW = 0;
const uint16_t HELP_PACKAGE_CAN_ID = 0x0FFFUL;
const uint16_t SWITCH_TRIGGERED_CAN_ID = 0x0050;
const uint16_t TRIGGER_SWITCH_CAN_ID = 0x0055;
const uint16_t DEBUG_PKG_CAN_ID = 0x0009;
void SetDevicedId(byte high, byte low);
void SetMeyPin(byte meyPinId, byte pinId);
// we need to put the local change to the rules engine. otherwise local changes on a pin will not come to the rules state.
void AddLocalPinChangedHandler(void (*localPinChangedHandler)(can_frame *frame));
void AddCanInterface(byte pinId);
void SetupMeyCan(byte majorHardwareVersion, byte minorHardwareVersion, byte deviceTypeId);
void ForEachCanInterface(void (*handle)(MCP2515 *canInterace));
bool ReadPin(PinState *state);
bool CheckPinStatus(PinState * state);
void CheckMeyPinsTriggered(); /* checks weather a meypin triggered and sends a can pkg is neccessary */
void HandleFrame(can_frame *frame, MCP2515 *source);
void HandleTriggerMeypinCanPackage(can_frame *frame);
byte CircularShift(byte b);
uint16_t GetDeviceId(uint32_t canFrameId);
uint16_t GetPackageType(uint32_t canFrameId);
byte GetDeviceIdLow();
byte GetDeviceIdHigh();
uint32_t CreateCanId(uint16_t commandId);
void SendVersionPackage(MCP2515 *interface);
void SendSwitchedTriggeredCanPackage(byte pinId, int state);
void BroadcastDebugPackage(byte b0, byte b1);
void BroadcastDebugPackage(byte b0, byte b1, byte b2);
void BroadcastTriggerMeyPinCanPackage(uint16_t targetCanId, byte pinId, byte state);
void DoSendCanPkg(can_frame *frame);
void DoSendCanPkg(MCP2515 *interface, can_frame *frame);
void CalculateMyDeviceId();
#endif

View File

@@ -1,114 +1,117 @@
#include "MeyRule.h"
#include "MeyCan.h"
#include <Arduino.h>
#include <mcp2515.h>;
RemotePinInfo remotePinInfo = RemotePinInfo();
Rule *rules = NULL;
void PutRule(Rule *rule)
{
if (rules == NULL)
rules = rule;
else
rules->AddRule(rule);
}
void AddSimple(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId)
{
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->targetDevId = targetDevId;
rule->targetMeyPinId = targetMeyPinId;
rule->toggle = false;
rule->inverse = false;
rule->lastPinState = false;
PutRule(rule);
}
void AddToggle(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId)
{
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->targetDevId = targetDevId;
rule->targetMeyPinId = targetMeyPinId;
rule->toggle = true;
rule->inverse = false;
rule->lastPinState = false;
PutRule(rule);
}
void AddToggleInverse(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId)
{
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->targetDevId = targetDevId;
rule->targetMeyPinId = targetMeyPinId;
rule->toggle = true;
rule->inverse = true;
rule->lastPinState = false;
PutRule(rule);
}
void CheckRule(uint16_t deviceId, uint8_t dt, uint8_t state, Rule *rule)
{
RemotePinInfo *currentRemotePinInfo = remotePinInfo.FindOrAdd(rule->targetDevId);
if (currentRemotePinInfo == NULL) return;
// check the new state with the last one. Needs to be done, as the UP switch might
// send it multiple times like "01 01" "01 01" for a single tip.(antibeat)
bool lastPinState = rule->lastPinState;
bool pinState = dt > 0;
if (rule->triggeredOnce && lastPinState == pinState) return;
rule->lastPinState = pinState;
rule->triggeredOnce = true;
if (rule->inverse)
pinState = !pinState;
if (rule->toggle)
pinState = (currentRemotePinInfo->getPinState(rule->targetMeyPinId) ^ true);
BroadcastTriggerMeyPinCanPackage(rule->targetDevId, rule->targetMeyPinId, pinState);
currentRemotePinInfo->setPinState(rule->targetMeyPinId, pinState);
}
void HandleTriggered(can_frame *frame)
{
if (GetPackageType(frame->can_id) == SWITCH_TRIGGERED_CAN_ID)
{
RemotePinInfo *currentPinState = remotePinInfo.FindOrAdd(GetDeviceId(frame->can_id) );
if (currentPinState == NULL)
return;
currentPinState->setPinState(frame->data[0], frame->data[1]);
}
}
void HandleRules(can_frame *frame)
{
HandleTriggered(frame);
if (rules == NULL) return;
if (GetPackageType(frame->can_id) == SWITCH_TRIGGERED_CAN_ID)
{
uint16_t deviceId = GetDeviceId(frame->can_id);
uint8_t dt = frame->data[1];
uint8_t state = frame->data[0];
rules->Traverse(deviceId, dt, state, CheckRule);
}
}
#include "MeyRule.h"
#include "MeyCan.h"
#include <Arduino.h>
#include <mcp2515.h>;
RemotePinInfo remotePinInfo = RemotePinInfo();
Rule *rules = NULL;
void PutRule(Rule *rule) {
if (rules == NULL)
rules = rule;
else
rules->AddRule(rule);
}
void AddSimple(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId) {
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->target.devId = targetDevId;
rule->target.meyPinId = targetMeyPinId;
rule->target.lastPinState = false;
rule->toggle = false;
rule->inverse = false;
PutRule(rule);
}
void AddToggle(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId) {
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->target.devId = targetDevId;
rule->target.meyPinId = targetMeyPinId;
rule->target.lastPinState = false;
rule->toggle = true;
rule->inverse = false;
PutRule(rule);
}
void AddToggleInverse(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId) {
Rule *rule = new Rule();
rule->sourceDevId = sourceDevId;
rule->sourceMeyPinId = sourceMeyPinId;
rule->target.devId = targetDevId;
rule->target.meyPinId = targetMeyPinId;
rule->target.lastPinState = false;
rule->toggle = true;
rule->inverse = true;
PutRule(rule);
}
void CheckRule(uint16_t deviceId, uint8_t dt, uint8_t state, Rule *rule) {
RemotePinInfo *currentRemotePinInfo = remotePinInfo.FindOrAdd(rule->target.devId);
if (currentRemotePinInfo == NULL) return;
// check the new state with the last one. Needs to be done, as the UP switch might
// send it multiple times like "01 01" "01 01" for a single tip.(antibeat)
bool lastPinState = rule->target.lastPinState;
bool pinState = dt > 0;
if (rule->triggeredOnce && lastPinState == pinState) return;
rule->target.lastPinState = pinState;
rule->triggeredOnce = true;
if (rule->inverse)
pinState = !pinState;
if (rule->toggle)
pinState = (currentRemotePinInfo->getPinState(rule->target.meyPinId) ^ true);
currentRemotePinInfo->setPinState(rule->target.meyPinId, pinState);
BroadcastTriggerMeyPinCanPackage(rule->target.devId, rule->target.meyPinId, pinState);
}
void HandleTriggered(can_frame *frame) {
if (GetPackageType(frame->can_id) == SWITCH_TRIGGERED_CAN_ID) {
RemotePinInfo *currentPinState = remotePinInfo.FindOrAdd(GetDeviceId(frame->can_id));
if (currentPinState == NULL) {
return;
}
currentPinState->setPinState(frame->data[0], frame->data[1]);
}
}
void SetLocalPinState(can_frame *frame)
{
HandleTriggered(frame);
}
void HandleRules(can_frame *frame) {
if (rules != NULL) {
if (GetPackageType(frame->can_id) == SWITCH_TRIGGERED_CAN_ID) {
uint16_t deviceId = GetDeviceId(frame->can_id);
uint8_t dt = frame->data[1];
uint8_t state = frame->data[0];
rules->Traverse(deviceId, dt, state, CheckRule);
}
}
HandleTriggered(frame);
}

View File

@@ -1,113 +1,107 @@
#ifndef MEYRULE_H
#define MEYRULE_H
#include <Arduino.h>
#include <mcp2515.h>;
struct Rule
{
uint16_t sourceDevId;
byte sourceMeyPinId;
uint16_t targetDevId;
byte targetMeyPinId;
bool toggle;
bool inverse;
Rule *nextRule = NULL;
bool lastPinState = false;
bool triggeredOnce = false;
void AddRule(Rule *rule)
{
if (this->nextRule == NULL)
{
this->nextRule = rule;
rule->nextRule = NULL;
} else {
this->nextRule->AddRule(rule);
}
}
void Traverse( uint16_t deviceId, uint8_t dt, uint8_t state, void (*handle)(uint16_t, uint8_t, uint8_t, Rule*))
{
if ( this->sourceDevId == deviceId && this->sourceMeyPinId == state)
handle(deviceId, dt, state, this);
if (this->nextRule != NULL)
this->nextRule->Traverse(deviceId, dt, state, handle);
}
};
typedef struct RemotePinInfo
{
const byte MAX_REMOTE_PIN_COUNT = 64;
uint16_t DeviceId = 0; // the id of the device
uint8_t pinState = 0; // bitmap of 8 MeyPin states of the device. 0000 0100, MeyPin #3 is HIGH in this example
RemotePinInfo *next = NULL;
bool getPinState(byte meyPin)
{
return (this->pinState >> (meyPin - 1)) & 1;
}
void setPinState(byte meyPin, bool state)
{
if (state)
this->pinState = this->pinState | (1 << (meyPin - 1)); // 0001 0000
else
this->pinState = this->pinState & (~(1 << (meyPin - 1))); // 1110 1111 -> not
}
int16_t Count()
{
if (this->next == NULL) return 1;
return this->next->Count() + 1;
}
RemotePinInfo* FindOrAdd(uint16_t deviceId, byte count = 0)
{
if (count > MAX_REMOTE_PIN_COUNT)
return NULL;
if (this->DeviceId == 0 && this->pinState == 0)
{
this->DeviceId = deviceId;
this->pinState = 0;
}
if (this->DeviceId == deviceId)
{
//ToggleDebug();
return this;
}
if (next != NULL)
{
return next->FindOrAdd(deviceId, count + 1);
}
RemotePinInfo *theNext = new RemotePinInfo;
theNext->DeviceId = deviceId;
theNext->pinState = 0;
theNext->next = NULL;
this->next = theNext;
return this->next;
}
};
extern RemotePinInfo remotePinInfo;
extern Rule *rules;
void AddSimple(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void AddToggle(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void AddToggleInverse(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void HandleRules(can_frame *frame);
void PutRule(Rule *rule);
void CheckRule(uint16_t deviceId, uint8_t dt, uint8_t state, Rule *rule);
#endif
#ifndef MEYRULE_H
#define MEYRULE_H
#include <Arduino.h>
#include <mcp2515.h>;
struct TargetPin{
uint16_t devId;
byte meyPinId;
bool lastPinState = false;
};
struct Rule {
uint16_t sourceDevId;
byte sourceMeyPinId;
TargetPin target = TargetPin();
bool toggle;
bool inverse;
Rule *nextRule = NULL;
bool triggeredOnce = false;
void AddRule(Rule *rule) {
if (this->nextRule == NULL) {
this->nextRule = rule;
rule->nextRule = NULL;
} else {
this->nextRule->AddRule(rule);
}
}
void Traverse(uint16_t deviceId, uint8_t dt, uint8_t state, void (*handle)(uint16_t, uint8_t, uint8_t, Rule *)) {
if (this->sourceDevId == deviceId && this->sourceMeyPinId == state)
handle(deviceId, dt, state, this);
if (this->nextRule != NULL)
this->nextRule->Traverse(deviceId, dt, state, handle);
}
};
typedef struct RemotePinInfo {
const byte MAX_REMOTE_PIN_COUNT = 64;
uint16_t DeviceId = 0; // the id of the device
uint8_t pinState = 0; // bitmap of 8 MeyPin states of the device. 0000 0100, MeyPin #3 is HIGH in this example
RemotePinInfo *next = NULL;
bool getPinState(byte meyPin) {
return (this->pinState >> (meyPin - 1)) & 1;
}
void setPinState(byte meyPin, bool state) {
if (state)
this->pinState = this->pinState | (1 << (meyPin - 1)); // 0001 0000
else
this->pinState = this->pinState & (~(1 << (meyPin - 1))); // 1110 1111 -> not
}
int16_t Count() {
if (this->next == NULL) return 1;
return this->next->Count() + 1;
}
RemotePinInfo *FindOrAdd(uint16_t deviceId, byte count = 0) {
if (count > MAX_REMOTE_PIN_COUNT)
return NULL;
if (this->DeviceId == 0 && this->pinState == 0) {
this->DeviceId = deviceId;
this->pinState = 0;
}
if (this->DeviceId == deviceId) {
//ToggleDebug();
return this;
}
if (next != NULL) {
return next->FindOrAdd(deviceId, count + 1);
}
RemotePinInfo *theNext = new RemotePinInfo;
theNext->DeviceId = deviceId;
theNext->pinState = 0;
theNext->next = NULL;
this->next = theNext;
return this->next;
}
};
extern RemotePinInfo remotePinInfo;
extern Rule *rules;
void SetLocalPinState(can_frame *frame);
void AddSimple(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void AddToggle(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void AddToggleInverse(uint16_t sourceDevId, byte sourceMeyPinId, uint16_t targetDevId, byte targetMeyPinId);
void HandleRules(can_frame *frame);
void PutRule(Rule *rule);
void CheckRule(uint16_t deviceId, uint8_t dt, uint8_t state, Rule *rule);
#endif

View File

@@ -1,96 +1,114 @@
#include <SPI.h>;
#include <mcp2515.h>;
#include "MeyCan.h";
#include "MeyRule.h";
const int16_t SW_FLUR = 0XD238;
const int16_t SW_ANBAU = 0x87A9;
const int16_t SW_WOHNZIMMER = 0x87CA;
const int16_t UP_WOHNZIMMER_TUER = 0x051F;
const int16_t UP_WOHNZIMMER_TERASSE = 0x05df;
const int16_t UP_FLUR_EINGANG = 0x0769;
const int16_t UP_BUERO = 0x1177;
const int16_t UP_FLUR_BUERO = 0x05A1;
const int16_t UP_FLUR_KUECHE = 0x01EF;
const int16_t UP_KINDERZIMMER = 0x0196;
const int16_t UP_FLUR_ELTERN = 0x0632;
const int16_t UP_KUECHE_FLUR = 0x07F5;
const int16_t UP_KUECHE_BAD = 0x0585;
struct can_frame incomingCanFrame;
void setup() {
SPI.begin();
// AddToggleInverse(UP_WOHNZIMMER_TUER, 5, SW_WOHNZIMMER, 4); // Lichtschalter Wohnzimmer Licht 1
// AddToggleInverse(UP_WOHNZIMMER_TUER, 5, SW_WOHNZIMMER, 3); // Lichtschalter Wohnzimmer Licht 2
// AddToggle(UP_WOHNZIMMER_TERASSE, 1, SW_WOHNZIMMER, 4); // Licht 1 von Terassenschalter
// AddToggle(UP_WOHNZIMMER_TERASSE, 1, SW_WOHNZIMMER, 3); // Licht 2 von Terassenschalter
//
// AddToggle(0x0769, 1, SW_WOHNZIMMER, 7); // Eingangstür Flur Licht 2
// AddToggle(0x0769, 1, SW_FLUR, 1); //Eingangstür Flur Licht 1
//
// AddToggle(UP_WOHNZIMMER_TUER, 3, SW_WOHNZIMMER, 1); // Licht 1 Wochzimmer Eingangstür
// AddToggle(UP_WOHNZIMMER_TUER, 4, SW_WOHNZIMMER, 2); // Licht 2 Wochzimmer Eingangstür
//
// AddToggle(0x1177, 1, SW_WOHNZIMMER, 6); // Licht Papa Büro
// AddToggle(0x05A1, 1, SW_WOHNZIMMER, 7); // Flurlicht von Papas Büro
// AddToggle(0x05A1, 1, SW_FLUR, 1); // Flurlicht von Papas Büro
// AddToggle(0x01EF, 1, SW_WOHNZIMMER, 7); // Flurlicht von Papas Büro
// AddToggle(0x01EF, 1, SW_FLUR, 1); // Flurlicht von Papas Büro
// AddToggle(0x0196, 3, SW_WOHNZIMMER, 7); // Flurlicht von Papas Büro
// AddToggle(0x0196, 3, SW_FLUR, 1); // Flurlicht von Papas Büro
// AddToggle(0x0632, 1, SW_FLUR, 5); // Flurlicht von Papas Büro
//
// AddToggle(UP_WOHNZIMMER_TUER, 2, SW_FLUR, 2); // Linus Zimmer hoch aus Wohnzimmer
// AddToggle(UP_WOHNZIMMER_TUER, 1, SW_FLUR, 3); // Linus Zimmer runter hoch aus Wohnzimmer
//
// AddToggle(0x0769, 2, SW_FLUR, 4); // Linus Zimmer runter hoch aus Wohnzimmer
//
//
// AddToggle(UP_KUECHE_FLUR, 1, SW_ANBAU, 2);
// AddToggle(UP_KUECHE_FLUR, 2, SW_ANBAU, 3);
// AddToggle(UP_KUECHE_BAD, 1, SW_ANBAU, 2);
// AddToggle(UP_KUECHE_BAD, 3, SW_ANBAU, 1);
// AddToggle(UP_KUECHE_BAD, 2, SW_ANBAU, 4);
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL.MCLKCTRLA | 1 << 7);
delay(10); // a bit delay for mcp2515 to get the clock
SetMeyPin(0, 1, PIN_PC7);
SetMeyPin(1, 2, PIN_PC6);
SetMeyPin(2, 3, PIN_PC5);
SetMeyPin(3, 4, PIN_PC4);
SetMeyPin(4, 5, PIN_PC3);
SetMeyPin(5, 6, PIN_PC2);
SetMeyPin(6, 7, PIN_PC1);
SetMeyPin(7, 8, PIN_PC0);
AddCanInterface(PIN_PA2);
AddCanInterface(PIN_PA3);
AddCanInterface(PIN_PB0);
AddCanInterface(PIN_PB1);
SetupMeyCan(7, 0, 1);
}
void loop()
{
ForEachCanInterface(CheckCanInterface);
}
void CheckCanInterface(MCP2515 *interface)
{
if (interface->readMessage(&incomingCanFrame) == MCP2515::ERROR_OK)
{
HandleFrame(&incomingCanFrame, interface);
HandleRules(&incomingCanFrame);
}
}
#include <SPI.h>;
#include <mcp2515.h>;
#include "MeyCan.h";
#include "MeyRule.h";
#define PIN8 8
#define PIN9 9
const int16_t SW_FLUR = 0XD238;
const int16_t SW_ANBAU = 0x87A9;
const int16_t SW_WOHNZIMMER = 0x87CA;
const int16_t SW_TERRASSE = 0x618A;
const int16_t UP_WOHNZIMMER_TUER = 0x051F; // [X X]
const int16_t UP_WOHNZIMMER_TERASSE = 0x05df;
const int16_t UP_FLUR_EINGANG = 0x0769; // [X]
const int16_t UP_BUERO = 0x1177;
const int16_t UP_FLUR_BUERO = 0x05A1; // [X]
const int16_t UP_FLUR_KUECHE = 0x01EF;
const int16_t UP_KINDERZIMMER = 0x0196; // [X X]
const int16_t UP_FLUR_ELTERN = 0x0632;
const int16_t UP_ELTERN = 0x08AE;
const int16_t UP_KUECHE_FLUR = 0x07F5; // [X]
const int16_t UP_KUECHE_BAD = 0x0585; // [X X]
struct can_frame incomingCanFrame;
/*
Software matching Hardware of meycan v8.1
*/
void setup() {
SPI.begin();
AddToggle(UP_WOHNZIMMER_TUER, 1, SW_WOHNZIMMER, 5);
AddToggle(UP_WOHNZIMMER_TUER, 1, SW_WOHNZIMMER, 6);
AddSimple(UP_WOHNZIMMER_TUER, 2, SW_WOHNZIMMER, 7);
AddSimple(UP_WOHNZIMMER_TUER, 3, SW_WOHNZIMMER, 8);
AddToggle(UP_KINDERZIMMER, 3, SW_FLUR, 6);
AddToggle(UP_KINDERZIMMER, 3, SW_WOHNZIMMER, 2);
AddToggle(UP_KINDERZIMMER, 2, SW_FLUR, 3);
AddSimple(UP_KINDERZIMMER, 4, SW_FLUR, 4);
AddSimple(UP_KINDERZIMMER, 1, SW_FLUR, 5);
AddToggle(UP_FLUR_EINGANG, 1, SW_FLUR, 1);
AddToggle(UP_FLUR_EINGANG, 2, SW_FLUR, 6);
AddToggle(UP_FLUR_EINGANG, 2, SW_WOHNZIMMER, 2);
AddToggle(UP_ELTERN, 1, SW_FLUR, 2);
AddToggle(UP_BUERO, 1, SW_WOHNZIMMER, 3);
AddToggle(UP_FLUR_BUERO, 1, SW_FLUR, 6);
AddToggle(UP_FLUR_BUERO, 1, SW_WOHNZIMMER, 2);
AddToggle (UP_WOHNZIMMER_TERASSE, 1, SW_WOHNZIMMER, 7); // Licht 1 von Terassenschalter
AddToggle (UP_WOHNZIMMER_TERASSE, 2, SW_WOHNZIMMER, 8); // Licht
AddToggle (UP_WOHNZIMMER_TERASSE, 3, SW_TERRASSE, 2); // Pergola
/// RULE FOR SWITCH WOHNZIMMER (BOTH) OF TERASSE
// AddSimple (UP_WOHNZIMMER_TERASSE, 3, SW_WOHNZIMMER, 5); // Eingangstür Flur Licht 2
// AddSimple (UP_WOHNZIMMER_TERASSE, 3, SW_WOHNZIMMER, 6); // Eingangstür Flur Licht 2
AddToggle(UP_KUECHE_FLUR, 1, SW_ANBAU, 3);
AddToggle(UP_KUECHE_FLUR, 2, SW_ANBAU, 2);
AddToggle(UP_KUECHE_BAD, 1, SW_ANBAU, 3);
AddToggle(UP_KUECHE_BAD, 2, SW_ANBAU, 1);
AddToggle(UP_KUECHE_BAD, 3, SW_ANBAU, 4);
AddToggle(UP_FLUR_KUECHE, 1, SW_FLUR, 6);
AddToggle(UP_FLUR_KUECHE, 1, SW_WOHNZIMMER, 2);
SetMeyPin(1, PIN3);
SetMeyPin(2, PIN5);
SetMeyPin(3, PIN7);
SetMeyPin(4, PIN9);
SetMeyPin(5, PIN8);
SetMeyPin(6, PIN6);
SetMeyPin(7, PIN4);
SetMeyPin(8, PIN2);
SetDevicedId(0x87, 0xCA);
AddLocalPinChangedHandler(SetLocalPinStateAdapter);
AddCanInterface(PIN_A0);
AddCanInterface(PIN_A1);
AddCanInterface(PIN_A2);
AddCanInterface(PIN_A3);
SetupMeyCan(8, 0, 2);
}
void loop() {
ForEachCanInterface(CheckCanInterface);
}
void SetLocalPinStateAdapter(can_frame *frame)
{
SetLocalPinState(frame);
}
void CheckCanInterface(MCP2515 *interface) {
if (interface->readMessage(&incomingCanFrame) == MCP2515::ERROR_OK) {
HandleFrame(&incomingCanFrame, interface);
HandleRules(&incomingCanFrame);
}
}