#include "MeyCan.h"; #include ; #include ; PinState *MeyPin = NULL; CanInterface *CanBusses = NULL; uint16_t myDeviceId; 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->ForEach(handle); } void SetupMeyCan() { CalculateMyDeviceId(); if (MeyPin != NULL); MeyPin->ForEach(SetupMeyPin); if (CanBusses != NULL) { CanBusses->ForEach(InitCanInterface, NULL); } } void SetCanInterface(byte index, byte pinId) { MCP2515* newCanInterface = new MCP2515(pinId); CanInterface* canInterface = new CanInterface(); 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 = 6; toSend.data[0] = SOFTWARE_VERSION_HIGH; toSend.data[1] = SOFTWARE_VERSION_LOW; toSend.data[2] = HARDWARE_VERSION_HIGH; toSend.data[3] = HARDWARE_VERSION_LOW; toSend.data[4] = (myDeviceId >> 8) & 0xFF; toSend.data[5] = myDeviceId & 0xFF; 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(); }