Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : /* 16 : CANSensor class, for easy creation of CAN sensors using custom CAN protocols 17 : */ 18 : 19 : #pragma once 20 : 21 : #include "AP_CAN.h" 22 : #include "AP_CANDriver.h" 23 : #ifndef HAL_BUILD_AP_PERIPH 24 : #include "AP_CANManager.h" 25 : #endif 26 : 27 : #if HAL_MAX_CAN_PROTOCOL_DRIVERS 28 : 29 : class CANSensor : public AP_CANDriver { 30 : public: 31 : CANSensor(const char *driver_name, uint16_t stack_size=2048); 32 : 33 : /* Do not allow copies */ 34 : CLASS_NO_COPY(CANSensor); 35 : 36 : void init(uint8_t driver_index) override; 37 : bool add_interface(AP_HAL::CANIface* can_iface) override; 38 : 39 : // Return true if this sensor has been successfully registered to a driver and initialized. 40 0 : bool initialized() const { return _initialized; } 41 : 42 : // handler for incoming frames 43 : virtual void handle_frame(AP_HAL::CANFrame &frame) = 0; 44 : 45 : // handler for outgoing frames 46 : bool write_frame(AP_HAL::CANFrame &out_frame, const uint32_t timeout_us); 47 : 48 : #ifdef HAL_BUILD_AP_PERIPH 49 : static void set_periph(const uint8_t i, const AP_CAN::Protocol protocol, AP_HAL::CANIface* iface) { 50 : if (i < ARRAY_SIZE(_periph)) { 51 : _periph[i].protocol = protocol; 52 : _periph[i].iface = iface; 53 : } 54 : } 55 : 56 : // return driver type index i 57 : static AP_CAN::Protocol get_driver_type(const uint8_t i) 58 : { 59 : if (i < ARRAY_SIZE(_periph)) { 60 : return _periph[i].protocol; 61 : } 62 : return AP_CAN::Protocol::None; 63 : } 64 : #else 65 4172 : static AP_CAN::Protocol get_driver_type(const uint8_t i) { return AP::can().get_driver_type(i); } 66 : #endif 67 : 68 : protected: 69 : void register_driver(AP_CAN::Protocol dtype); 70 : 71 : private: 72 : void loop(); 73 : 74 : const char *const _driver_name; 75 : const uint16_t _stack_size; 76 : bool _initialized; 77 : uint8_t _driver_index; 78 : 79 : // this is true when we are setup as an auxillary driver using CAN_Dn_PROTOCOL2 80 : bool is_aux_11bit_driver; 81 : 82 : AP_CANDriver *_can_driver; 83 : HAL_BinarySemaphore sem_handle; 84 : AP_HAL::CANIface* _can_iface; 85 : 86 : #ifdef HAL_BUILD_AP_PERIPH 87 : void register_driver_periph(const AP_CAN::Protocol dtype); 88 : 89 : struct CANSensor_Periph { 90 : AP_HAL::CANIface* iface; 91 : AP_CAN::Protocol protocol; 92 : } static _periph[HAL_NUM_CAN_IFACES]; 93 : #endif 94 : }; 95 : 96 : // a class to allow for multiple CAN backends with one 97 : // CANSensor driver. This can be shared among different libraries like rangefinder and proximity 98 : class MultiCAN : public CANSensor { 99 : public: 100 : // callback functor def for forwarding frames 101 : FUNCTOR_TYPEDEF(ForwardCanFrame, bool, AP_HAL::CANFrame &); 102 : 103 : MultiCAN(ForwardCanFrame cf, AP_CAN::Protocol can_type, const char *driver_name); 104 : 105 : // handle a received frame from the CAN bus 106 : void handle_frame(AP_HAL::CANFrame &frame) override; 107 : 108 : private: 109 : // class to allow for multiple callbacks implemented as a linked list 110 : class MultiCANLinkedList { 111 : public: 112 : struct CANSensor_Multi { 113 : ForwardCanFrame _callback; 114 : CANSensor_Multi* next = nullptr; 115 : }; 116 : 117 : // register a callback for a CAN frame by adding it to the linked list 118 : void register_callback(ForwardCanFrame callback); 119 : 120 : // distribute the CAN frame to the registered callbacks 121 : void handle_frame(AP_HAL::CANFrame &frame); 122 : HAL_Semaphore sem; 123 : 124 : private: 125 : CANSensor_Multi* head = nullptr; 126 : }; 127 : 128 : // Pointer to static instance of the linked list for persistence across instances 129 : static MultiCANLinkedList* callbacks; 130 : }; 131 : 132 : #endif // HAL_MAX_CAN_PROTOCOL_DRIVERS 133 :