Previous: , Up: Implementing and integrating foreign components   [Contents]


3.3.3 Implementing generated ‘skeleton’ components

To start implementing the LED component’s behavior, create the LED.cc and LED.hh files. The AlarmSystem you generated from the Dezyne models already includes the LED.hh file by name, which is why you are restricted in naming it. In this LED.hh file you are also required to define a struct (or class, they are the same in C++) LED that inherits from skel::LED. The LED class definition in LED.hh will look like this:

#include "skel_LED.hh"

class LED : public skel::LED {

}

By inheriting from skel::LED, the LED class is forced to implement all pure virtual functions defined in the base class. The pure virtual functions that are defined in the base class are all events that would normally be handled by the respective component’s behavior. Let’s take a look at the generated LED class in skel_LED.hh:

namespace skel {
  struct LED
  {
    // Dezyne meta information
    ILED iLed;

    LED(const dzn::locator&);
    virtual ~LED();

    // Dezyne meta informaton

    private:
    virtual void iLed_setGreen() = 0;
    virtual void iLed_setYellow() = 0;
    virtual void iLed_setRed() = 0;
    virtual void iLed_turnOff() = 0;
  };
}

As expected, the events we promised to implement in the ILED interface (setGreen, setYellow, setRed and turnOff) are pure virtual functions in the generated base class. You should add these function declarations to the LED class definition in LED.hh as an exercise.

Solution:

#include "skel_LED.hh"

class LED : public skel::LED {
  void iLed_setGreen();
  void iLed_setYellow();
  void iLed_setRed();
  void iLed_turnOff();
}

Lastly, as the LED class you’ll be creating will be constructed like any other generated Dezyne class, you will need to define a constructor for the LED that accepts a dzn::locator reference as parameter. The final version of the foreign LED class definition, from the Dezyne perspective, will look like this:

#include "skel_LED.hh"

class LED : public skel::LED {
  void iLed_setGreen();
  void iLed_setYellow();
  void iLed_setRed();
  void iLed_turnOff();

public:
  LED(const dzn::locator& loc);
}

Note that the constructor must be public; this is because the generated AlarmSystem directly calls the constructor of the LED class. The functions it implements do not have to be public; those functions are called through the LED class’ ILED port. The skel_LED.hh file already includes the necessary files from the Dezyne runtime to be able to refer to dzn::locator, so that’s taken care of as well.

With the definition out of the way, what’s left to be done is the implementation of the functions of the LED class. Driving an LED on the Raspberry Pi can be done with the WiringPi library (http://wiringpi.com). To make use of WiringPi, its setup function needs to be called and the GPIO pins connected to the LED must be initialized. This is hardware-specific setup that should be performed in the implementation of the LED’s constructor; it will be performed when the constructor is called by the generated AlarmSystem. As an exercise, write an implementation for the constructor using wiringPiSetup() and pinMode() for your hardware setup.

Solution:

#include <wiringPi.h>
#include "LED.hh"

LED::LED(const dzn::locator& loc) {
  wiringPiSetup();
  //Pin numbers are declared in LED.hh as PIN_RED, PIN_GREEN and PIN_BLUE for readability
  pinMode(PIN_RED, OUTPUT);
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_BLUE, OUTPUT);
}

The solution above takes care of all the hardware setup, but that is not all we want to do with the foreign implementation of a Dezyne component. To fully integrate a foreign component in the AlarmSystem, you should call also call the constructor of the component’s base class to handle Dezyne related initialization. In C++, this is easily done by modifying the constructor to the following:

LED::LED(const dzn::locator& loc) : skel::LED(loc) {

This modification will call the constructor of LED’s base class skel::LED as well as perform the constructor you implemented in your foreign component. In skel::LED all of the Dezyne meta information and port binding is handled, so all you need to worry about in the foreign LED class is the functional behavior of the component.

To implement the setGreen, setYellow, setRed and turnOff functions you can do that like you would any other function. WiringPi provides a digitalWrite() function you can use to turn output on a GPIO pin on or off. All the colors we wish to display on the RGB LED can be created by a mixture of on and off on the three respective pins. Try implementing the remaining functions yourself as an exercise.

Solution:

void LED::iLed_setGreen() {
  digitalWrite(PIN_RED, LOW);
  digitalWrite(PIN_GREEN, HIGH);
  digitalWrite(PIN_BLUE, LOW);
}

void LED::iLed_setYellow() {
  digitalWrite(PIN_RED, HIGH);
  digitalWrite(PIN_GREEN, HIGH);
  digitalWrite(PIN_BLUE, LOW);
}

void LED::iLed_setRed() {
  digitalWrite(PIN_RED, HIGH);
  digitalWrite(PIN_GREEN, LOW);
  digitalWrite(PIN_BLUE, LOW);
}

void LED::iLed_turnOff() {
  digitalWrite(PIN_RED, LOW);
  digitalWrite(PIN_GREEN, LOW);
  digitalWrite(PIN_BLUE, LOW);
}

In summary: you now have a small but functionally complete burglar alarm program which accepts ‘s’ and ‘v’ commands from the user to denote a sensor trigger and valid password entry. Based on sequences of events, the program will display different colors on an RGB LED denoting whether the system is Unarmed, Armed or Alarming.

In the next section, you will find instructions on how to compile this application on a Raspberry Pi target so you can see it function in the real world!


Previous: , Up: Implementing and integrating foreign components   [Contents]