HapticLib
0.7
Haptic Feedback Library for embedded systems
|
In this page are explained internal details of HapticLib. The Developer that wants to extend or modify the library will find this page useful.
SystemDesc is a global structure holding the references of the application runtime state.
It holds a reference for each initialized haptor and a reference for each initialized pattern.
Using this variable all library code can interact with the rest of the system easily.
Additionally, here are stored the PWM driving signal frequency and the global inter-samples delay.
The scope of this variable would be global, but a preprocessor conditionally inclusion has been made to avoid the exposure of this variable to the user application code.
If the user needs access to this system variable, he must define the HL_SYSTEM_FILE preprocessor symbol on the module using it.
The actual structure definition of system_desc is the following:
typedef struct system_desc { uint8_t num_haptors; haptor_desc haptors[MAX_HAPTORS]; pattern_desc patterns[MAX_HAPTORS]; uint32_t pwm_freq; uint8_t samples_delay; } system_desc;
MAX_HAPTORS is a platform specific definition to limit the actual maximum number of haptors available.
SystemDesc holds a reference to each haptor initialized. The reference is a descriptor holding the following information about the haptor:
typedef struct haptor_desc { uint8_t id; uint16_t min_duty; uint16_t max_duty; pattern_desc *activePattern; struct haptor_desc *nextHaptor; } haptor_desc;
min_duty and max_duty are useful to calibrate the range of operation of the physical device.
activePattern refer to the descriptor of the pattern attached to this haptor (if any).
nextHaptor is a reference to another haptor. This pointer creates a linked list of haptors belonging to the same group. It is used to implement multi-haptor patterns. (see below for further informations)
SystemDesc hold a reference to each active pattern in the running system.
The reference is a descriptor of a pattern holding the following data:
typedef struct pattern_desc { pattern_name name; user_param *userParams; status_param statusParams; pattern_continuator continuator; struct haptor_desc *activeHaptorList; } pattern_desc;
pattern_name is a numeric id (int) handled as enumeration ( pattern_name ) to make code cleaner and easy to read.
userParams is a reference to a structure holding the user provided parameters needed by the pattern.
statusParams is a data structure holding the state of the pattern. This structure is defined by the pattern developer and is not exposed to the user.
continuator is a function pointer to the code that will be executed at every scheduled instant by this active pattern. If this pointer is NULL, then the system will consider this pattern not active.
the continuator is a function defined by the pattern developer and is not exposed to the user.
activeHaptorList points to the first haptor of the linked list forming the group of attached haptors. Using this list a pattern can easily developed as multi-haptor.
When a pattern is initialized, an available slot on SystemDesc is searched for and, if found, the pattern goes there.
The pattern now has no haptor attached to it, so the user must add every haptor to it. At every call of hl_addHaptor() the linked-list is formed for later references by the pattern code.
Now the pattern is ready to be started for the actual rendering.
The rendering of a pattern has two main steps:
When the pattern is started, a function called pattern initiator is called to initialize the pattern initial status. userParams is used to set the initial status of the pattern that is hold in statusParams.
The initiator must set the pattern continuator on its pattern descriptor.
This operation is the actual start of the pattern, as the patternScheduler check for this pointer to be not-NULL to execute the pattern continuator code.
From now on, when the scheduler decides, the pattern continuator is executed.
The actual logic inside the continuator, is up to the pattern developer.
Usually the task carried by the continuator are:
The userParams polling is a key features to let the user drive the pattern logic ( as coded by the pattern developer ).
The exit strategy is a way for the pattern to self-deallocate from scheduling. This is not mandatory, but the pattern developer must explicitly document the behavior. For example, a pattern could self-stop after some time of execution. Another pattern could run indefinitely and stop only when the user forces its stop calling hl_stopPattern().
To create a new pattern generator, the easy way is to copy an existing one and the modify it.
Here are the steps to implement a new test pattern generator:
test2.h will contain the definitions of the new pattern:
test2.c will contain at least initiator and continuator code:
Be sure to implement a correct exit strategy on the continuator triggered by some event (could be a value on some userParam set by the user application code), or explicitly state on pattern documentation that the user must call hl_stopPattern() to stop it.
The documentation template is as follow:
Inside hl_patterns.h, references to the new pattern must be added in 4 points:
Inside hl_patterns.c, the new pattern must be added in 2 points:
Adding a new platform, like for patterns, consists in adding a new sub-directory inside HapticLib/platforms.
Comparison of HapticLevel demo application with a modified version of MEMS demo application from STM.
Instructions for HapticLevel compilation:
Instructions for modified demo compilation: