- refactor data-link layer

- add dummy tp-uart dl
- add bau07b0 (copy of bau57B0; refactoring needed)
This commit is contained in:
Thomas Kunze 2018-06-05 00:32:26 +02:00
parent 3f0016a0bd
commit b0b6336899
10 changed files with 646 additions and 154 deletions

303
bau07B0.cpp Normal file
View File

@ -0,0 +1,303 @@
#include "bau07B0.h"
#include <string.h>
#include <stdio.h>
using namespace std;
Bau07B0::Bau07B0(Platform& platform): _memoryReference((uint8_t*)&_deviceObj), _memory(platform), _addrTable(_memoryReference),
_assocTable(_memoryReference), _groupObjTable(_memoryReference), _appProgram(_memoryReference),
_platform(platform), _appLayer(_assocTable, *this),
_transLayer(_appLayer, _addrTable, _platform), _netLayer(_transLayer),
_dlLayer(_deviceObj, _addrTable, _netLayer, _platform)
{
_appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer);
_netLayer.dataLinkLayer(_dlLayer);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_appProgram);
_memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable);
}
void Bau07B0::loop()
{
_dlLayer.loop();
_transLayer.loop();
sendNextGroupTelegram();
}
void Bau07B0::sendNextGroupTelegram()
{
static uint16_t startIdx = 1;
GroupObjectTableObject& table = _groupObjTable;
uint16_t objCount = table.entryCount();
for (uint16_t asap = startIdx; asap < objCount; asap++)
{
GroupObject& go = table.get(asap);
ComFlag flag = go.commFlag();
if (flag != ReadRequest && flag != WriteRequest)
continue;
if(!go.communicationEnable() || ! go.transmitEnable())
continue;
if (flag == WriteRequest)
{
uint8_t* data = go.valueRef();
_appLayer.groupValueWriteRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, data,
go.sizeInTelegram());
}
else
{
_appLayer.groupValueReadRequest(AckRequested, asap, go.priority(), NetworkLayerParameter);
}
go.commFlag(Transmitting);
startIdx = asap + 1;
return;
}
startIdx = 1;
}
void Bau07B0::updateGroupObject(GroupObject & go, uint8_t * data, uint8_t length)
{
uint8_t* goData = go.valueRef();
if (length != go.valueSize())
{
go.commFlag(Error);
return;
}
memcpy(goData, data, length);
go.commFlag(cfUpdate);
if (go.updateHandler)
go.updateHandler(go);
}
void Bau07B0::readMemory()
{
_memory.readMemory();
}
DeviceObject& Bau07B0::deviceObject()
{
return _deviceObj;
}
GroupObjectTableObject& Bau07B0::groupObjectTable()
{
return _groupObjTable;
}
ApplicationProgramObject& Bau07B0::parameters()
{
return _appProgram;
}
bool Bau07B0::configured()
{
return _groupObjTable.loadState() == LS_LOADED
&& _addrTable.loadState() == LS_LOADED
&& _assocTable.loadState() == LS_LOADED
&& _appProgram.loadState() == LS_LOADED;
}
bool Bau07B0::enabled()
{
return _dlLayer.enabled();
}
void Bau07B0::enabled(bool value)
{
_dlLayer.enabled(value);
}
void Bau07B0::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress, uint8_t * data)
{
memcpy(_memoryReference + memoryAddress, data, number);
_memory.memoryModified();
if (_deviceObj.verifyMode())
memoryReadIndication(priority, hopType, asap, number, memoryAddress);
}
void Bau07B0::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress)
{
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_memoryReference + memoryAddress);
}
void Bau07B0::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType)
{
if (descriptorType != 0)
descriptorType = 0x3f;
uint8_t descriptor[] = { 0x07, 0xb0 };
_appLayer.deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, descriptorType, descriptor);
}
void Bau07B0::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
{
// for platforms that don't really restart
_deviceObj.progMode(false);
// Flush the EEPROM before resetting
_memory.writeMemory();
_platform.restart();
}
void Bau07B0::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key)
{
_appLayer.authorizeResponse(AckRequested, priority, hopType, asap, 0);
}
void Bau07B0::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
{
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_memoryReference + memoryAddress);
}
void Bau07B0::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
memcpy(_memoryReference + memoryAddress, data, number);
_memory.memoryModified();
if (_deviceObj.verifyMode())
userMemoryReadIndication(priority, hopType, asap, number, memoryAddress);
}
void Bau07B0::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t propertyIndex)
{
uint8_t pid = propertyId;
bool writeEnable = false;
uint8_t type = 0;
uint16_t numberOfElements = 0;
uint8_t access = 0;
InterfaceObject* obj = getInterfaceObject(objectIndex);
if (obj)
obj->readPropertyDescription(pid, propertyIndex, writeEnable, type, numberOfElements, access);
_appLayer.propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, objectIndex, pid, propertyIndex,
writeEnable, type, numberOfElements, access);
}
void Bau07B0::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
{
InterfaceObject* obj = getInterfaceObject(objectIndex);
if(obj)
obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, numberOfElements, startIndex);
}
void Bau07B0::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{
uint8_t size = 0;
uint32_t elementCount = numberOfElements;
InterfaceObject* obj = getInterfaceObject(objectIndex);
if (obj)
{
uint8_t elementSize = obj->propertySize((PropertyID)propertyId);
size = elementSize * numberOfElements;
}
else
elementCount = 0;
uint8_t data[size];
if(obj)
obj->readProperty((PropertyID)propertyId, startIndex, elementCount, data);
_appLayer.propertyValueReadResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, elementCount,
startIndex, data, size);
}
void Bau07B0::individualAddressReadIndication(HopCountType hopType)
{
if (_deviceObj.progMode())
_appLayer.individualAddressReadResponse(AckRequested, hopType);
}
void Bau07B0::individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress)
{
if (_deviceObj.progMode())
_deviceObj.induvidualAddress(newaddress);
}
void Bau07B0::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t * data, uint8_t dataLength, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void Bau07B0::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void Bau07B0::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType)
{
GroupObject& go = _groupObjTable.get(asap);
uint8_t* data = go.valueRef();
_appLayer.groupValueReadResponse(AckRequested, asap, priority, hopType, data, go.sizeInTelegram());
}
void Bau07B0::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data,
uint8_t dataLength)
{
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.responseUpdateEnable())
return;
updateGroupObject(go, data, dataLength);
}
void Bau07B0::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, uint8_t * data, uint8_t dataLength)
{
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.writeEnable())
return;
updateGroupObject(go, data, dataLength);
}
InterfaceObject* Bau07B0::getInterfaceObject(uint8_t idx)
{
switch (idx)
{
case 0:
return &_deviceObj;
case 1:
return &_addrTable;
case 2:
return &_assocTable;
case 3:
return &_groupObjTable;
case 4:
return &_appProgram;
case 5: // would be app_program 2
return nullptr;
default:
return nullptr;
}
}

75
bau07B0.h Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#include "bau.h"
#include "device_object.h"
#include "address_table_object.h"
#include "association_table_object.h"
#include "group_object_table_object.h"
#include "application_program_object.h"
#include "application_layer.h"
#include "transport_layer.h"
#include "network_layer.h"
#include "tpuart_data_link_layer.h"
#include "platform.h"
#include "memory.h"
class Bau07B0: protected BusAccessUnit
{
using BusAccessUnit::memoryReadIndication;
public:
Bau07B0(Platform& platform);
void loop();
DeviceObject& deviceObject();
GroupObjectTableObject& groupObjectTable();
ApplicationProgramObject& parameters();
bool configured();
bool enabled();
void enabled(bool value);
void readMemory();
protected:
void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress, uint8_t* data) override;
void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress) override;
void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType);
void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap);
void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key);
void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress);
void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData);
void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t propertyIndex);
void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex);
void individualAddressReadIndication(HopCountType hopType);
void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress);
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType,
uint8_t* data, uint8_t dataLength, bool status);
void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status);
void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType);
void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType,
uint8_t* data, uint8_t dataLength);
void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType,
uint8_t* data, uint8_t dataLength);
InterfaceObject* getInterfaceObject(uint8_t idx);
void sendNextGroupTelegram();
void updateGroupObject(GroupObject& go, uint8_t* data, uint8_t length);
private:
DeviceObject _deviceObj;
// pointer to first private variable as reference to memory read/write commands
uint8_t* _memoryReference;
Memory _memory;
AddressTableObject _addrTable;
AssociationTableObject _assocTable;
GroupObjectTableObject _groupObjTable;
ApplicationProgramObject _appProgram;
Platform& _platform;
ApplicationLayer _appLayer;
TransportLayer _transLayer;
NetworkLayer _netLayer;
TpUartDataLinkLayer _dlLayer;
};

