knx/cemi_frame.cpp
2018-04-09 22:30:23 +02:00

196 lines
3.9 KiB
C++

#include "cemi_frame.h"
#include "bits.h"
#include "string.h"
#include <stdio.h>
CemiFrame::CemiFrame(uint8_t* data, uint16_t length): _npdu(data + NPDU_LPDU_DIFF, *this),
_tpdu(data + TPDU_LPDU_DIFF, *this), _apdu(data + APDU_LPDU_DIFF, *this)
{
_data = data;
_ctrl1 = data + data[1] + 2;
_length = length;
}
CemiFrame::CemiFrame(uint8_t apduLength): _data(buffer),
_npdu(_data + NPDU_LPDU_DIFF, *this), _tpdu(_data + TPDU_LPDU_DIFF, *this), _apdu(_data + APDU_LPDU_DIFF, *this)
{
_ctrl1 = _data + 2;
_length = 0;
memset(_data, 0, apduLength + APDU_LPDU_DIFF);
_ctrl1[0] |= Broadcast;
_npdu.octetCount(apduLength);
}
CemiFrame::CemiFrame(const CemiFrame & other): _data(buffer),
_npdu(_data + NPDU_LPDU_DIFF, *this), _tpdu(_data + TPDU_LPDU_DIFF, *this), _apdu(_data + APDU_LPDU_DIFF, *this)
{
_ctrl1 = _data + 2;
_length = other._length;
memcpy(_data, other._data, other.totalLenght());
}
CemiFrame& CemiFrame::operator=(CemiFrame other)
{
_length = other._length;
_data = buffer;
_ctrl1 = _data + 2;
memcpy(_data, other._data, other.totalLenght());
_npdu._data = _data + NPDU_LPDU_DIFF;
_tpdu._data = _data + TPDU_LPDU_DIFF;
_apdu._data = _data + APDU_LPDU_DIFF;
return *this;
}
MessageCode CemiFrame::messageCode() const
{
return (MessageCode)_data[0];
}
void CemiFrame::messageCode(MessageCode msgCode)
{
_data[0] = msgCode;
}
uint16_t CemiFrame::totalLenght() const
{
uint16_t tmp =
_npdu.length() + NPDU_LPDU_DIFF;
return tmp;
}
FrameFormat CemiFrame::frameType() const
{
return (FrameFormat)(_ctrl1[0] & StandardFrame);
}
void CemiFrame::frameType(FrameFormat type)
{
_ctrl1[0] &= ~StandardFrame;
_ctrl1[0] |= type;
}
Repetition CemiFrame::repetition() const
{
return (Repetition)(_ctrl1[0] & RepititionAllowed);
}
void CemiFrame::repetition(Repetition rep)
{
_ctrl1[0] &= ~RepititionAllowed;
_ctrl1[0] |= rep;
}
SystemBroadcast CemiFrame::systemBroadcast() const
{
return (SystemBroadcast)(_ctrl1[0] & Broadcast);
}
void CemiFrame::systemBroadcast(SystemBroadcast value)
{
_ctrl1[0] &= ~Broadcast;
_ctrl1[0] |= value;
}
Priority CemiFrame::priority() const
{
return (Priority)(_ctrl1[0] & LowPriority);
}
void CemiFrame::priority(Priority value)
{
_ctrl1[0] &= ~LowPriority;
_ctrl1[0] |= value;
}
AckType CemiFrame::ack() const
{
return (AckType)(_ctrl1[0] & AckRequested);
}
void CemiFrame::ack(AckType value)
{
_ctrl1[0] &= ~AckRequested;
_ctrl1[0] |= value;
}
AddressType CemiFrame::addressType() const
{
return (AddressType)(_ctrl1[1] & GroupAddress);
}
void CemiFrame::addressType(AddressType value)
{
_ctrl1[1] &= ~GroupAddress;
_ctrl1[1] |= value;
}
uint8_t CemiFrame::hopCount() const
{
return ((_ctrl1[1] >> 4) & 0x7);
}
void CemiFrame::hopCount(uint8_t value)
{
_ctrl1[1] &= ~(0x7 << 4);
_ctrl1[1] |= ((value & 0x7) << 4);
}
uint16_t CemiFrame::sourceAddress() const
{
uint16_t addr;
popWord(addr, _ctrl1 + 2);
return addr;
}
void CemiFrame::sourceAddress(uint16_t value)
{
pushWord(value, _ctrl1 + 2);
}
uint16_t CemiFrame::destinationAddress() const
{
uint16_t addr;
popWord(addr, _ctrl1 + 4);
return addr;
}
void CemiFrame::destinationAddress(uint16_t value)
{
pushWord(value, _ctrl1 + 4);
}
NPDU& CemiFrame::npdu()
{
return _npdu;
}
TPDU& CemiFrame::tpdu()
{
return _tpdu;
}
APDU& CemiFrame::apdu()
{
return _apdu;
}
bool CemiFrame::valid() const
{
uint8_t addInfoLen = _data[1];
uint8_t apduLen = _data[1 + _data[1] + NPDU_LPDU_DIFF];
if (_length != 0 && _length != (addInfoLen + apduLen + NPDU_LPDU_DIFF + 2))
return false;
if ((_ctrl1[0] & 0x40) > 0 // Bit 6 has do be 0
|| (_ctrl1[1] & 0xF) > 0 // only standard or extended frames
|| _npdu.octetCount() == 0xFF // not allowed
|| (_npdu.octetCount() > 15 && frameType() == StandardFrame)
)
return false;
return true;
}