MCA2 Calculator Tutorial Chapter 4

From Mca2
Jump to navigationJump to search

Now that a pocket calculator with only one calculation type is very poor we implement some more functionality. Create three further modules. One for subtraction, one for multiplication and one for division. Concretely:

[home] $ -C projects/calculator/src/calculator/ "Subtract"
[home] $ -C projects/calculator/src/calculator/ "Multiply"
[home] $ -C projects/calculator/src/calculator/ "Divide"

Enter the header files of each module and create two ControllerInputs eCI_VALUE1 and eCI_VALUE2 and one SensorOutput eSO_RESULT. Remember to add a member variable of type double named m_result. Go to the Control() functions in each .cpp file of the new modules. Read the values from the ControllerInputs and store them in m_result. Add code to the Sensor-functions to write m result to the SensorOutput as we did within mAdd.cpp. When finished, add the new modules to the CMakeLists.txt.




Afterwards open the gPocketCalc.cpp. Include the header-files of the new modules:

#include "mSubtract.h"
#include "mMultiply.h"
#include "mDivide.h"


Create one object per module and save the memory adresses in pointers:

mSubtract *subtraction = new mSubtract(this);
mMultiply *multiplication = new mMultiply(this);
mDivide *division = new mDivide(this);


Add the down edges from the ControllerInputs of the group to the ControllerInputs of the modules.

AddEdgeDown(this, subtraction, 2, eCI_VALUE1, mSubtract::eCI_VALUE1, eCI_VALUE2, mSubtract::eCI_VALUE2);
AddEdgeDown(this, multiplication, 2, eCI_VALUE1, mMultiply::eCI_VALUE1, eCI_VALUE2, mMultiply::eCI_VALUE2);
AddEdgeDown(this, division, 2, eCI_VALUE1, mDivide::eCI_VALUE1, eCI_VALUE2, mDivide::eCI_VALUE2);


Although it is possible to connect the same ControllerInputs of the group to the ControllerInputs of several modules, this must not be done with the SensorOutputs of the modules and the SensorOutput of the group. The reason is crucial: All modules would overwrite each other’s SensorOutput and which of the results the group would be able to read is not deterministic. So always when you are going to connect outputs of modules or groups with inputs of other modules or groups, you should think about if it is possible or if it would cause the outputs to overwrite others. The solution for this problem is to use a multiplexer. A multiplexer is a prebuilt module that comes with mca2 and can be found in the library mcal_general. The multiplexer module is capable of multiplexing in several ways. What we need here is a multiplexer from SensorInput to SensorOutput.


From the figure it is possible to learn the functionality of the multiplexer. You can see that the multiplexer saves the four different results from the four different calculations. You can chose through the multiplexer which chanel you would like to give to the SensorOutput.

Remark: This figure shows the Calculator when it is finished.

We now define some enums in gPocketCalc.h to name the inputs and outputs of the multiplexer. Add to the public-declaration area:

enum {
  eMP_SI_DIMENSION /*!< Endmarker and Dimension */

DESCR(static, gPocketCalc, m_mp_so_description, 7, Natural, cDATA_VECTOR_END_MARKER);
enum {
  eMP_SO_DIMENSION /*!< Endmarker and Dimension */


The DESCRiption is for naming purposes in a similar way the ControllerInput enums are named. You can ignore it for the moment and focus on the multiplexer, which we create by including the header file in the group

#include "mcal_general/mMultiplexer.h"


and calling the constructor of mMultiplexer. Here we can specify the functionality of the multiplexer.

mMultiplexer *mux = new mMultiplexer(this, mMultiplexer::eMM_SI2SO, mMultiplexer::eCM_CI, eMP_SO_DIMENSION, eMP_SI_DIMENSION, m_mp_so_description, "Calculation Type MUX", true);


The parameters of the constructor are:

  • the parent-pointer
  • the multiplexing mode – here we define it by using an enum out of the namespace mMultiplthat matches our purposes of multiplexing from SensorInput to SensorOutput
  • the place ( ControllerInput or SensorInput ) where we want to have a selector to tellmultiplexer which of the SensorInputs should be passed
  • the dimension we want to multiplex – here eMP_SO_DIMENSION = 1 because we only multiplex eSO RESULT-SensorOutputs of the four modules
  • the number of between how many modules we want to multiplex – here eMP_SI_DIMENSION = 4 because of 4 modules
  • the description to name the SensorIn- and Outputs of the Multiplexer with “Result”
  • the name of the multiplexer to be shown in mcabrowser
  • and fixit – which is for fixing edges and you can ignore it’s meaning for the moment.

As we will have to tell the multiplexer which SensorInput to pass we need another ControllerInput for our group. Create one by adding eCI_CALCULATION_TYPE to the ControllerInput enum in the .h file:

enum {
  eCI_DIMENSION              /*!< Endmarker and Dimension */


The next step would be to connect the modules to the multiplexer and the multiplexer to the group. Remember to remove the old up-edge from the addition module to the group.

AddEdgeDown(this, mux, 1, eCI_CALCULATION_TYPE, 0);
AddEdgeUp(addition, mux, eMP_SO_DIMENSION, mAdd::eSO_RESULT, eMP_SI_ADD);
AddEdgeUp(subtraction, mux, eMP_SO_DIMENSION, mSubtract::eSO_RESULT, eMP_SI_SUBTRACT);
AddEdgeUp(multiplication, mux, eMP_SO_DIMENSION, mMultiply::eSO_RESULT, eMP_SI_MULTIPLY);
AddEdgeUp(division, mux, eMP_SO_DIMENSION, mDivide::eSO_RESULT, eMP_SI_DIVIDE);
AddEdgeUp(mux,this, 1, 0, eSO_RESULT);


Now, when you are using cmake to build the project, you need to add the mca2_general library to the project. You can do it, by adding the "mca2_general" under ICMAKER_INTERNAL_DEPENDENCIES in the CMakeLists.txt file located in the src folder. After adding, the changed part of the CMakeLists.txt should look like:



That’s it, we’re done! Our program should work. Run

[mca-home-dir] $ mcabrowser

and test it (and see figures 6 and 7). Compile and run the program.

< Back === Forward >