mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 00:44:37 -06:00
Implementation of the offsets in the RateGroupDriver (#2166)
* Implementation of the offsets * Fix comment * Fix spell error * Changing configure interface by addind DividersSet * Update RPI topology * Removing numDivisors from call * Removing memset clear as the constructor handles zeroed initialization * Fixing ASSERT and removing m_numDivisors * Renaming divisersSet to diviserSet --------- Co-authored-by: Simone Morettini <simone.morettini@redwirespaceeurope.com> Co-authored-by: Michael D Starch <Michael.D.Starch@jpl.nasa.gov>
This commit is contained in:
parent
9633049549
commit
36a07dd967
@ -291,13 +291,12 @@ module RPI {
|
||||
{
|
||||
|
||||
phase Fpp.ToCpp.Phases.configObjects """
|
||||
NATIVE_INT_TYPE rgDivs[Svc::RateGroupDriver::DIVIDER_SIZE] = { 1, 10, 0 };
|
||||
Svc::RateGroupDriver::DividerSet rgDivs{{{1, 0}, {10, 0}, {0, 0}}};
|
||||
"""
|
||||
|
||||
|
||||
phase Fpp.ToCpp.Phases.configComponents """
|
||||
rateGroupDriverComp.configure(
|
||||
ConfigObjects::rateGroupDriverComp::rgDivs,
|
||||
FW_NUM_ARRAY_ELEMENTS(ConfigObjects::rateGroupDriverComp::rgDivs)
|
||||
ConfigObjects::rateGroupDriverComp::rgDivs
|
||||
);
|
||||
"""
|
||||
}
|
||||
|
||||
@ -35,8 +35,9 @@ Fw::MallocAllocator mallocator;
|
||||
Svc::FprimeFraming framing;
|
||||
Svc::FprimeDeframing deframing;
|
||||
|
||||
// The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz
|
||||
NATIVE_INT_TYPE rateGroupDivisors[Svc::RateGroupDriver::DIVIDER_SIZE] = {1, 2, 4};
|
||||
// The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz and
|
||||
// zero offset for all the dividers
|
||||
Svc::RateGroupDriver::DividerSet rateGroupDivisorsSet{{{1, 0}, {2, 0}, {4, 0}}};
|
||||
|
||||
// Rate groups may supply a context token to each of the attached children whose purpose is set by the project. The
|
||||
// reference topology sets each token to zero as these contexts are unused in this project.
|
||||
@ -87,7 +88,7 @@ void configureTopology() {
|
||||
cmdSeq.allocateBuffer(0, mallocator, CMD_SEQ_BUFFER_SIZE);
|
||||
|
||||
// Rate group driver needs a divisor list
|
||||
rateGroupDriverComp.configure(rateGroupDivisors, FW_NUM_ARRAY_ELEMENTS(rateGroupDivisors));
|
||||
rateGroupDriverComp.configure(rateGroupDivisorsSet);
|
||||
|
||||
// Rate groups require context arrays. Empty for Reference example.
|
||||
rateGroup1Comp.configure(rateGroup1Context, FW_NUM_ARRAY_ELEMENTS(rateGroup1Context));
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
This component takes a primary clock tick in the system and divides it down to drive output ports.
|
||||
Constructor arguments define the divisors for each port. The output ports are meant to be connected
|
||||
to the input ports of rate groups to drive them at the correct rate.
|
||||
This component takes a primary clock tick in the system and divides it down to drive output ports.
|
||||
Constructor arguments define the divisors for each port.
|
||||
The dividers argument define the divisors for each port as well as an offset to allow the triggering
|
||||
for the rate group to be offset from each other.
|
||||
The output ports are meant to be connected to the input ports of rate groups to drive them at the
|
||||
correct rate.
|
||||
|
||||
RateGroupDriverComponentAi.xml - XML definition of rate group driver component
|
||||
RateGroupDriverImpl.hpp(.cpp) - Implementation for rate group driver
|
||||
RateGroupDriverImpl.hpp(.cpp) - Implementation for rate group driver
|
||||
@ -8,59 +8,52 @@ namespace Svc {
|
||||
|
||||
RateGroupDriver::RateGroupDriver(const char* compName) :
|
||||
RateGroupDriverComponentBase(compName),
|
||||
m_numDividers(0),m_ticks(0),m_rollover(1) {
|
||||
m_ticks(0),m_rollover(1),m_configured(false) {
|
||||
|
||||
}
|
||||
|
||||
void RateGroupDriver::configure(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers)
|
||||
void RateGroupDriver::configure(const DividerSet& dividerSet)
|
||||
{
|
||||
|
||||
// check arguments
|
||||
FW_ASSERT(dividers);
|
||||
FW_ASSERT(numDividers);
|
||||
this->m_numDividers = numDividers;
|
||||
FW_ASSERT(numDividers <= static_cast<NATIVE_INT_TYPE>(FW_NUM_ARRAY_ELEMENTS(this->m_dividers)),
|
||||
numDividers,
|
||||
static_cast<NATIVE_INT_TYPE>(FW_NUM_ARRAY_ELEMENTS(this->m_dividers)));
|
||||
FW_ASSERT(dividerSet.dividers);
|
||||
// verify port/table size matches
|
||||
FW_ASSERT(FW_NUM_ARRAY_ELEMENTS(this->m_dividers) == this->getNum_CycleOut_OutputPorts(),
|
||||
static_cast<NATIVE_INT_TYPE>(FW_NUM_ARRAY_ELEMENTS(this->m_dividers)),
|
||||
this->getNum_CycleOut_OutputPorts());
|
||||
// clear table
|
||||
::memset(this->m_dividers,0,sizeof(this->m_dividers));
|
||||
// copy provided array of dividers
|
||||
for (NATIVE_INT_TYPE entry = 0; entry < numDividers; entry++) {
|
||||
this->m_dividers[entry] = dividers[entry];
|
||||
for (NATIVE_UINT_TYPE entry = 0; entry < RateGroupDriver::DIVIDER_SIZE; entry++) {
|
||||
// A port with an offset equal or bigger than the divisor is not accepted because it would never be called
|
||||
FW_ASSERT((dividerSet.dividers[entry].offset==0)||(dividerSet.dividers[entry].offset < dividerSet.dividers[entry].divisor),
|
||||
dividerSet.dividers[entry].offset,
|
||||
dividerSet.dividers[entry].divisor);
|
||||
this->m_dividers[entry] = dividerSet.dividers[entry];
|
||||
// rollover value should be product of all dividers to make sure integer rollover doesn't jump cycles
|
||||
// only use non-zero dividers
|
||||
if (dividers[entry] != 0) {
|
||||
this->m_rollover *= dividers[entry];
|
||||
if (dividerSet.dividers[entry].divisor != 0) {
|
||||
this->m_rollover *= dividerSet.dividers[entry].divisor;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_configured = true;
|
||||
}
|
||||
|
||||
RateGroupDriver::~RateGroupDriver() {
|
||||
|
||||
}
|
||||
|
||||
void RateGroupDriver::init(NATIVE_INT_TYPE instanceId) {
|
||||
RateGroupDriverComponentBase::init(instanceId);
|
||||
}
|
||||
|
||||
void RateGroupDriver::CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart) {
|
||||
|
||||
// Make sure that the dividers have been configured:
|
||||
// If this asserts, add the configure() call to initialization.
|
||||
FW_ASSERT(this->m_numDividers);
|
||||
FW_ASSERT(this->m_configured);
|
||||
|
||||
// Loop through each divider. For a given port, the port will be called when the divider value
|
||||
// divides evenly into the number of ticks. For example, if the divider value for a port is 4,
|
||||
// it would be called every fourth invocation of the CycleIn port.
|
||||
for (NATIVE_INT_TYPE entry = 0; entry < this->m_numDividers; entry++) {
|
||||
if (this->m_dividers[entry] != 0) {
|
||||
for (NATIVE_UINT_TYPE entry = 0; entry < RateGroupDriver::DIVIDER_SIZE; entry++) {
|
||||
if (this->m_dividers[entry].divisor != 0) {
|
||||
if (this->isConnected_CycleOut_OutputPort(entry)) {
|
||||
if ((this->m_ticks % this->m_dividers[entry]) == 0) {
|
||||
if ((this->m_ticks % this->m_dividers[entry].divisor) == this->m_dividers[entry].offset) {
|
||||
this->CycleOut_out(entry,cycleStart);
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,31 @@ namespace Svc {
|
||||
class RateGroupDriver : public RateGroupDriverComponentBase {
|
||||
|
||||
public:
|
||||
//! Size of the divider table, provided as a constants to users passing the table in
|
||||
static const NATIVE_UINT_TYPE DIVIDER_SIZE = NUM_CYCLEOUT_OUTPUT_PORTS;
|
||||
|
||||
//! \class Divider
|
||||
//! \brief Struct describing a divider
|
||||
struct Divider{
|
||||
//! Initializes divisor and offset to 0 (unused)
|
||||
Divider() : divisor(0), offset(0)
|
||||
{}
|
||||
//! Initializes divisor and offset to passed-in pair
|
||||
Divider(NATIVE_INT_TYPE divisorIn, NATIVE_INT_TYPE offsetIn) :
|
||||
divisor(divisorIn), offset(offsetIn)
|
||||
{}
|
||||
//! Divisor
|
||||
NATIVE_INT_TYPE divisor;
|
||||
//! Offset
|
||||
NATIVE_INT_TYPE offset;
|
||||
};
|
||||
|
||||
//! \class DividerSet
|
||||
//! \brief Struct containing an array of dividers
|
||||
struct DividerSet {
|
||||
//! Dividers
|
||||
Divider dividers[Svc::RateGroupDriver::DIVIDER_SIZE];
|
||||
};
|
||||
|
||||
//! \brief RateGroupDriver constructor
|
||||
//!
|
||||
@ -43,17 +68,10 @@ namespace Svc {
|
||||
//!
|
||||
RateGroupDriver(const char* compName);
|
||||
|
||||
//! \brief RateGroupDriver initialization function
|
||||
//!
|
||||
//! The init() function initializes the autocoded base class
|
||||
|
||||
void init(NATIVE_INT_TYPE instanceId = 0);
|
||||
|
||||
//! \brief RateGroupDriver configuration function
|
||||
//! \param dividers array of integers used to divide down input tick
|
||||
//! \param numDividers size of dividers array
|
||||
//! \param dividersSet set of dividers used to divide down input tick
|
||||
|
||||
void configure(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers);
|
||||
void configure(const DividerSet& dividersSet);
|
||||
|
||||
//! \brief RateGroupDriverImpl destructor
|
||||
|
||||
@ -66,18 +84,16 @@ namespace Svc {
|
||||
void CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart);
|
||||
|
||||
//! divider array
|
||||
NATIVE_INT_TYPE m_dividers[NUM_CYCLEOUT_OUTPUT_PORTS];
|
||||
|
||||
//! size of divider array
|
||||
NATIVE_INT_TYPE m_numDividers;
|
||||
Divider m_dividers[NUM_CYCLEOUT_OUTPUT_PORTS];
|
||||
|
||||
//! tick counter
|
||||
NATIVE_INT_TYPE m_ticks;
|
||||
|
||||
//! rollover counter
|
||||
NATIVE_INT_TYPE m_rollover;
|
||||
public:
|
||||
//! Size of the divider table, provided as a constants to users passing the table in
|
||||
static const NATIVE_UINT_TYPE DIVIDER_SIZE = NUM_CYCLEOUT_OUTPUT_PORTS;
|
||||
|
||||
//! has the configure method been called
|
||||
bool m_configured;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Svc {
|
||||
this->m_portCalls[portNum] = true;
|
||||
}
|
||||
|
||||
void RateGroupDriverImplTester::runSchedNominal(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers) {
|
||||
void RateGroupDriverImplTester::runSchedNominal(Svc::RateGroupDriver::DividerSet dividersSet, NATIVE_INT_TYPE numDividers) {
|
||||
|
||||
TEST_CASE(106.1.1,"Nominal Execution");
|
||||
COMMENT(
|
||||
@ -48,7 +48,7 @@ namespace Svc {
|
||||
NATIVE_INT_TYPE expected_rollover = 1;
|
||||
|
||||
for (NATIVE_INT_TYPE div = 0; div < numDividers; div++) {
|
||||
expected_rollover *= dividers[div];
|
||||
expected_rollover *= dividersSet.dividers[div].divisor;
|
||||
}
|
||||
|
||||
ASSERT_EQ(expected_rollover,this->m_impl.m_rollover);
|
||||
@ -65,7 +65,7 @@ namespace Svc {
|
||||
ASSERT_EQ((cycle+1)%expected_rollover,this->m_impl.m_ticks);
|
||||
// check for various intervals
|
||||
for (NATIVE_INT_TYPE div = 0; div < numDividers; div++) {
|
||||
if (cycle % dividers[div] == 0) {
|
||||
if (cycle % dividersSet.dividers[div].divisor == dividersSet.dividers[div].offset) {
|
||||
EXPECT_TRUE(this->m_portCalls[div]);
|
||||
} else {
|
||||
EXPECT_FALSE(this->m_portCalls[div]);
|
||||
|
||||
@ -20,7 +20,7 @@ namespace Svc {
|
||||
|
||||
void init(NATIVE_INT_TYPE instance = 0);
|
||||
|
||||
void runSchedNominal(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers);
|
||||
void runSchedNominal(Svc::RateGroupDriver::DividerSet dividersSet, NATIVE_INT_TYPE numDividers);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -31,10 +31,10 @@ void connectPorts(Svc::RateGroupDriver& impl, Svc::RateGroupDriverImplTester& te
|
||||
|
||||
TEST(RateGroupDriverTest,NominalSchedule) {
|
||||
|
||||
NATIVE_INT_TYPE dividers[] = {1,2,3};
|
||||
Svc::RateGroupDriver::DividerSet dividersSet{{{1, 0}, {2, 1}, {3, 0}}};
|
||||
|
||||
Svc::RateGroupDriver impl("RateGroupDriver");
|
||||
impl.configure(dividers,FW_NUM_ARRAY_ELEMENTS(dividers));
|
||||
impl.configure(dividersSet);
|
||||
|
||||
Svc::RateGroupDriverImplTester tester(impl);
|
||||
|
||||
@ -44,7 +44,7 @@ TEST(RateGroupDriverTest,NominalSchedule) {
|
||||
// connect ports
|
||||
connectPorts(impl,tester);
|
||||
|
||||
tester.runSchedNominal(dividers,FW_NUM_ARRAY_ELEMENTS(dividers));
|
||||
tester.runSchedNominal(dividersSet,FW_NUM_ARRAY_ELEMENTS(dividersSet.dividers));
|
||||
|
||||
}
|
||||
|
||||
@ -53,5 +53,3 @@ int main(int argc, char* argv[]) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user