libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers can_acceptance_filter_configurator.hpp Source File

can_acceptance_filter_configurator.hpp

00001 /*
00002  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>,
00003  *                    Ilia  Sheremet <illia.sheremet@gmail.com>
00004  */
00005 
00006 #ifndef UAVCAN_TRANSPORT_CAN_ACCEPTANCE_FILTER_CONFIGURATOR_HPP_INCLUDED
00007 #define UAVCAN_TRANSPORT_CAN_ACCEPTANCE_FILTER_CONFIGURATOR_HPP_INCLUDED
00008 
00009 #include <cassert>
00010 #include <uavcan/data_type.hpp>
00011 #include <uavcan/error.hpp>
00012 #include <uavcan/transport/dispatcher.hpp>
00013 #include <uavcan/node/abstract_node.hpp>
00014 #include <uavcan/build_config.hpp>
00015 #include <uavcan/util/multiset.hpp>
00016 
00017 namespace uavcan
00018 {
00019 /**
00020  * This class configures hardware acceptance filters (if this feature is present on the particular CAN driver) to
00021  * preclude reception of irrelevant CAN frames on the hardware level.
00022  *
00023  * Configuration starts by creating an object of class @ref CanAcceptanceFilterConfigurator on the stack.
00024  * By means of computeConfiguration() method the class determines the number of available HW filters and the number
00025  * of listeners. In case if custom configuration required, it is possible to add it through addFilterConfig().
00026  * Subsequently obtained configurations are then loaded into the CAN driver by calling the applyConfiguration() method.
00027  * If the cumulative number of configurations obtained by computeConfiguration() and addFilterConfig() is higher than
00028  * the number of available HW filters, configurations will be merged automatically in the most efficient way.
00029  *
00030  * Note that if the application adds additional server or subscriber objects after the filters have been configured,
00031  * the configuration procedure will have to be performed again.
00032  *
00033  * The maximum number of CAN acceptance filters is predefined in uavcan/build_config.hpp through a constant
00034  * @ref MaxCanAcceptanceFilters. The algorithm doesn't allow to have higher number of HW filters configurations than
00035  * defined by MaxCanAcceptanceFilters. You can change this value according to the number specified in your CAN driver
00036  * datasheet.
00037  */
00038 class CanAcceptanceFilterConfigurator
00039 {
00040 public:
00041     /**
00042      * These arguments defines whether acceptance filter configuration has anonymous messages or not
00043      */
00044     enum AnonymousMessages
00045     {
00046         AcceptAnonymousMessages,
00047         IgnoreAnonymousMessages
00048     };
00049 
00050 private:
00051     /**
00052      * Below constants based on UAVCAN transport layer specification. Masks and ID's depends on message
00053      * TypeID, TransferID (RequestNotResponse - for service types, ServiceNotMessage - for all types of messages).
00054      * For more details refer to uavcan.org/CAN_bus_transport_layer_specification.
00055      * For clarity let's represent "i" as Data Type ID and "d" as Destination Node Id
00056      * DefaultFilterMsgMask = 00000 11111111 11111111 10000000
00057      * DefaultFilterMsgID   = 00000 iiiiiiii iiiiiiii 00000000, no need to explicitly define, since MsgID initialized
00058      * as 0.
00059      * DefaultFilterServiceMask = 00000 00000000 01111111 10000000
00060      * DefaultFilterServiceID   = 00000 00000000 0ddddddd 10000000, all Service Response Frames are accepted by
00061      * HW filters.
00062      * DefaultAnonMsgMask = 00000 00000000 00000000 11111111
00063      * DefaultAnonMsgID   = 00000 00000000 00000000 00000000, by default the config is added to accept all anonymous
00064      * frames. In case there are no anonymous messages, invoke computeConfiguration(IgnoreAnonymousMessages).
00065      */
00066     static const unsigned DefaultFilterMsgMask = 0xFFFF80;
00067     static const unsigned DefaultFilterServiceMask = 0x7F80;
00068     static const unsigned DefaultFilterServiceID = 0x80;
00069     static const unsigned DefaultAnonMsgMask = 0xFF;
00070     static const unsigned DefaultAnonMsgID = 0x0;
00071 
00072     typedef uavcan::Multiset<CanFilterConfig>  MultisetConfigContainer;
00073 
00074     static CanFilterConfig mergeFilters(CanFilterConfig& a_, CanFilterConfig& b_);
00075     static uint8_t countBits(uint32_t n_);
00076     uint16_t getNumFilters() const;
00077 
00078     /**
00079      * Fills the multiset_configs_ to proceed it with mergeConfigurations()
00080      */
00081     int16_t loadInputConfiguration(AnonymousMessages load_mode);
00082 
00083     /**
00084      * This method merges several listeners's filter configurations by predetermined algorithm
00085      * if number of available hardware acceptance filters less than number of listeners
00086      */
00087     int16_t mergeConfigurations();
00088 
00089     INode& node_;               //< Node reference is needed for access to ICanDriver and Dispatcher
00090     MultisetConfigContainer multiset_configs_;
00091     uint16_t filters_number_;
00092 
00093 public:
00094     /**
00095      * @param node              Libuavcan node whose subscribers/servers/etc will be used to configure the filters.
00096      *
00097      * @param filters_number    Allows to override the maximum number of hardware filters to use.
00098      *                          If set to zero (which is default), the class will obtain the number of available
00099      *                          filters from the CAN driver via @ref ICanIface::getNumFilters().
00100      */
00101     explicit CanAcceptanceFilterConfigurator (INode& node, uint16_t filters_number = 0)
00102         : node_(node)
00103         , multiset_configs_(node.getAllocator())
00104         , filters_number_(filters_number)
00105     { }
00106 
00107     /**
00108      * This method invokes loadInputConfiguration() and mergeConfigurations() consequently
00109      * in order to comute optimal filter configurations for the current hardware.
00110      *
00111      * It can only be invoked when all of the subscriber and server objects are initialized.
00112      * If new subscriber or server objects are added later, the filters will have to be reconfigured again.
00113      *
00114      * @param mode Either: AcceptAnonymousMessages - the filters will accept all anonymous messages (this is default)
00115      *                     IgnoreAnonymousMessages - anonymous messages will be ignored
00116      * @return 0 = success, negative for error.
00117      */
00118     int computeConfiguration(AnonymousMessages mode = AcceptAnonymousMessages);
00119 
00120     /**
00121      * Add an additional filter configuration.
00122      * This method must not be invoked after @ref computeConfiguration().
00123      * @return 0 = success, negative for error.
00124      */
00125     int addFilterConfig(const CanFilterConfig& config);
00126 
00127     /**
00128      * This method loads the configuration computed with mergeConfigurations() or explicitly added by addFilterConfig()
00129      * to the CAN driver. Must be called after computeConfiguration() and addFilterConfig().
00130      * @return 0 = success, negative for error.
00131      */
00132     int applyConfiguration();
00133 
00134     /**
00135      * Returns the configuration computed with mergeConfigurations() or added by addFilterConfig().
00136      * If mergeConfigurations() or addFilterConfig() have not been called yet, an empty configuration will be returned.
00137      */
00138     const MultisetConfigContainer & getConfiguration() const
00139     {
00140         return multiset_configs_;
00141     }
00142 };
00143 
00144 /**
00145  * This function is a shortcut for @ref CanAcceptanceFilterConfigurator.
00146  * It allows to compute filter configuration and then apply it in just one step.
00147  * It implements only the most common use case; if you have special requirements,
00148  * use @ref CanAcceptanceFilterConfigurator directly.
00149  *
00150  * @param node  Refer to @ref CanAcceptanceFilterConfigurator constructor for explanation.
00151  * @param mode  Refer to @ref CanAcceptanceFilterConfigurator::computeConfiguration() for explanation.
00152  * @return non-negative on success, negative error code on error.
00153  */
00154 static inline int configureCanAcceptanceFilters(INode& node,
00155                                                 CanAcceptanceFilterConfigurator::AnonymousMessages mode
00156                                                     = CanAcceptanceFilterConfigurator::AcceptAnonymousMessages)
00157 {
00158     CanAcceptanceFilterConfigurator cfger(node);
00159 
00160     const int compute_res = cfger.computeConfiguration(mode);
00161     if (compute_res < 0)
00162     {
00163         return compute_res;
00164     }
00165 
00166     return cfger.applyConfiguration();
00167 }
00168 
00169 }
00170 
00171 #endif