-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* @file | ||
* @author Philipp Jungkamp <[email protected]> | ||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC | ||
* @license Apache 2.0 | ||
*********************************************************************************/ | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
#include <optional> | ||
#include <villas/nodes/c37_118/parser.hpp> | ||
#include <villas/node/config.hpp> | ||
#include <villas/node.hpp> | ||
#include <villas/signal.hpp> | ||
|
||
namespace villas { | ||
namespace node { | ||
namespace c37_118 { | ||
|
||
class C37_118 : public Node { | ||
protected: | ||
struct Input { | ||
std::string address; | ||
} input; | ||
|
||
virtual | ||
int _read(struct Sample *smps[], unsigned cnt) override; | ||
|
||
public: | ||
C37_118(const std::string &name = ""); | ||
|
||
virtual | ||
~C37_118() override; | ||
|
||
virtual | ||
int parse(json_t *json, const uuid_t sn_uuid) override; | ||
|
||
virtual | ||
int start() override; | ||
|
||
virtual | ||
int stop() override; | ||
}; | ||
|
||
} /* namespace c37_118 */ | ||
} /* namespace node */ | ||
} /* namespace villas */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/** | ||
* @file | ||
* @author Philipp Jungkamp <[email protected]> | ||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC | ||
* @license Apache 2.0 | ||
*********************************************************************************/ | ||
|
||
#pragma once | ||
|
||
#include <optional> | ||
#include <cstring> | ||
#include <villas/nodes/c37_118/types.hpp> | ||
|
||
namespace villas { | ||
namespace node { | ||
namespace c37_118 { | ||
namespace parser { | ||
|
||
using Result = std::intptr_t; | ||
|
||
enum class Status : Result { | ||
Ok = 0, | ||
MissingBytes, | ||
MissingConfig, | ||
InvalidValue, | ||
InvalidChecksum, | ||
InvalidSlice, | ||
Other, | ||
}; | ||
|
||
template <typename T = Result> | ||
Result ok(T t = 0); | ||
Result error(Status); | ||
Status status(Result); | ||
bool is_ok(Result); | ||
|
||
// context used to assemble and disassemble data frames with the information contained in config structs | ||
class Context { | ||
public: | ||
using Config = std::variant<types::Config2 /*, struct Config3 */>; | ||
Config config; | ||
|
||
Context(Config config); | ||
void reset(); | ||
void next_pmu(); | ||
uint16_t num_pmu() const; | ||
uint16_t format() const; | ||
uint16_t phnmr() const; | ||
uint16_t annmr() const; | ||
uint16_t dgnmr() const; | ||
|
||
private: | ||
size_t pmu_index; | ||
}; | ||
|
||
// placeholder type allowing deferred assignment to a field during serialization | ||
template <typename T> | ||
class Placeholder; | ||
|
||
class Parser { | ||
public: | ||
std::optional<Context> context; | ||
|
||
using ssize_t = std::ptrdiff_t; | ||
|
||
Parser() = default; | ||
Parser(unsigned char *buffer, size_t length, std::optional<Context::Config> config = std::nullopt); | ||
Result slice(ssize_t from, size_t length); | ||
Result require(size_t length); | ||
Parser subparser(unsigned char *buffer, size_t length); | ||
size_t remaining() const; | ||
|
||
template <typename T> | ||
Result copy_from(T const *arg, size_t length = sizeof(T)); | ||
|
||
template <typename T> | ||
Result copy_to(T *arg, size_t length = sizeof(T)); | ||
|
||
template <typename Arg1, typename Arg2, typename... Args> | ||
Result deserialize(Arg1 *arg1, Arg2 *arg2, Args *...args); | ||
|
||
Result deserialize(uint16_t *i); | ||
Result deserialize(uint32_t *i); | ||
Result deserialize(int16_t *i); | ||
Result deserialize(int32_t *i); | ||
Result deserialize(float *f); | ||
|
||
template <typename T> | ||
Result deserialize(std::vector<T> *v); | ||
|
||
template <typename T, size_t N> | ||
Result deserialize(std::array<T, N> *a); | ||
|
||
template <typename Format> | ||
Result deserialize(types::Rectangular<Format> *r); | ||
|
||
template <typename Format> | ||
Result deserialize(types::Polar<Format> *r); | ||
|
||
Result deserialize(types::Phasor *p); | ||
Result deserialize(types::Analog *a); | ||
Result deserialize(types::Freq *f); | ||
Result deserialize(types::PmuData *d); | ||
Result deserialize(types::Data *d); | ||
Result deserialize(types::Header *h); | ||
Result deserialize(types::Name1 *n); | ||
Result deserialize(types::ChannelInfo *c); | ||
Result deserialize(types::DigitalInfo *d); | ||
Result deserialize(types::PmuConfig1 *c); | ||
Result deserialize(types::Config1 *c); | ||
Result deserialize(types::Config2 *c); | ||
Result deserialize(types::Name3 *n); | ||
Result deserialize(types::Config3 *c); | ||
Result deserialize(types::Command *c); | ||
Result deserialize(types::Frame *f); | ||
|
||
template <typename Arg1, typename Arg2, typename... Args> | ||
Result serialize(Arg1 const *arg1, Arg2 const *arg2, Args const *...args); | ||
Result serialize(uint8_t const *i); | ||
Result serialize(uint16_t const *i); | ||
Result serialize(uint32_t const *i); | ||
Result serialize(int8_t const *i); | ||
Result serialize(int16_t const *i); | ||
Result serialize(int32_t const *i); | ||
Result serialize(float const *f); | ||
|
||
template <typename T> | ||
Result serialize(Placeholder<T> const *p); | ||
|
||
template <typename T> | ||
Result serialize(std::vector<T> const *v); | ||
|
||
template <typename T, size_t N> | ||
Result serialize(std::array<T, N> const *a); | ||
|
||
template <typename Format> | ||
Result serialize(types::Rectangular<Format> const *r); | ||
|
||
template <typename Format> | ||
Result serialize(types::Polar<Format> const *r); | ||
|
||
Result serialize(types::Phasor const *p); | ||
Result serialize(types::Analog const *a); | ||
Result serialize(types::Freq const *f); | ||
Result serialize(types::PmuData const *d); | ||
Result serialize(types::Data const *d); | ||
Result serialize(types::Header const *h); | ||
Result serialize(types::Name1 const *n); | ||
Result serialize(types::ChannelInfo const *c); | ||
Result serialize(types::DigitalInfo const *d); | ||
Result serialize(types::PmuConfig1 const *c); | ||
Result serialize(types::Config1 const *c); | ||
Result serialize(types::Config2 const *c); | ||
Result serialize(types::Name3 const *n); | ||
Result serialize(types::Config3 const *c); | ||
Result serialize(types::Command const *c); | ||
Result serialize(types::Frame const *f); | ||
|
||
private: | ||
unsigned char *start, *cursor, *end; | ||
}; | ||
|
||
// placeholder type allowing deferred assignment to a field during serialization | ||
template <typename T> | ||
class Placeholder | ||
{ | ||
public: | ||
Placeholder() = default; | ||
Result replace(T *t); | ||
private: | ||
mutable std::optional<Parser> saved_parser; | ||
friend Result Parser::serialize(Placeholder<T> const *p); | ||
}; | ||
|
||
uint16_t calculate_crc(unsigned char *frame, uint16_t size); | ||
|
||
} /* namespace parser */ | ||
} /* namespace c37_118 */ | ||
} /* namespace node */ | ||
} /* namespace villas */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#include <array> | ||
#include <complex> | ||
#include <stdint.h> | ||
#include <type_traits> | ||
#include <variant> | ||
#include <vector> | ||
|
||
namespace villas { | ||
namespace node { | ||
namespace c37_118 { | ||
namespace types { | ||
|
||
// cartesian phasor representation | ||
template <typename Format> | ||
struct Rectangular { | ||
Format real; | ||
Format imaginary; | ||
}; | ||
|
||
// polar phasor representation | ||
template <typename Format, bool Unsigned = std::is_integral_v<Format>> | ||
struct Polar; | ||
|
||
template <typename Format> | ||
struct Polar<Format, true> | ||
{ | ||
std::make_unsigned_t<Format> magnitude; | ||
std::make_signed_t<Format> phase; | ||
}; | ||
|
||
template <typename Format> | ||
struct Polar<Format, false> | ||
{ | ||
Format magnitude; | ||
Format phase; | ||
}; | ||
|
||
struct Phasor : public std::variant<Rectangular<int16_t>, Polar<int16_t>, Rectangular<float>, Polar<float>> | ||
{ | ||
std::complex<float> to_complex() const; | ||
}; | ||
|
||
struct Analog : public std::variant<int16_t, float> | ||
{ | ||
float to_float() const; | ||
}; | ||
|
||
struct Freq : public std::variant<int16_t, float> | ||
{ | ||
}; | ||
|
||
struct PmuData | ||
{ | ||
uint16_t stat; | ||
std::vector<Phasor> phasor; | ||
Freq freq; | ||
Freq dfreq; | ||
std::vector<Analog> analog; | ||
std::vector<uint16_t> digital; | ||
}; | ||
|
||
struct Data | ||
{ | ||
std::vector<PmuData> pmus; | ||
}; | ||
|
||
struct Header | ||
{ | ||
std::string data; | ||
}; | ||
|
||
struct Name1 : public std::string | ||
{ | ||
}; | ||
|
||
struct ChannelInfo | ||
{ | ||
Name1 nam; | ||
uint32_t unit; | ||
}; | ||
|
||
struct DigitalInfo | ||
{ | ||
std::array<Name1, 16> nam; | ||
uint32_t unit; | ||
}; | ||
|
||
struct PmuConfig1 | ||
{ | ||
Name1 stn; | ||
uint16_t idcode; | ||
uint16_t format; | ||
std::vector<ChannelInfo> phinfo; | ||
std::vector<ChannelInfo> aninfo; | ||
std::vector<DigitalInfo> dginfo; | ||
uint16_t fnom; | ||
uint16_t cfgcnt; | ||
}; | ||
|
||
struct Config1 | ||
{ | ||
uint32_t time_base; | ||
std::vector<PmuConfig1> pmus; | ||
uint16_t data_rate; | ||
}; | ||
|
||
struct Config2 : public Config1 {}; | ||
|
||
struct Name3 : public std::string | ||
{ | ||
}; | ||
|
||
// ToDo | ||
struct Config3 | ||
{ | ||
}; | ||
|
||
struct Command | ||
{ | ||
uint16_t cmd; | ||
std::vector<unsigned char> ext; | ||
|
||
static constexpr uint16_t DATA_START = 0x1; | ||
static constexpr uint16_t DATA_STOP = 0x2; | ||
static constexpr uint16_t GET_HEADER = 0x3; | ||
static constexpr uint16_t GET_CONFIG1 = 0x4; | ||
static constexpr uint16_t GET_CONFIG2 = 0x5; | ||
static constexpr uint16_t GET_CONFIG3 = 0x6; | ||
}; | ||
|
||
using Message = std::variant<Data, Header, Config1, Config2, Command, Config3>; | ||
|
||
struct Frame | ||
{ | ||
uint16_t version; | ||
uint16_t idcode; | ||
uint32_t soc; | ||
uint32_t fracsec; | ||
Message message; | ||
}; | ||
|
||
} /* namespace types */ | ||
} /* namespace c37_118 */ | ||
} /* namespace node */ | ||
} /* namespace villas */ |
Oops, something went wrong.