Paul Paterson / CanPipe Featured

Dependents:   CanPipe_Example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CanPipe.cpp Source File

CanPipe.cpp

00001 #include "CanPipe.h"
00002 
00003 /* Public Methods ************************************************************/
00004 CanPipe::CanPipe(CAN *p_can, FilterMode filter_mode):
00005         p_can_(p_can),
00006         filter_mode_(filter_mode)
00007 {
00008     num_software_filters_ = 0;
00009     p_can_->attach<CanPipe>(this, &CanPipe::ReadIrq);
00010 }
00011 
00012 int CanPipe::RegisterFilter(unsigned int id,
00013         unsigned int mask,
00014         CANFormat format,
00015         int handle)
00016 {
00017     printf("CanPipe::RegisterCallback:\r\n");
00018     int retval = 0;
00019 
00020     switch (filter_mode_) {
00021         case kFilterHardwareOnly:
00022             //printf("creating hardware filter\r\n");
00023             retval = p_can_->filter(id, mask, format, handle);
00024             break;
00025         case kFilterAuto:
00026             //printf("creating hardware filter\r\n");
00027             retval = p_can_->filter(id, mask, format, handle);
00028             handle = retval;
00029         case kFilterSoftwareOnly:
00030             //printf("   creating software filter\r\n");
00031             if (num_software_filters_ < kMaxHandles) {
00032                 if (!handle) {
00033                     handle = 1;
00034                     for (int i_filter = 0; i_filter < num_software_filters_; ++i_filter) {
00035                         if (handle <= software_filters_[i_filter].handle) {
00036                             handle = software_filters_[i_filter].handle + 1;
00037                         }
00038                     }
00039                 }
00040                 SoftwareFilter new_filter = {id, mask, format, handle};
00041                 software_filters_[num_software_filters_++] = new_filter;
00042                 retval = handle;
00043             }
00044             break;
00045         default:
00046             break;
00047     }
00048     //printf("\r\n");
00049 
00050     return retval;
00051 }
00052 
00053 int CanPipe::RegisterCallback(CanMessageCallback callback, int handle) {
00054     printf("CanPipe::RegisterCallback:\r\n   handle: %d\r\n", handle);
00055     /* get new node from the pool */
00056     CallbackNode *new_node = AllocateNode(callback);
00057     if (!new_node)
00058         return kErrorCbNodeMemory;
00059 
00060     /* get the appropriate list */
00061     CallbackList *list = FindListWithHandle(handle);
00062     if (!list) {
00063         /* no list for handle yet.  Allocate it now */
00064         list = AllocateList(handle);
00065     }
00066     if (!list)
00067         return kErrorCbListMemory;
00068 
00069     /* add new node to list */
00070     if (list->begin) {
00071         /* append to the end */
00072         CallbackNode *node_iterator = list->begin;
00073         while (node_iterator->next_node) {
00074             node_iterator = node_iterator->next_node;
00075         }
00076         node_iterator->next_node = new_node;
00077     } else {
00078         /* this is the first node */
00079         list->begin = new_node;
00080     }
00081     return kOkay;
00082 }
00083 
00084 
00085 void CanPipe::PostMessage(CANMessage msg) {
00086     write_buffer.push(msg);
00087 }
00088 
00089 int CanPipe::HandleMessages(void) {
00090     int b_retval = 0; // boolean for whether or not a message was handled
00091 
00092     /* Perform callbacks for all received messages */
00093     CANMessage msg;
00094     while (read_buffer.pop(msg)) {
00095         b_retval = 1;
00096 
00097         printf("* Reading message 0x%03X\r\n", msg.id);
00098         int handle = 0;
00099 
00100         // software filters override any hardware filtering
00101         if (filter_mode_ == kFilterAuto || filter_mode_ == kFilterSoftwareOnly) {
00102             SoftwareFilter filter;
00103             for (int f = 0; f < num_software_filters_; ++f) {
00104                 filter = software_filters_[f];
00105                 if (filter.format == CANAny || msg.format == filter.format) {
00106                     if ((msg.id & filter.mask) == (filter.id & filter.mask)) {
00107                         handle = filter.handle;
00108                         break;
00109                     }
00110                 }
00111             }
00112         }
00113 
00114         CallbackList *callback_list = FindListWithHandle(handle);
00115         if (!callback_list)
00116             return 0; 
00117 
00118         CallbackNode *node_iterator = callback_list->begin;
00119         while (node_iterator) {
00120             int result = node_iterator->callback(msg);
00121 
00122             /* if an error occurred or callback claims to have completed message
00123              * handling, then leave the message chain.
00124              */
00125             if (result) {
00126                 break;
00127             } else {
00128                 node_iterator = node_iterator->next_node;
00129             }
00130         }
00131     }
00132 
00133     /* Write all posted messages to the bus */
00134     CANMessage write_msg;
00135     while (write_buffer.pop(write_msg)) {
00136         b_retval = 1;
00137         if (p_can_->write(write_msg)) {
00138             /* Do something */
00139         } else {
00140             /* Do something */
00141         }
00142     }
00143 
00144     return b_retval;
00145 }
00146 
00147 /* Private Methods ************************************************************/
00148 void CanPipe::ReadIrq(void) {
00149 
00150 // LPC15xx specific ============================================================
00151     uint32_t can_int = LPC_C_CAN0->CANINT;
00152     uint32_t can_status = LPC_C_CAN0->CANSTAT; /* Reading clears the interrupt */
00153     if (can_int & 0x8000) {
00154         // TODO: React to status changes
00155     }
00156 // END LPC15xx specific ========================================================
00157 
00158     CANMessage msg;
00159     if (p_can_->read(msg)){
00160         // TODO:  raise flag if buffer is full
00161         read_buffer.push(msg);
00162     }
00163 }
00164 
00165 CanPipe::CallbackNode* CanPipe::AllocateNode(CanMessageCallback callback) {
00166     CallbackNode* result = 0;
00167     if (num_nodes_ < kMaxCallbacks) {
00168         result = &callback_node_pool_[num_nodes_++];
00169         result->callback = callback;
00170     }
00171     return result;
00172 }
00173 
00174 CanPipe::CallbackList* CanPipe::AllocateList(int handle) {
00175     CallbackList* result = 0;
00176     if (num_lists_ < kMaxHandles) {
00177         result = &callback_list_map_[num_lists_++];
00178         result->handle = handle;
00179     }
00180     return result;
00181 }
00182 
00183 CanPipe::CallbackList* CanPipe::FindListWithHandle(int handle) {
00184     CallbackList* result = 0;
00185     /* iterate over all of the lists */
00186     for (int i = 0; i < num_lists_; ++i) {
00187         if (callback_list_map_[i].handle == handle) {
00188             result = &callback_list_map_[i];
00189             break;
00190         }
00191     }
00192     return result;
00193 }