Save work

This commit is contained in:
nanosonde 2019-11-08 16:06:05 +01:00
parent 8756e683a9
commit 2b9057b6d2
10 changed files with 171 additions and 79 deletions

View File

@ -10,9 +10,18 @@ using namespace std;
Bau27B0::Bau27B0(Platform& platform) Bau27B0::Bau27B0(Platform& platform)
: BauSystemB(platform), : BauSystemB(platform),
_dlLayer(_deviceObj, _rfMediumObj, _addrTable, _netLayer, _platform) _dlLayer(_deviceObj, _rfMediumObj, _addrTable, _netLayer, _platform)
#ifdef USE_USBIF
, _cemiServer(_tunnelInterface, *this)
, _tunnelInterface(_deviceObj, _cemiServer, _platform)
#endif
{ {
_netLayer.dataLinkLayer(_dlLayer); _netLayer.dataLinkLayer(_dlLayer);
_memory.addSaveRestore(&_rfMediumObj); _memory.addSaveRestore(&_rfMediumObj);
#ifdef USE_USBIF
_cemiServer.dataLinkLayer(_dlLayer);
_dlLayer.cemiServer(_cemiServer);
_memory.addSaveRestore(&_cemiServerObject);
#endif
// Set Mask Version in Device Object depending on the BAU // Set Mask Version in Device Object depending on the BAU
uint16_t maskVersion; uint16_t maskVersion;
@ -70,6 +79,18 @@ DataLinkLayer& Bau27B0::dataLinkLayer()
return _dlLayer; return _dlLayer;
} }
void Bau27B0::enabled(bool value)
{
::BauSystemB::enabled(value);
_tunnelInterface.enabled(value);
}
void Bau27B0::loop()
{
::BauSystemB::loop();
_tunnelInterface.loop();
}
void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint8_t* rfDoA, void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint8_t* rfDoA,
uint8_t* knxSerialNumber) uint8_t* knxSerialNumber)
{ {

View File

@ -4,11 +4,18 @@
#include "rf_medium_object.h" #include "rf_medium_object.h"
#include "rf_physical_layer.h" #include "rf_physical_layer.h"
#include "rf_data_link_layer.h" #include "rf_data_link_layer.h"
#ifdef USE_USBIF
#include "usb_data_link_layer.h"
#include "cemi_server.h"
#include "cemi_server_object.h"
#endif
class Bau27B0 : public BauSystemB class Bau27B0 : public BauSystemB
{ {
public: public:
Bau27B0(Platform& platform); Bau27B0(Platform& platform);
void enabled(bool value);
void loop();
protected: protected:
InterfaceObject* getInterfaceObject(uint8_t idx); InterfaceObject* getInterfaceObject(uint8_t idx);
@ -18,6 +25,11 @@ class Bau27B0 : public BauSystemB
private: private:
RfDataLinkLayer _dlLayer; RfDataLinkLayer _dlLayer;
RfMediumObject _rfMediumObj; RfMediumObject _rfMediumObj;
#ifdef USE_USBIF
CemiServer _cemiServer;
UsbDataLinkLayer _tunnelInterface;
CemiServerObject _cemiServerObject;
#endif
uint8_t _descriptor[2] = {0x27, 0xB0}; uint8_t _descriptor[2] = {0x27, 0xB0};
#ifdef USE_USBIF #ifdef USE_USBIF

View File

@ -15,10 +15,6 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platfo
_assocTable(platform), _groupObjTable(platform), _appProgram(platform), _assocTable(platform), _groupObjTable(platform), _appProgram(platform),
_platform(platform), _appLayer(_assocTable, *this), _platform(platform), _appLayer(_assocTable, *this),
_transLayer(_appLayer, _addrTable), _netLayer(_transLayer) _transLayer(_appLayer, _addrTable), _netLayer(_transLayer)
#ifdef USE_USBIF
, _dlLayerUsb(_deviceObj, _addrTable, _netLayer, _platform),
_cemiServer(_dlLayerUsb, *this)
#endif
{ {
_appLayer.transportLayer(_transLayer); _appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer); _transLayer.networkLayer(_netLayer);
@ -27,17 +23,11 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platfo
_memory.addSaveRestore(&_addrTable); _memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable); _memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable); _memory.addSaveRestore(&_groupObjTable);
#ifdef USE_USBIF
_memory.addSaveRestore(&_cemiServerObject);
#endif
} }
void BauSystemB::loop() void BauSystemB::loop()
{ {
dataLinkLayer().loop(); dataLinkLayer().loop();
#ifdef USE_USBIF
_dlLayerUsb.loop();
#endif
_transLayer.loop(); _transLayer.loop();
sendNextGroupTelegram(); sendNextGroupTelegram();
nextRestartState(); nextRestartState();
@ -51,9 +41,6 @@ bool BauSystemB::enabled()
void BauSystemB::enabled(bool value) void BauSystemB::enabled(bool value)
{ {
dataLinkLayer().enabled(value); dataLinkLayer().enabled(value);
#ifdef USE_USBIF
_dlLayerUsb.enabled(value);
#endif
} }
void BauSystemB::sendNextGroupTelegram() void BauSystemB::sendNextGroupTelegram()

View File

@ -12,11 +12,6 @@
#include "tpuart_data_link_layer.h" #include "tpuart_data_link_layer.h"
#include "platform.h" #include "platform.h"
#include "memory.h" #include "memory.h"
#ifdef USE_USBIF
#include "usb_data_link_layer.h"
#include "cemi_server.h"
#include "cemi_server_object.h"
#endif
class BauSystemB : protected BusAccessUnit class BauSystemB : protected BusAccessUnit
{ {
@ -93,9 +88,4 @@ class BauSystemB : protected BusAccessUnit
bool _configured = true; bool _configured = true;
RestartState _restartState = Idle; RestartState _restartState = Idle;
uint32_t _restartDelay = 0; uint32_t _restartDelay = 0;
#ifdef USE_USBIF
UsbDataLinkLayer _dlLayerUsb;
CemiServer _cemiServer;
CemiServerObject _cemiServerObject;
#endif
}; };

View File

@ -6,14 +6,79 @@
#include "bits.h" #include "bits.h"
#include <stdio.h> #include <stdio.h>
CemiServer::CemiServer(UsbDataLinkLayer& dlLayer, BusAccessUnit& bau): CemiServer::CemiServer(UsbDataLinkLayer& tunnelInterface, BusAccessUnit& bau):
_dlLayer(dlLayer), _tunnelInterface(tunnelInterface),
_bau(bau) _bau(bau)
{ {
} }
#pragma region DLL Callbacks void CemiServer::dataLinkLayer(DataLinkLayer& layer)
{
_dataLinkLayer = &layer;
}
void CemiServer::dataIndicationToTunnel(CemiFrame& frame)
{
_tunnelInterface.sendCemiFrame(frame);
}
void CemiServer::frameReceived(CemiFrame& frame)
{
switch(frame.messageCode())
{
case L_data_req:
{
// Send as indication to data link layer
frame.messageCode(L_data_ind);
_dataLinkLayer->dataIndicationFromTunnel(frame);
// Send local reply to tunnel
frame.messageCode(L_data_con);
_tunnelInterface.sendCemiFrame(frame);
break;
}
case M_PropRead_req:
{
break;
}
case M_PropWrite_req:
{
break;
}
case M_FuncPropCommand_req:
{
break;
}
case M_FuncPropStateRead_req:
{
break;
}
case M_Reset_req:
{
break;
}
// we should not receive this: server -> client
case L_data_con:
case L_data_ind:
case M_PropInfo_ind:
case M_PropRead_con:
case M_PropWrite_con:
case M_FuncPropCommand_con:
//case M_FuncPropStateRead_con: // same value as M_FuncPropCommand_con
case M_Reset_ind:
default:
break;
}
_dataLinkLayer->dataIndicationFromTunnel(frame);
}
/*
void CemiServer::propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, void CemiServer::propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{ {
@ -176,3 +241,5 @@ void CemiServer::individualConfirm(AckType ack, HopCountType hopType, Priority p
break; break;
} }
} }
*/

View File

@ -5,6 +5,9 @@
class UsbDataLinkLayer; class UsbDataLinkLayer;
class BusAccessUnit; class BusAccessUnit;
class DataLinkLayer;
class CemiFrame;
/** /**
* This is an implementation of the cEMI server as specified in @cite knx:3/6/3. * This is an implementation of the cEMI server as specified in @cite knx:3/6/3.
* Overview on page 57. * Overview on page 57.
@ -18,18 +21,22 @@ class CemiServer
public: public:
/** /**
* The constructor. * The constructor.
* @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses. * @param tunnelInterface The TunnelInterface of the KNX tunnel (e.g. USB or KNXNET/IP)
* @param bau methods are called here depending of the content of the APDU * @param bau methods are called here depending of the content of the APDU
*/ */
CemiServer(UsbDataLinkLayer& dlLayer, BusAccessUnit& bau); CemiServer(UsbDataLinkLayer& tunnelInterface, BusAccessUnit& bau);
void dataLinkLayer(DataLinkLayer& layer);
// from data link layer // from data link layer
#pragma region Data - Link - Layer - Callbacks // Only L_Data service
void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu); void dataIndicationToTunnel(CemiFrame& frame);
void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
#pragma endregion
#pragma region from bau // From tunnel interface
void frameReceived(CemiFrame& frame);
/*
void propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, void propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex); uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex);
void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
@ -41,15 +48,16 @@ class CemiServer
void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type,
uint16_t maxNumberOfElements, uint8_t access); uint16_t maxNumberOfElements, uint8_t access);
#pragma endregion */
private: private:
/*
void propertyDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, void propertyDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data,
uint8_t length); uint8_t length);
void individualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu); void individualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status); void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
*/
UsbDataLinkLayer& _dlLayer; DataLinkLayer* _dataLinkLayer;
UsbDataLinkLayer& _tunnelInterface;
BusAccessUnit& _bau; BusAccessUnit& _bau;
}; };

