mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
- refactor data-link layer
- add dummy tp-uart dl - add bau07b0 (copy of bau57B0; refactoring needed)
This commit is contained in:
parent
3f0016a0bd
commit
b0b6336899
303
bau07B0.cpp
Normal file
303
bau07B0.cpp
Normal 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
75
bau07B0.h
Normal 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;
|
||||||
|
|
||||||
|
};
|
@ -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
3
bits.h
@ -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>
|
||||||
|
@ -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();
|
||||||
@ -134,7 +37,7 @@ void DataLinkLayer::loop()
|
|||||||
|
|
||||||
if (source == ownAddr)
|
if (source == ownAddr)
|
||||||
_deviceObject.induvidualAddressDuplication(true);
|
_deviceObject.induvidualAddressDuplication(true);
|
||||||
|
|
||||||
if (addrType == GroupAddress && destination == 0)
|
if (addrType == GroupAddress && destination == 0)
|
||||||
_networkLayer.systemBroadcastIndication(ack, type, npdu, priority, source);
|
_networkLayer.systemBroadcastIndication(ack, type, npdu, priority, source);
|
||||||
else
|
else
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
102
ip_data_link_layer.cpp
Normal 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
23
ip_data_link_layer.h
Normal 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;
|
||||||
|
};
|
74
tpuart_data_link_layer.cpp
Normal file
74
tpuart_data_link_layer.cpp
Normal 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
20
tpuart_data_link_layer.h
Normal 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);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user