From b9c4a043dcbaf9dd51730438afad99b5154df04a Mon Sep 17 00:00:00 2001 From: Auke Klazema <klazema@astron.nl> Date: Thu, 24 Jan 2019 09:24:59 +0000 Subject: [PATCH] task SW-575: Added processing of multiple complex weights --- MAC/APL/PIC/RSP_Driver/src/rspctl.cc | 64 +++++++++++++++++++++----- MAC/APL/PIC/RSP_Driver/src/rspctl.h | 34 ++++++++++---- MAC/APL/PIC/RSP_Driver/test/tRSPCtl.cc | 27 +++++++++++ 3 files changed, 105 insertions(+), 20 deletions(-) diff --git a/MAC/APL/PIC/RSP_Driver/src/rspctl.cc b/MAC/APL/PIC/RSP_Driver/src/rspctl.cc index 0c3f5a4a257..322726b62d1 100644 --- a/MAC/APL/PIC/RSP_Driver/src/rspctl.cc +++ b/MAC/APL/PIC/RSP_Driver/src/rspctl.cc @@ -213,19 +213,28 @@ void WeightsCommand::send() boost::dynamic_bitset<> beamlet_mask = getBEAMLETSMask(itsBitsPerSample); // -1 < m_value <= 1 - complex<double> value = m_value; - value *= (1<<14); // -.99999 should become -16383 and 1 should become 16384 setweights.weights() = itsWeights; int rcunr = 0; int max_beamlets = maxBeamlets(itsBitsPerSample); + bool multiple_values = (m_values.size() > 1); for (int rcu = 0; rcu < MAX_RCUS; rcu++) { if (setweights.rcumask.test(rcu)) { + std::list<complex<double>>::iterator itr = m_values.begin(); for (int beamlet = 0; beamlet < max_beamlets; beamlet++) { if (beamlet_mask.test(beamlet)) { + complex<double> value = *itr; + value *= (1<<14); // -.99999 should become -16383 and 1 should become 16384 int plane = beamlet / maxBeamletsPerBank(itsBitsPerSample); int beamletnr = beamlet % maxBeamletsPerBank(itsBitsPerSample); setweights.weights()(0,rcunr,plane,beamletnr) = complex<int16>((int16)value.real(), (int16)value.imag()); //setweights.weights()(0,rcunr,plane,beamletnr) = complex<int16>(10+plane, beamletnr); // for testing + if(multiple_values) { // advance value if we have multiple values otherwise use the single value for all beamlets + itr++; + if(itr == m_values.end()) { + logMessage(cerr,formatString("Error: not enough complex numbers for the amount of beamlets")); + rspctl_exit_code = EXIT_FAILURE; + } + } } } // beamlet rcunr++; @@ -3301,6 +3310,22 @@ GCFEvent::TResult LatencyCommand::ack(GCFEvent& e) return GCFEvent::HANDLED; } +TestableRSPCtl::TestableRSPCtl(string name, int argc, char** argv) : + RSPCtl(name, argc, argv), + m_argc (argc), + m_argv (argv) +{ +} + +TestableRSPCtl::~TestableRSPCtl() +{ +} + +Command* TestableRSPCtl::getCommand() +{ + return parse_options(m_argc, m_argv); +} + // // RSPCtl() // @@ -4058,15 +4083,28 @@ Command* RSPCtl::parse_options(int argc, char** argv) if (optarg) { weightscommand->setMode(false); - double re = 0.0, im = 0.0; - int numitems = sscanf(optarg, "%lf,%lf", &re, &im); - if (numitems == 0 || numitems == EOF) { - logMessage(cerr,"Error: invalid weights value. Should be of the format " - "'--weights=value.re[,value.im]' where value is a floating point value in the range (-1,1]."); - rspctl_exit_code = EXIT_FAILURE; - exit(EXIT_FAILURE); - } - weightscommand->setValue(complex<double>(re,im)); + std::list<std::complex<double>> weights; + + if(optarg[0] == '(') { + weights = utility::strtocomplexlist(optarg); + if (weights.empty()) { + logMessage(cerr,"Error: invalid or missing '--weights' option"); + rspctl_exit_code = EXIT_FAILURE; + exit(EXIT_FAILURE); + } + } + else { + double re = 0.0, im = 0.0; + int numitems = sscanf(optarg, "%lf,%lf", &re, &im); + if (numitems == 0 || numitems == EOF) { + logMessage(cerr,"Error: invalid weights value. Should be of the format " + "'--weights=value.re[,value.im]' where value is a floating point value in the range (-1,1]."); + rspctl_exit_code = EXIT_FAILURE; + exit(EXIT_FAILURE); + } + weights.push_back(complex<double>(re,im)); + } + weightscommand->setValues(weights); } } break; @@ -4099,7 +4137,9 @@ Command* RSPCtl::parse_options(int argc, char** argv) } //weightscommand->setValue(complex<double>(amplitude * ::cos(angle), amplitude * ::sin(angle))); - weightscommand->setValue(amplitude * exp(complex<double>(0,angle / 180.0 * M_PI))); + std::list<std::complex<double>> weights; + weights.push_back(amplitude * exp(complex<double>(0,angle / 180.0 * M_PI))); + weightscommand->setValues(weights); } } break; diff --git a/MAC/APL/PIC/RSP_Driver/src/rspctl.h b/MAC/APL/PIC/RSP_Driver/src/rspctl.h index e876edd886f..55d99b66f3a 100644 --- a/MAC/APL/PIC/RSP_Driver/src/rspctl.h +++ b/MAC/APL/PIC/RSP_Driver/src/rspctl.h @@ -215,12 +215,15 @@ public: virtual ~WeightsCommand() {} virtual void send(); virtual GCFEvent::TResult ack(GCFEvent& e); - void setValue(std::complex<double> value) { - m_value = value; + void setValues(std::list<std::complex<double>> values) { + m_values = values; } void setType(int type) { m_type = type; } + std::list<std::complex<double>> getValues() { + return m_values; + } private: - std::complex<double> m_value; + std::list<std::complex<double>> m_values; int m_type; int itsStage; blitz::Array<std::complex<int16>, 4> itsWeights; @@ -850,18 +853,17 @@ public: // Start the controller main loop. void mainloop(); - +protected: + // the command to execute + Command* itsCommand; + Command* parse_options(int argc, char** argv); private: // private methods - Command* parse_options(int argc, char** argv); void logMessage(ostream& stream, const string& message); // ports GCFTCPPort* itsRSPDriver; - // the command to execute - Command* itsCommand; - // dimensions of the connected hardware int m_nrcus; int m_nrspboards; @@ -884,6 +886,22 @@ private: SubClockCommand m_subclock; // always subscribe to clock updates }; +class TestableRSPCtl : public RSPCtl +{ +public: + // The constructor of the RSPCtl task. + // @param name The name of the task. The name is used for looking + // up connection establishment information using the GTMNameService and + // GTMTopologyService classes. + TestableRSPCtl(string name, int argc, char** argv); + virtual ~TestableRSPCtl(); + Command* getCommand(); +private: + // commandline parameters + int m_argc; + char** m_argv; +}; + }; // namespace rspctl }; // namespace LOFAR diff --git a/MAC/APL/PIC/RSP_Driver/test/tRSPCtl.cc b/MAC/APL/PIC/RSP_Driver/test/tRSPCtl.cc index b8d2dbe144e..ae99cf37a36 100644 --- a/MAC/APL/PIC/RSP_Driver/test/tRSPCtl.cc +++ b/MAC/APL/PIC/RSP_Driver/test/tRSPCtl.cc @@ -5,6 +5,7 @@ #include "rspctl.h" using namespace LOFAR::TYPES; +using namespace LOFAR::rspctl; using namespace LOFAR::rspctl::utility; TEST(returns_empty_complex_list_with_empty_string) @@ -43,6 +44,32 @@ TEST(strtocomplexlist_contains_correct_complex_number_when_string_has_a_pair_wit CHECK_EQUAL(0, first_value.imag()); } +TEST(rspctl_should_create_the_weightscommand_when_weights_option_is_given) +{ + char* argv[2]; + argv[0] = const_cast<char*>("rspctl"); + argv[1] = const_cast<char*>("--weights=(1,1)"); + TestableRSPCtl rspctl("RSPCtl", 2, argv); + + Command* command = rspctl.getCommand(); + CHECK_EQUAL(true, (dynamic_cast<WeightsCommand*>(command) != NULL)); +} + +TEST(rspctl_should_set_weights_correctly_on_command) +{ + char* argv[2]; + argv[0] = const_cast<char*>("rspctl"); + argv[1] = const_cast<char*>("--weights=(0.2,0.1)"); + TestableRSPCtl rspctl("RSPCtl", 2, argv); + + Command* command = rspctl.getCommand(); + WeightsCommand* weights_command = dynamic_cast<WeightsCommand*>(command); + std::list<std::complex<double>> values = weights_command->getValues(); + + CHECK_EQUAL(0.2, values.front().real()); + CHECK_EQUAL(0.1, values.front().imag()); +} + int main(int, const char *[]) { return UnitTest::RunAllTests(); -- GitLab