View File

@ -4,7 +4,7 @@
#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_server.h"
DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
NetworkLayer& layer, Platform& platform) : NetworkLayer& layer, Platform& platform) :
@ -12,6 +12,16 @@ DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
{ {
} }
void DataLinkLayer::cemiServer(CemiServer& cemiServer)
{
_cemiServer = &cemiServer;
}
void DataLinkLayer::dataIndicationFromTunnel(CemiFrame& frame)
{
}
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)
{ {
// Normal data requests and broadcasts will always be transmitted as (domain) broadcast with domain address for open media (e.g. RF medium) // Normal data requests and broadcasts will always be transmitted as (domain) broadcast with domain address for open media (e.g. RF medium)

View File

@ -5,6 +5,7 @@
#include "address_table_object.h" #include "address_table_object.h"
#include "knx_types.h" #include "knx_types.h"
#include "network_layer.h" #include "network_layer.h"
#include "cemi_server.h"
class DataLinkLayer class DataLinkLayer
{ {
@ -12,6 +13,10 @@ class DataLinkLayer
DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer, DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer,
Platform& platform); Platform& platform);
void cemiServer(CemiServer& cemiServer);
void dataIndicationFromTunnel(CemiFrame& frame);
// 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);
@ -30,4 +35,5 @@ class DataLinkLayer
AddressTableObject& _groupAddressTable; AddressTableObject& _groupAddressTable;
NetworkLayer& _networkLayer; NetworkLayer& _networkLayer;
Platform& _platform; Platform& _platform;
CemiServer* _cemiServer;
}; };