View File

@ -10,7 +10,7 @@
#include "application_layer.h" #include "application_layer.h"
#include "transport_layer.h" #include "transport_layer.h"
#include "network_layer.h" #include "network_layer.h"
#include "data_link_layer.h" #include "ip_data_link_layer.h"
#include "platform.h" #include "platform.h"
#include "memory.h" #include "memory.h"
@ -72,6 +72,6 @@ private:
ApplicationLayer _appLayer; ApplicationLayer _appLayer;
TransportLayer _transLayer; TransportLayer _transLayer;
NetworkLayer _netLayer; NetworkLayer _netLayer;
DataLinkLayer _dlLayer; IpDataLinkLayer _dlLayer;
}; };

3
bits.h
View File

@ -16,7 +16,8 @@
((x)>> 8 & 0x0000FF00UL) | \ ((x)>> 8 & 0x0000FF00UL) | \
((x)>>24 & 0x000000FFUL) ) ((x)>>24 & 0x000000FFUL) )
#define ntohl(x) htonl(x) #define ntohl(x) htonl(x)
#define printf #define println SerialUSB.println
#define print SerialUSB.print
#else #else
#include <Arduino.h> #include <Arduino.h>
#include <user_interface.h> #include <user_interface.h>

View File

@ -1,128 +1,31 @@
/*
* bus.cpp - Low level EIB bus access.
*
* Copyright (c) 2014 Stefan Taferner <stefan.taferner@gmx.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*/
#include "data_link_layer.h" #include "data_link_layer.h"
#include "bits.h" #include "bits.h"
#include "platform.h" #include "platform.h"
#include "device_object.h" #include "device_object.h"
#include "address_table_object.h" #include "address_table_object.h"
#include "cemi_frame.h"
#include <stdio.h>
#include <string.h>
#define KNXIP_HEADER_LEN 0x6 DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
#define KNXIP_PROTOCOL_VERSION 0x10
#define ROUTING_INDICATION 0x0530
#define KNXIP_MULTICAST_PORT 3671
#define MIN_LEN_CEMI 10
#ifdef DUMP_TELEGRAMS
unsigned char telBuffer[32];
uint32_t telLength = 0;
#endif
DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam,
NetworkLayer& layer, Platform& platform) : NetworkLayer& layer, Platform& platform) :
_deviceObject(devObj), _groupAddressTable(addrTab), _ipParameters(ipParam), _networkLayer(layer), _platform(platform) _deviceObject(devObj), _groupAddressTable(addrTab), _networkLayer(layer), _platform(platform)
{ {
} }
void DataLinkLayer::dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, Priority priority, NPDU& npdu) void DataLinkLayer::dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, Priority priority, NPDU& npdu)
{ {
bool success = sendPacket(npdu, ack, destinationAddr, addrType, format, priority); bool success = sendTelegram(npdu, ack, destinationAddr, addrType, format, priority);
_networkLayer.dataConfirm(ack, addrType, destinationAddr, format, priority, npdu.frame().sourceAddress(), npdu, success); _networkLayer.dataConfirm(ack, addrType, destinationAddr, format, priority, npdu.frame().sourceAddress(), npdu, success);
} }
void DataLinkLayer::systemBroadcastRequest(AckType ack, FrameFormat format, Priority priority, NPDU& npdu) void DataLinkLayer::systemBroadcastRequest(AckType ack, FrameFormat format, Priority priority, NPDU& npdu)
{ {
bool success = sendPacket(npdu, ack, 0, GroupAddress, format, priority); bool success = sendTelegram(npdu, ack, 0, GroupAddress, format, priority);
_networkLayer.systemBroadcastConfirm(ack, format, priority, npdu.frame().sourceAddress(), npdu, success); _networkLayer.systemBroadcastConfirm(ack, format, priority, npdu.frame().sourceAddress(), npdu, success);
} }
bool DataLinkLayer::sendPacket(NPDU &npdu, AckType ack, uint16_t destinationAddr, AddressType addrType, FrameFormat format, Priority priority) void DataLinkLayer::frameRecieved(CemiFrame & frame)
{ {
CemiFrame& frame = npdu.frame();
frame.messageCode(L_data_ind);
frame.destinationAddress(destinationAddr);
frame.sourceAddress(_deviceObject.induvidualAddress());
frame.addressType(addrType);
frame.priority(priority);
frame.repetition(RepititionAllowed);
if (npdu.octetCount() <= 15)
frame.frameType(StandardFrame);
else
frame.frameType(format);
if (!frame.valid())
{
printf("invalid frame\n");
return false;
}
//if (frame.npdu().octetCount() > 0)
//{
// print.print("-> DLL ");
// frame.apdu().printPDU();
//}
uint16_t length = frame.totalLenght() + KNXIP_HEADER_LEN;
uint8_t* buffer = new uint8_t[length];
buffer[0] = KNXIP_HEADER_LEN;
buffer[1] = KNXIP_PROTOCOL_VERSION;
pushWord(ROUTING_INDICATION, buffer + 2);
pushWord(length, buffer + 4);
memcpy(buffer + KNXIP_HEADER_LEN, frame._data, frame.totalLenght());
bool success = sendBytes(buffer, length);
// only send 50 packet per second: see KNX 3.2.6 p.6
_platform.mdelay(20);
delete[] buffer;
return success;
}
void DataLinkLayer::loop()
{
if (!_enabled)
return;
uint8_t buffer[512];
int len = _platform.readBytes(buffer, 512);
if (len <= 0)
return;
if (len < KNXIP_HEADER_LEN)
return;
if (buffer[0] != KNXIP_HEADER_LEN
|| buffer[1] != KNXIP_PROTOCOL_VERSION)
return;
uint16_t code;
popWord(code, buffer + 2);
if (code != ROUTING_INDICATION) // only routing indication for now
return;
if (len < MIN_LEN_CEMI)
return;
//TODO: Check correct length (additions Info + apdu length)
CemiFrame frame(buffer + KNXIP_HEADER_LEN, len - KNXIP_HEADER_LEN);
AckType ack = frame.ack(); AckType ack = frame.ack();
AddressType addrType = frame.addressType(); AddressType addrType = frame.addressType();
uint16_t destination = frame.destinationAddress(); uint16_t destination = frame.destinationAddress();
@ -155,45 +58,38 @@ void DataLinkLayer::loop()
} }
} }
void DataLinkLayer::enabled(bool value) bool DataLinkLayer::sendTelegram(NPDU & npdu, AckType ack, uint16_t destinationAddr, AddressType addrType, FrameFormat format, Priority priority)
{ {
if (value && !_enabled) CemiFrame& frame = npdu.frame();
frame.messageCode(L_data_ind);
frame.destinationAddress(destinationAddr);
frame.sourceAddress(_deviceObject.induvidualAddress());
frame.addressType(addrType);
frame.priority(priority);
frame.repetition(RepititionAllowed);
if (npdu.octetCount() <= 15)
frame.frameType(StandardFrame);
else
frame.frameType(format);
if (!frame.valid())
{ {
_platform.setupMultiCast(_ipParameters.multicastAddress(), KNXIP_MULTICAST_PORT); println("invalid frame\n");
_enabled = true;
return;
}
if(!value && _enabled)
{
_platform.closeMultiCast();
_enabled = false;
return;
}
}
bool DataLinkLayer::enabled() const
{
return _enabled;
}
bool DataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
{
if (!_enabled)
return false; return false;
#ifdef DUMP_TELEGRAMS_
{
print.print("QSD: ");
for (uint32_t i = 0; i <= length; ++i)
{
if (i) print.print(" ");
print.print(bytes[i], HEX, 2);
} }
print.println();
}
#endif
return _platform.sendBytes(bytes, length); //if (frame.npdu().octetCount() > 0)
//{
// print.print("-> DLL ");
// frame.apdu().printPDU();
//}
return sendFrame(frame);
}
uint8_t* DataLinkLayer::frameData(CemiFrame& frame)
{
return frame._data;
} }

