Paul Paterson / CanPipe Featured

Dependents:   CanPipe_Example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CanPipe.h Source File

CanPipe.h

00001 
00002 
00003 #ifndef CANPIPE_H
00004 #define CANPIPE_H
00005 
00006 #include "mbed.h"
00007 #include "CircularBuffer.h"
00008 
00009 /** Function pointer type for user to attach and handle CAN messages
00010  */
00011 typedef Callback<int(CANMessage&)> CanMessageCallback;
00012 
00013 /** A stack on top of mbed CAN class to handle complex filtered callbacks
00014  */
00015 class CanPipe
00016 {
00017 public:
00018     int temp_counter;
00019     /* Public Type definitions and forward declarations ***********************/
00020     /** Enumeration for method return values */
00021     enum CanPipeResult {
00022         kOkay = 0,
00023         kErrorCbNodeMemory,
00024         kErrorCbListMemory,
00025         kDone
00026     };
00027 
00028     /** Enumeration for how filters should be handled */
00029     enum FilterMode {
00030         kFilterAuto = 0,
00031         kFilterHardwareOnly,
00032         kFilterSoftwareOnly
00033     };
00034 
00035     /* Public Methods *********************************************************/
00036     /** Creates message handler linked with the CAN device
00037      *
00038      * @param p_can reference to CAN device
00039      * @param filter_mode hardware or software filtering only (Optional)
00040      *
00041      * Example:
00042      * @code
00043      * #include "mbed.h"
00044      * #include "CanPipe.h"
00045      *
00046      * Ticker ticker;
00047      * DigitalOut led1(LED1);
00048      *
00049      * CAN m_can(P0_11, P0_31);
00050      * CanPipe m_can_pipe(&m_can);
00051      *
00052      * char counter = 0;
00053      *
00054      * void send() {
00055      *     led1 = !led1;
00056      *     m_can_pipe.PostMessage(CANMessage(1337, &counter, 1));
00057      * }
00058      *
00059      * int callback1(CANMessage &msg) { return CanPipe::kOkay; }
00060      * int callback2(CANMessage &msg) { return CanPipe::kOkay; }
00061      * int callback3(CANMessage &msg) { return CanPipe::kOkay; }
00062      *
00063      * int main() {
00064      *     int handle;
00065      *
00066      *     handle = m_can_pipe.RegisterFilter(0x200, 0x780);
00067      *     m_can_pipe.RegisterCallback(callback1, handle);
00068      *
00069      *     handle = m_can_pipe.RegisterFilter(0x281, 0);
00070      *     m_can_pipe.RegisterCallback(callback2, handle);
00071      *     m_can_pipe.RegisterCallback(callback3, handle);
00072      *
00073      *     ticker.attach(send, 1);
00074      *
00075      *     while (1) {
00076      *         __WFI(); //sleep();
00077      *         m_can_pipe.HandleMessages();
00078      *     }
00079      * }
00080      * @endcode
00081      */
00082     CanPipe(CAN *p_can, FilterMode filter_mode = kFilterAuto);
00083 
00084     /** Assigns a filter to apply to CAN messages.
00085      * @param id 29 bit identifier to base filter on
00086      * @param mask Bit mask applied to the id
00087      * @param format CAN message format (Default CANAny)
00088      * @param handle Number to associate with message when passing this filter (Optional)
00089      *
00090      * Can create software filters if device fails to create filters in hardware
00091      */
00092     int RegisterFilter(unsigned int id, unsigned int mask, CANFormat format = CANAny, int handle = 0);
00093 
00094     /** Assigns a callback to apply to CAN messages associated with a given filter.
00095      * @param callback 29 bit identifier to base filter on
00096      * @param handle Filter handle to associate with this callback (Optional)
00097      *
00098      * Member functions can be added using the right callback Constructor
00099      * @code
00100      * canopen_class.RegisterCallback(
00101      *         CanMessageCallback(&object_instance, &ObjectClass::HandleMessage),
00102      *         handle);
00103      * @endcode
00104      */
00105     int RegisterCallback(CanMessageCallback callback, int handle);
00106 
00107     /** Stage a message to be written to the bus.
00108      *
00109      * @param msg message to write
00110      */
00111     void PostMessage(CANMessage msg);
00112 
00113     /** Passes all received messages through the software-filters, if any, and
00114      *  writes any messages that have been posted.
00115      *  @return Boolean 1 if a message was handled (post or receive).  0 otherwise.
00116      */
00117     int HandleMessages();
00118 
00119 private:
00120     /* Private Type definitions and forward declarations **********************/
00121     static const int kMaxHandles = 32;
00122     static const int kMaxCallbacks = 64;
00123 
00124     struct SoftwareFilter {
00125         unsigned int id;
00126         unsigned int mask;
00127         CANFormat format;
00128         int handle;
00129     };
00130 
00131     struct CallbackNode {
00132         CanMessageCallback callback;
00133         CallbackNode *next_node;
00134     };
00135 
00136     struct CallbackList {
00137         int handle;
00138         CallbackNode *begin;
00139     };
00140 
00141     /* Private Members ********************************************************/
00142     CAN *p_can_;
00143 
00144     FilterMode filter_mode_;
00145 
00146     SoftwareFilter software_filters_[kMaxHandles];
00147     CallbackNode callback_node_pool_[kMaxCallbacks];
00148     CallbackList callback_list_map_[kMaxHandles];
00149 
00150     int num_software_filters_;
00151     int num_nodes_;
00152     int num_lists_;
00153 
00154     CircularBuffer<CANMessage, 16> read_buffer;
00155     CircularBuffer<CANMessage, 16> write_buffer;
00156 
00157     /* Private Methods ********************************************************/
00158     void ReadIrq(void);
00159 
00160     int FilterMessage();
00161 
00162     CallbackNode* AllocateNode(CanMessageCallback callback);
00163     CallbackList* AllocateList(int handle);
00164 
00165     CallbackList* FindListWithHandle(int handle);
00166 };
00167 
00168 #endif /* CANPIPE_H */