Now that we have explained the concepts involved in adding a device driver to Gadgeteer, we can show some code. The following example is for a fictitious piece of hardware that has only one button.
Example A.1. ButtonDevice.h
1 #ifndef _MY_BUTTON_DEVICE_H_
#define _MY_BUTTON_DEVICE_H_
#include <gadget/Devices/DriverConfig.h>
5
#include <stdlib.h>
#include <vpr/vpr.h>
#include <vpr/Thread/Thread.h>
10 #include <gadget/Type/Input.h>
#include <gadget/Type/Digital.h>
#include <gadget/Type/InputMixer.h>
15 class ButtonDevice
: public gadget::InputMixer<gadget::Input, gadget::Digital>
{
public:
ButtonDevice()
20 : mSampleThread(NULL)
, mRunning(false)
{
/* Do nothing. */ ;
}
25
virtual ~ButtonDevice()
{
if ( mRunning )
{
30 this->stopSampling();
}
}
virtual void updateData();
35 virtual bool startSampling();
virtual bool sample();
virtual bool stopSampling();
static std::string getElementType();
40
/**
* Invokes the global scope delete operator. This is required for proper
* releasing of memory in DLLs on Win32.
*/
45 void operator delete(void* p)
{
::operator delete(p);
}
50 protected:
/**
* Deletes this object. This is an implementation of the pure virtual
* gadget::Input::destroy() method.
*/
55 virtual void destroy()
{
delete this;
}
60 private:
static void sampleFunction(void* classPointer);
int mDigitalData;
vpr::Thread* mSampleThread;
65 bool mRunning;
// configuration data set by config()
std::string mPortName;
int mBaudRate;
70 };
#endifExample A.2. ButtonDevice.cpp
1 #include <gadget/Devices/DriverConfig.h>
#include <vpr/vpr.h>
#include <vpr/System.h>
5 #include <gadget/InputManager.h>
#include <gadget/Type/DeviceConstructor.h>
#include "ButtonDevice.h"
10
using namespace gadget;
extern "C"
{
15
GADGET_DRIVER_EXPORT(void) initDevice(InputManager* inputMgr)
{
new DeviceConstructor<ButtonDevice>(inputMgr);
}
20
}
/** Returns a string that matches this device's configuration element type. */
std::string ButtonDevice::getElementType()
25 {
return std::string("MyButtonDevice");
}
//: When the system detects a configuration change for your driver, it will
30 // pass the new jccl::ConfigElement into this function. See the documentation
// on config elements, for information on how to access them.
bool ButtonDevice::config(jccl::ConfigElementPtr e)
{
if ( ! Digital::config(e))
35 {
return false;
}
mPort = e->getProperty<std::string>("port");
40 mBaud = e->getProperty<int>("baud");
return true;
}
45 void ButtonDevice::updateData()
{
if ( mRunning )
{
swapDigitalBuffers();
50 }
}
/**
* Spanws the sample thread, which calls MyButtonDevice::sample() repeatedly.
55 */
bool ButtonDevice::startSampling()
{
mRunning = true;
mSampleThread = new vpr::Thread(threadedSampleFunction, (void*) this);
60
if ( ! mSampleThread->valid() )
{
mRunning = false;
return false; // thread creation failed
65 }
else
{
return true; // thread creation success
}
70 }
/**
* Records (or samples) the current data. This is called repeatedly by the
* sample thread created by startSampling().
75 */
bool ButtonDevice::sample()
{
bool status(false);
80 if ( mRunning )
{
// Here you would add your code to sample the hardware for a button
// press:
std::vector<DigitalData> samples(1);
85 samples[0] = 1;
addDigitalSample(samples);
// Successful sample.
status = true;
90 }
return status;
}
95 /** Kills the sample thread. */
bool ButtonDevice::stopSampling()
{
mRunning = false;
100 if (mSampleThread != NULL)
{
mSampleThread->kill(); // Not guaranteed to work on all platforms
mSampleThread->join();
delete mSampleThread;
105 mSampleThread = NULL;
}
return true;
}
110 /**
* Our sampling function that is executed by the spawned sample thread.
* This function is declared as a static member of MyButtonDevice. It simply
* calls MyButtonDevice::sample() over and over.
*/
115 void ButtonDevice::threadedSampleFunction(void* classPointer)
{
ButtonDevice* this_ptr = static_cast<ButtonDevice*>( classPointer );
// spin until someone kills "mSampleThread"
120 while ( this_ptr->mRunning )
{
this_ptr->sample();
vpr::System::sleep(1); //specify some time here, so you don't waste CPU cycles
}
125 }