From ee72a23617253589013ed5c4a8b8a7cb4bd5f405 Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Mon, 2 Dec 2019 15:39:09 +0100 Subject: [PATCH] save work --- src/knx/cemi_frame.h | 2 +- src/knx/cemi_server.cpp | 32 +++++++++++++++++++++++++ src/knx/data_link_layer.cpp | 29 ++++------------------ src/knx/rf_data_link_layer.cpp | 44 +++++++++++++++++++++------------- 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/knx/cemi_frame.h b/src/knx/cemi_frame.h index 49e80b8..80052d2 100644 --- a/src/knx/cemi_frame.h +++ b/src/knx/cemi_frame.h @@ -80,7 +80,7 @@ class CemiFrame APDU _apdu; uint16_t _length = 0; // only set if created from byte array - // nly for RF medium + // only for RF medium uint8_t* _rfSerialOrDoA = 0; uint8_t _rfInfo = 0; uint8_t _rfLfn = 0; // RF Data Link layer frame number diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index 655d468..27e175a 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -94,6 +94,38 @@ void CemiServer::frameReceived(CemiFrame& frame) frame.sourceAddress(_clientAddress); } +#if MEDIUM_TYPE == 2 + // Check if we have additional info for RF + + uint8_t rfSerialOrDoA[6]; + uint8_t rfLfn; + + if (((frame.data())[1] == 0x0A) && // Additional info total length: we only handle one additional info of type RF + ((frame.data())[2] == 0x02) && // Additional info type: RF + ((frame.data())[3] == 0x08) ) // Additional info length of type RF: 8 bytes (fixed) + { + // Use the values provided in the RF additonal info + memcpy(&rfSerialOrDoA, &((frame.data())[5]), 6); + rfLfn = (frame.data())[11]; + } + else + { + // Let the RF data link layer fill in its own values + memset(&rfSerialOrDoA, 0x00, 6); + rfLfn = 0xFF; + } + + if ( (rfSerialOrDoA[0] == 0x00) && (rfSerialOrDoA[1] == 0x00) && (rfSerialOrDoA[2] == 0x00) && + (rfSerialOrDoA[3] == 0x00) && (rfSerialOrDoA[4] == 0x00) && (rfSerialOrDoA[5] == 0x00) ) + { + frame.rfSerialOrDoA(nullptr); + } + else + { + frame.rfSerialOrDoA(rfSerialOrDoA); + } +#endif + print("L_data_req: src: "); print(frame.sourceAddress(), HEX); print(" dst: "); diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index 92a8d49..bc8b21f 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -19,35 +19,16 @@ void DataLinkLayer::cemiServer(CemiServer& cemiServer) void DataLinkLayer::dataRequestFromTunnel(CemiFrame& frame) { - uint16_t destination = frame.destinationAddress(); - uint16_t ownAddr = _deviceObject.induvidualAddress(); - AddressType addrType = frame.addressType(); - frame.messageCode(L_data_con); _cemiServer->dataConfirmationToTunnel(frame); frame.messageCode(L_data_ind); + + // Send to local stack + frameRecieved(frame); - if (addrType == InduvidualAddress) - { - if (destination == ownAddr) - { - // Send to local stack only - frameRecieved(frame); - } - else // TODO: check if this is correct: shall we send a frame to the bus too if it was intended for us? - { - // Send to KNX medium only - sendFrame(frame); - } - } - else // GroupAddress - { - // Send to local stack - frameRecieved(frame); - // Send to KNX medium - sendFrame(frame); - } + // Send to KNX medium + sendFrame(frame); } void DataLinkLayer::dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, Priority priority, NPDU& npdu) diff --git a/src/knx/rf_data_link_layer.cpp b/src/knx/rf_data_link_layer.cpp index 699c56e..749fdfa 100644 --- a/src/knx/rf_data_link_layer.cpp +++ b/src/knx/rf_data_link_layer.cpp @@ -29,27 +29,37 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame) return false; } - // Depending on this flag, use either KNX Serial Number - // or the RF domain address that was programmed by ETS - if (frame.systemBroadcast() == SysBroadcast) + // If no serial number of domain address was set, + // use our own SN/DoA + if (frame.rfSerialOrDoA() == nullptr) { - uint8_t knxSerialNumber[6]; - pushWord(_deviceObject.manufacturerId(), &knxSerialNumber[0]); - pushInt(_deviceObject.bauNumber(), &knxSerialNumber[2]); - frame.rfSerialOrDoA(&knxSerialNumber[0]); - } - else - { - frame.rfSerialOrDoA(_rfMediumObj.rfDomainAddress()); + // Depending on this flag, use either KNX Serial Number + // or the RF domain address that was programmed by ETS + if (frame.systemBroadcast() == SysBroadcast) + { + uint8_t knxSerialNumber[6]; + pushWord(_deviceObject.manufacturerId(), &knxSerialNumber[0]); + pushInt(_deviceObject.bauNumber(), &knxSerialNumber[2]); + frame.rfSerialOrDoA(&knxSerialNumber[0]); + } + else + { + frame.rfSerialOrDoA(_rfMediumObj.rfDomainAddress()); + } } - // Set Data Link Layer Frame Number - frame.rfLfn(_frameNumber); - // Link Layer frame number counts 0..7 - _frameNumber = (_frameNumber + 1) & 0x7; + // If Link Layer frame is set to 0xFF, + // use our own counter + if (frame.rfLfn() == 0xFF) + { + // Set Data Link Layer Frame Number + frame.rfLfn(_frameNumber); + // Link Layer frame number counts 0..7 + _frameNumber = (_frameNumber + 1) & 0x7; + } // bidirectional device, battery is ok, signal strength indication is void (no measurement) - frame.rfInfo(0x02); + frame.rfInfo(0x02); // TODO: Is queueing really required? // According to the spec. the upper layer may only send a new L_Data.req if it received @@ -321,8 +331,8 @@ void RfDataLinkLayer::addFrameTxQueue(CemiFrame& frame) tx_frame->next = NULL; // Prepare the raw RF frame - fillRfFrame(frame, tx_frame->data); /* + fillRfFrame(frame, tx_frame->data); print("TX LFN: "); print(frame.rfLfn());