View File

@ -3,31 +3,29 @@
#include <stdint.h> #include <stdint.h>
#include "device_object.h" #include "device_object.h"
#include "address_table_object.h" #include "address_table_object.h"
#include "ip_parameter_object.h"
#include "knx_types.h" #include "knx_types.h"
#include "network_layer.h" #include "network_layer.h"
class DataLinkLayer class DataLinkLayer
{ {
public: public:
DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam, NetworkLayer& layer, DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer,
Platform& platform); Platform& platform);
// from network layer // from network layer
void dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, void dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format,
Priority priority, NPDU& npdu); Priority priority, NPDU& npdu);
void systemBroadcastRequest(AckType ack, FrameFormat format, Priority priority, NPDU& npdu); void systemBroadcastRequest(AckType ack, FrameFormat format, Priority priority, NPDU& npdu);
void loop(); virtual void loop() = 0;
void enabled(bool value); virtual void enabled(bool value) = 0;
bool enabled() const; virtual bool enabled() const = 0;
private: protected:
bool _enabled = false; void frameRecieved(CemiFrame& frame);
bool sendPacket(NPDU &npdu, AckType ack, uint16_t destinationAddr, AddressType addrType, FrameFormat format, Priority priority); bool sendTelegram(NPDU &npdu, AckType ack, uint16_t destinationAddr, AddressType addrType, FrameFormat format, Priority priority);
bool sendBytes(uint8_t* buffer, uint16_t length); virtual bool sendFrame(CemiFrame& frame) = 0;
uint8_t* frameData(CemiFrame& frame);
DeviceObject& _deviceObject; DeviceObject& _deviceObject;
AddressTableObject& _groupAddressTable; AddressTableObject& _groupAddressTable;
IpParameterObject& _ipParameters;
NetworkLayer& _networkLayer; NetworkLayer& _networkLayer;
Platform& _platform; Platform& _platform;
}; };

