lundi 25 janvier 2021

How to exploit polymorphism on embedded systems?

I have been developing a C++ software driver for the adc peripheral of the MCU.

The individual analog inputs connected to the adc can be configured for operation in the unipolar or bipolar mode. To reflect this fact in my design I have decided to model the analog inputs by the AnalogInput abstract class and then define two derived classes. UnipolarAnalogInput for the unipolar analog inputs and BipolarAnalogInput for the bipolar analog inputs. These two classes differ only in the implementation of the getValue() method.

enum class Type
{
Unipolar,
Bipolar
};

class AnalogInput
{
public:

virtual float getValue() = 0; 

};

class UnipolarAnalogInput : public AnalogInput
{
public:

UnipolarAnalogInput(uint8_t _id, bool _enabled, Type _type);
bool isEnabled();
bool isReady();
float getValue(); 

private:

uint8_t id;
Type type;
bool enabled;
bool ready;
uint16_t raw_value;

};

class BipolarAnalogInput : public AnalogInput
{
public:

BipolarAnalogInput(uint8_t _id, bool _enabled, Type _type);
bool isEnabled();
bool isReady();
float getValue(); 

private:

uint8_t id;
Type type;
bool enabled;
bool ready;
uint16_t raw_value;

};

My goal is to fullfill following requirements:

  1. work with both types of the analog inputs uniformly
  2. have a chance to create either the instance of the UnipolarAnalogInput or BipolarAnalogInput based on users configuration of the Adc which is known at the compile time
  3. have a chance to create the instances in for loop iteration
  4. have the implementation which is suitable for the embedded systems

Here are my ideas

As far as the requirement 1.

The ideal state would be to have AnalogInput analog_inputs[NO_ANALOG_INPUTS]. As far as I understand correctly this is not possible in C++. Instead of that I need to define AnalogInput *analog_inputs[NO_ANALOG_INPUTS].

As far as the requirement 2.

It seems to me that the best solution for the other systems than the embedded systems would be to use the factory method design pattern i.e. inside the AnalogInput define

static AnalogInput* getInstance(Type type) {
    if(type == Unipolar) {
        // create instance of the UnipolarAnalogInput
    } else if(type == Bipolar) {
        // create instance of the BipolarAnalogInput
    }
}

Here I would probably need to define somewhere auxiliary arrays for the UnipolarAnalogInput instances and the BipolarAnalogInput instances where the instances would be allocated by the factory method and the pointers to those arrays would be returned by the getInstance(). This solution seems to me to be pretty cumbersome due to the auxiliary arrays presence.

As far as the requirement 3.

for(uint8_t input = 0; input < NO_ANALOG_INPUTS; input++) {
    analog_inputs[input] = AnalogInput::getInstance(AdcConfig->getInputType(input));
}

As far as the requirement 4.

Here I would say that what I have suggested above is applicable also for the embedded systems because the solution avoids usage of the standard new operator. Question mark is the virtual method getValue().

My questions:

  1. what do you think about the suggested approach in respect to the requirements?
  2. do you have more suitable solution?
  3. is the auxiliary arrays presence unavoidable?

Aucun commentaire:

Enregistrer un commentaire