View File

@ -15,7 +15,7 @@ Adafruit_USBD_HID usb_hid;
// HID report descriptor using TinyUSB's template // HID report descriptor using TinyUSB's template
// Generic In Out with 64 bytes report (max) // Generic In Out with 64 bytes report (max)
uint8_t const desc_hid_report[] = static uint8_t const desc_hid_report[] =
{ {
//TUD_HID_REPORT_DESC_GENERIC_INOUT(64) //TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
0x06, 0xA0, 0xFF, // Usage Page (Vendor Defined 0xFFA0) 0x06, 0xA0, 0xFF, // Usage Page (Vendor Defined 0xFFA0)
@ -235,10 +235,18 @@ void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8
void UsbDataLinkLayer::loop() void UsbDataLinkLayer::loop()
{ {
if (!_enabled) if (!_enabled)
{
return; return;
}
if (!isTxQueueEmpty())
{
//loadNextTxFrame();
//sendKnxHidReport();
}
} }
bool UsbDataLinkLayer::sendFrame(CemiFrame& frame) bool UsbDataLinkLayer::sendCemiFrame(CemiFrame& frame)
{ {
if (!_enabled) if (!_enabled)
return false; return false;
@ -248,18 +256,11 @@ bool UsbDataLinkLayer::sendFrame(CemiFrame& frame)
// the L_Data.con for the previous L_Data.req. // the L_Data.con for the previous L_Data.req.
addFrameTxQueue(frame); addFrameTxQueue(frame);
// TODO: For now L_data.req is confirmed immediately (L_Data.con)
// see 3.6.3 p.80: L_Data.con shall be generated AFTER transmission of the corresponsing frame
// RF sender will never generate L_Data.con with C=1 (Error), but only if the TX buffer overflows
// The RF sender cannot detect if the RF frame was transmitted successfully or not according to the spec.
dataConReceived(frame, true);
return true; return true;
} }
UsbDataLinkLayer::UsbDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, UsbDataLinkLayer::UsbDataLinkLayer(DeviceObject& deviceObject, CemiServer& cemiServer, Platform& platform)
NetworkLayer& layer, Platform& platform) : _deviceObject(deviceObject), _cemiServer(cemiServer), _platform(platform)
: DataLinkLayer(devObj, addrTab, layer, platform)
{ {
} }
@ -267,26 +268,14 @@ void UsbDataLinkLayer::frameBytesReceived(uint8_t* _buffer, uint16_t length)
{ {
// Prepare the cEMI frame // Prepare the cEMI frame
CemiFrame frame(_buffer, length); CemiFrame frame(_buffer, length);
/*
frame.frameType(ExtendedFrame); // KNX RF uses only extended frame format
frame.priority(SystemPriority); // Not used in KNX RF
frame.ack(AckDontCare); // Not used in KNX RF
frame.systemBroadcast(systemBroadcast); // Mapped from flag AddrExtensionType (KNX serial(0) or Domain Address(1))
frame.hopCount(hopCount); // Hop count from routing counter
frame.addressType(addressType); // Group address or individual address
frame.rfSerialOrDoA(&rfPacketBuf[4]); // Copy pointer to field Serial or Domain Address (check broadcast flag what it is exactly)
frame.rfInfo(rfPacketBuf[3]); // RF-info field (1 byte)
frame.rfLfn(lfn); // Data link layer frame number (LFN field)
*/
/* print("cEMI USB RX len: ");
print(" len: "); print(length);
print(newLength);
print(" data: "); print(" data: ");
printHex(" data: ", _buffer, newLength); printHex(" data: ", _buffer, length);
*/
frameRecieved(frame); _cemiServer.frameReceived(frame);
} }
void UsbDataLinkLayer::enabled(bool value) void UsbDataLinkLayer::enabled(bool value)
@ -329,12 +318,11 @@ void UsbDataLinkLayer::addFrameTxQueue(CemiFrame& frame)
tx_frame->data = new uint8_t[tx_frame->length]; tx_frame->data = new uint8_t[tx_frame->length];
tx_frame->next = NULL; tx_frame->next = NULL;
/* print("cEMI USB TX len: ");
print(" len: "); print(tx_frame->length);
print(totalLength);
printHex(" data:", tx_frame->data, tx_frame->length);
printHex(" data:", tx_frame->data, totalLength);
*/
if (_tx_queue.back == NULL) if (_tx_queue.back == NULL)
{ {
_tx_queue.front = _tx_queue.back = tx_frame; _tx_queue.front = _tx_queue.back = tx_frame;

View File

@ -3,25 +3,26 @@
#include <stdint.h> #include <stdint.h>
#include <Adafruit_TinyUSB.h> #include <Adafruit_TinyUSB.h>
#include "data_link_layer.h" #include "data_link_layer.h"
#include "cemi_server.h"
#define MAX_KNX_TELEGRAM_SIZE 263 #define MAX_KNX_TELEGRAM_SIZE 263
extern Adafruit_USBD_HID usb_hid; extern Adafruit_USBD_HID usb_hid;
class UsbDataLinkLayer : public DataLinkLayer class DeviceObject;
{ class Platform;
using DataLinkLayer::_deviceObject;
using DataLinkLayer::_groupAddressTable;
using DataLinkLayer::_platform;
class UsbDataLinkLayer
{
public: public:
UsbDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer, UsbDataLinkLayer(DeviceObject& deviceObject, CemiServer& cemiServer, Platform& platform);
Platform& platform);
void loop(); void loop();
void enabled(bool value); void enabled(bool value);
bool enabled() const; bool enabled() const;
bool sendCemiFrame(CemiFrame& frame);
private: private:
bool _enabled = false; bool _enabled = false;
uint8_t _loopState = 0; uint8_t _loopState = 0;
@ -43,10 +44,12 @@ class UsbDataLinkLayer : public DataLinkLayer
_tx_queue_frame_t* back = NULL; _tx_queue_frame_t* back = NULL;
} _tx_queue; } _tx_queue;
DeviceObject& _deviceObject;
CemiServer& _cemiServer;
Platform& _platform;
void addFrameTxQueue(CemiFrame& frame); void addFrameTxQueue(CemiFrame& frame);
bool isTxQueueEmpty(); bool isTxQueueEmpty();
void loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBufferLength); void loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBufferLength);
bool sendFrame(CemiFrame& frame);
void frameBytesReceived(uint8_t* buffer, uint16_t length); void frameBytesReceived(uint8_t* buffer, uint16_t length);
}; };