102
ip_data_link_layer.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "ip_data_link_layer.h"
#include "bits.h"
#include "platform.h"
#include "device_object.h"
#include "address_table_object.h"
#include "cemi_frame.h"
#include <stdio.h>
#include <string.h>
#define KNXIP_HEADER_LEN 0x6
#define KNXIP_PROTOCOL_VERSION 0x10
#define ROUTING_INDICATION 0x0530
#define KNXIP_MULTICAST_PORT 3671
#define MIN_LEN_CEMI 10
IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam,
NetworkLayer& layer, Platform& platform) : DataLinkLayer(devObj, addrTab, layer, platform), _ipParameters(ipParam)
{
}
bool IpDataLinkLayer::sendFrame(CemiFrame& frame)
{
uint16_t length = frame.totalLenght() + KNXIP_HEADER_LEN;
uint8_t* buffer = new uint8_t[length];
buffer[0] = KNXIP_HEADER_LEN;
buffer[1] = KNXIP_PROTOCOL_VERSION;
pushWord(ROUTING_INDICATION, buffer + 2);
pushWord(length, buffer + 4);
memcpy(buffer + KNXIP_HEADER_LEN, frameData(frame), frame.totalLenght());
bool success = sendBytes(buffer, length);
// only send 50 packet per second: see KNX 3.2.6 p.6
_platform.mdelay(20);
delete[] buffer;
return success;
}
void IpDataLinkLayer::loop()
{
if (!_enabled)
return;
uint8_t buffer[512];
int len = _platform.readBytes(buffer, 512);
if (len <= 0)
return;
if (len < KNXIP_HEADER_LEN)
return;
if (buffer[0] != KNXIP_HEADER_LEN
|| buffer[1] != KNXIP_PROTOCOL_VERSION)
return;
uint16_t code;
popWord(code, buffer + 2);
if (code != ROUTING_INDICATION) // only routing indication for now
return;
if (len < MIN_LEN_CEMI)
return;
//TODO: Check correct length (additions Info + apdu length)
CemiFrame frame(buffer + KNXIP_HEADER_LEN, len - KNXIP_HEADER_LEN);
frameRecieved(frame);
}
void IpDataLinkLayer::enabled(bool value)
{
if (value && !_enabled)
{
_platform.setupMultiCast(_ipParameters.multicastAddress(), KNXIP_MULTICAST_PORT);
_enabled = true;
return;
}
if(!value && _enabled)
{
_platform.closeMultiCast();
_enabled = false;
return;
}
}
bool IpDataLinkLayer::enabled() const
{
return _enabled;
}
bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
{
if (!_enabled)
return false;
return _platform.sendBytes(bytes, length);
}

23
ip_data_link_layer.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include "data_link_layer.h"
#include "ip_parameter_object.h"
class IpDataLinkLayer: public DataLinkLayer
{
using DataLinkLayer::_deviceObject;
public:
IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam, NetworkLayer& layer,
Platform& platform);
void loop();
void enabled(bool value);
bool enabled() const;
private:
bool _enabled = false;
bool sendFrame(CemiFrame& frame);
bool sendBytes(uint8_t* buffer, uint16_t length);
IpParameterObject& _ipParameters;
};

View File

@ -0,0 +1,74 @@
#include "tpuart_data_link_layer.h"
#include "bits.h"
#include "platform.h"
#include "device_object.h"
#include "address_table_object.h"
#include "cemi_frame.h"
#include <stdio.h>
#include <string.h>
TpUartDataLinkLayer::TpUartDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
NetworkLayer& layer, Platform& platform) : DataLinkLayer(devObj, addrTab, layer, platform)
{
}
bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame)
{
uint16_t length = frame.totalLenght();
uint8_t* buffer = new uint8_t[length];
//TODO: Create TP standard frame or extended frame from cemi frame into buffer
bool success = sendBytes(buffer, length);
delete[] buffer;
return success;
}
void TpUartDataLinkLayer::loop()
{
if (!_enabled)
return;
uint8_t buffer[512];
int len = 0;
// TODO: implement receiving of frames
CemiFrame frame(buffer, len);
frameRecieved(frame);
}
void TpUartDataLinkLayer::enabled(bool value)
{
if (value && !_enabled)
{
//TODO: implement setup of Serial + TPUART
_enabled = true;
return;
}
if(!value && _enabled)
{
//TODO: implement disable of TPUART
_enabled = false;
return;
}
}
bool TpUartDataLinkLayer::enabled() const
{
return _enabled;
}
bool TpUartDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
{
if (!_enabled)
return false;
//TODO: implement
return false;
}

20
tpuart_data_link_layer.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include "data_link_layer.h"
class TpUartDataLinkLayer: public DataLinkLayer
{
using DataLinkLayer::_deviceObject;
public:
TpUartDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer,
Platform& platform);
void loop();
void enabled(bool value);
bool enabled() const;
private:
bool _enabled = false;
bool sendFrame(CemiFrame& frame);
bool sendBytes(uint8_t* buffer, uint16_t length);
};