canard.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * Copyright (c) 2016-2019 UAVCAN Team
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. *
  22. * Contributors: https://github.com/UAVCAN/libcanard/contributors
  23. *
  24. * Documentation: http://uavcan.org/Implementations/Libcanard
  25. */
  26. #ifndef CANARD_H
  27. #define CANARD_H
  28. #include <stdint.h>
  29. #include <stddef.h>
  30. #include <stdbool.h>
  31. #include <assert.h>
  32. /// Build configuration header. Use it to provide your overrides.
  33. #if defined(CANARD_ENABLE_CUSTOM_BUILD_CONFIG) && CANARD_ENABLE_CUSTOM_BUILD_CONFIG
  34. # include "canard_build_config.h"
  35. #endif
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. /// Libcanard version. API will be backwards compatible within the same major version.
  40. #define CANARD_VERSION_MAJOR 0
  41. #define CANARD_VERSION_MINOR 2
  42. /// By default this macro resolves to the standard assert(). The user can redefine this if necessary.
  43. #ifndef CANARD_ASSERT
  44. # define CANARD_ASSERT(x) assert(x)
  45. #endif
  46. #define CANARD_GLUE(a, b) CANARD_GLUE_IMPL_(a, b)
  47. #define CANARD_GLUE_IMPL_(a, b) a##b
  48. /// By default this macro expands to static_assert if supported by the language (C11, C++11, or newer).
  49. /// The user can redefine this if necessary.
  50. #ifndef CANARD_STATIC_ASSERT
  51. # if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) ||\
  52. (defined(__cplusplus) && (__cplusplus >= 201103L))
  53. # define CANARD_STATIC_ASSERT(...) static_assert(__VA_ARGS__)
  54. # else
  55. # define CANARD_STATIC_ASSERT(x, ...) typedef char CANARD_GLUE(_static_assertion_, __LINE__)[(x) ? 1 : -1]
  56. # endif
  57. #endif
  58. /// Error code definitions; inverse of these values may be returned from API calls.
  59. #define CANARD_OK 0
  60. // Value 1 is omitted intentionally, since -1 is often used in 3rd party code
  61. #define CANARD_ERROR_INVALID_ARGUMENT 2
  62. #define CANARD_ERROR_OUT_OF_MEMORY 3
  63. #define CANARD_ERROR_NODE_ID_NOT_SET 4
  64. #define CANARD_ERROR_INTERNAL 9
  65. #define CANARD_ERROR_RX_INCOMPATIBLE_PACKET 10
  66. #define CANARD_ERROR_RX_WRONG_ADDRESS 11
  67. #define CANARD_ERROR_RX_NOT_WANTED 12
  68. #define CANARD_ERROR_RX_MISSED_START 13
  69. #define CANARD_ERROR_RX_WRONG_TOGGLE 14
  70. #define CANARD_ERROR_RX_UNEXPECTED_TID 15
  71. #define CANARD_ERROR_RX_SHORT_FRAME 16
  72. #define CANARD_ERROR_RX_BAD_CRC 17
  73. /// The size of a memory block in bytes.
  74. #define CANARD_MEM_BLOCK_SIZE 32U
  75. /// This will be changed when the support for CAN FD is added
  76. #define CANARD_CAN_FRAME_MAX_DATA_LEN 8U
  77. /// Node ID values. Refer to the specification for more info.
  78. #define CANARD_BROADCAST_NODE_ID 0
  79. #define CANARD_MIN_NODE_ID 1
  80. #define CANARD_MAX_NODE_ID 127
  81. /// Refer to the type CanardRxTransfer
  82. #define CANARD_MULTIFRAME_RX_PAYLOAD_HEAD_SIZE (CANARD_MEM_BLOCK_SIZE - offsetof(CanardRxState, buffer_head))
  83. /// Refer to the type CanardBufferBlock
  84. #define CANARD_BUFFER_BLOCK_DATA_SIZE (CANARD_MEM_BLOCK_SIZE - offsetof(CanardBufferBlock, data))
  85. /// Refer to canardCleanupStaleTransfers() for details.
  86. #define CANARD_RECOMMENDED_STALE_TRANSFER_CLEANUP_INTERVAL_USEC 1000000U
  87. /// Transfer priority definitions
  88. #define CANARD_TRANSFER_PRIORITY_HIGHEST 0
  89. #define CANARD_TRANSFER_PRIORITY_HIGH 8
  90. #define CANARD_TRANSFER_PRIORITY_MEDIUM 16
  91. #define CANARD_TRANSFER_PRIORITY_LOW 24
  92. #define CANARD_TRANSFER_PRIORITY_LOWEST 31
  93. /// Related to CanardCANFrame
  94. #define CANARD_CAN_EXT_ID_MASK 0x1FFFFFFFU
  95. #define CANARD_CAN_STD_ID_MASK 0x000007FFU
  96. #define CANARD_CAN_FRAME_EFF (1UL << 31U) ///< Extended frame format
  97. #define CANARD_CAN_FRAME_RTR (1UL << 30U) ///< Remote transmission (not used by UAVCAN)
  98. #define CANARD_CAN_FRAME_ERR (1UL << 29U) ///< Error frame (not used by UAVCAN)
  99. #define CANARD_TRANSFER_PAYLOAD_LEN_BITS 10U
  100. #define CANARD_MAX_TRANSFER_PAYLOAD_LEN ((1U << CANARD_TRANSFER_PAYLOAD_LEN_BITS) - 1U)
  101. /**
  102. * This data type holds a standard CAN 2.0B data frame with 29-bit ID.
  103. */
  104. typedef struct
  105. {
  106. /**
  107. * Refer to the following definitions:
  108. * - CANARD_CAN_FRAME_EFF
  109. * - CANARD_CAN_FRAME_RTR
  110. * - CANARD_CAN_FRAME_ERR
  111. */
  112. uint32_t id;
  113. uint8_t data[CANARD_CAN_FRAME_MAX_DATA_LEN];
  114. uint8_t data_len;
  115. } CanardCANFrame;
  116. /**
  117. * Transfer types are defined by the UAVCAN specification.
  118. */
  119. typedef enum
  120. {
  121. CanardTransferTypeResponse = 0,
  122. CanardTransferTypeRequest = 1,
  123. CanardTransferTypeBroadcast = 2
  124. } CanardTransferType;
  125. /**
  126. * Types of service transfers. These are not applicable to message transfers.
  127. */
  128. typedef enum
  129. {
  130. CanardResponse,
  131. CanardRequest
  132. } CanardRequestResponse;
  133. /*
  134. * Forward declarations.
  135. */
  136. typedef struct CanardInstance CanardInstance;
  137. typedef struct CanardRxTransfer CanardRxTransfer;
  138. typedef struct CanardRxState CanardRxState;
  139. typedef struct CanardTxQueueItem CanardTxQueueItem;
  140. /**
  141. * The application must implement this function and supply a pointer to it to the library during initialization.
  142. * The library calls this function to determine whether the transfer should be received.
  143. *
  144. * If the application returns true, the value pointed to by 'out_data_type_signature' must be initialized with the
  145. * correct data type signature, otherwise transfer reception will fail with CRC mismatch error. Please refer to the
  146. * specification for more details about data type signatures. Signature for any data type can be obtained in many
  147. * ways; for example, using the command line tool distributed with Libcanard (see the repository).
  148. */
  149. typedef bool (* CanardShouldAcceptTransfer)(const CanardInstance* ins, ///< Library instance
  150. uint64_t* out_data_type_signature, ///< Must be set by the application!
  151. uint16_t data_type_id, ///< Refer to the specification
  152. CanardTransferType transfer_type, ///< Refer to CanardTransferType
  153. uint8_t source_node_id); ///< Source node ID or Broadcast (0)
  154. /**
  155. * This function will be invoked by the library every time a transfer is successfully received.
  156. * If the application needs to send another transfer from this callback, it is highly recommended
  157. * to call canardReleaseRxTransferPayload() first, so that the memory that was used for the block
  158. * buffer can be released and re-used by the TX queue.
  159. */
  160. typedef void (* CanardOnTransferReception)(CanardInstance* ins, ///< Library instance
  161. CanardRxTransfer* transfer); ///< Ptr to temporary transfer object
  162. /**
  163. * INTERNAL DEFINITION, DO NOT USE DIRECTLY.
  164. * A memory block used in the memory block allocator.
  165. */
  166. typedef union CanardPoolAllocatorBlock_u
  167. {
  168. char bytes[CANARD_MEM_BLOCK_SIZE];
  169. union CanardPoolAllocatorBlock_u* next;
  170. } CanardPoolAllocatorBlock;
  171. /**
  172. * This structure provides usage statistics of the memory pool allocator.
  173. * This data helps to evaluate whether the allocated memory is sufficient for the application.
  174. */
  175. typedef struct
  176. {
  177. uint16_t capacity_blocks; ///< Pool capacity in number of blocks
  178. uint16_t current_usage_blocks; ///< Number of blocks that are currently allocated by the library
  179. uint16_t peak_usage_blocks; ///< Maximum number of blocks used since initialization
  180. } CanardPoolAllocatorStatistics;
  181. /**
  182. * INTERNAL DEFINITION, DO NOT USE DIRECTLY.
  183. */
  184. typedef struct
  185. {
  186. CanardPoolAllocatorBlock* free_list;
  187. CanardPoolAllocatorStatistics statistics;
  188. } CanardPoolAllocator;
  189. /**
  190. * INTERNAL DEFINITION, DO NOT USE DIRECTLY.
  191. * Buffer block for received data.
  192. */
  193. typedef struct CanardBufferBlock
  194. {
  195. struct CanardBufferBlock* next;
  196. uint8_t data[];
  197. } CanardBufferBlock;
  198. /**
  199. * INTERNAL DEFINITION, DO NOT USE DIRECTLY.
  200. */
  201. struct CanardRxState
  202. {
  203. struct CanardRxState* next;
  204. CanardBufferBlock* buffer_blocks;
  205. uint64_t timestamp_usec;
  206. const uint32_t dtid_tt_snid_dnid;
  207. // We're using plain 'unsigned' here, because C99 doesn't permit explicit field type specification
  208. unsigned calculated_crc : 16;
  209. unsigned payload_len : CANARD_TRANSFER_PAYLOAD_LEN_BITS;
  210. unsigned transfer_id : 5;
  211. unsigned next_toggle : 1; // 16+10+5+1 = 32, aligned.
  212. uint16_t payload_crc;
  213. uint8_t buffer_head[];
  214. };
  215. CANARD_STATIC_ASSERT(offsetof(CanardRxState, buffer_head) <= 28, "Invalid memory layout");
  216. CANARD_STATIC_ASSERT(CANARD_MULTIFRAME_RX_PAYLOAD_HEAD_SIZE >= 4, "Invalid memory layout");
  217. /**
  218. * This is the core structure that keeps all of the states and allocated resources of the library instance.
  219. * The application should never access any of the fields directly! Instead, API functions should be used.
  220. */
  221. struct CanardInstance
  222. {
  223. uint8_t node_id; ///< Local node ID; may be zero if the node is anonymous
  224. CanardShouldAcceptTransfer should_accept; ///< Function to decide whether the application wants this transfer
  225. CanardOnTransferReception on_reception; ///< Function the library calls after RX transfer is complete
  226. CanardPoolAllocator allocator; ///< Pool allocator
  227. CanardRxState* rx_states; ///< RX transfer states
  228. CanardTxQueueItem* tx_queue; ///< TX frames awaiting transmission
  229. void* user_reference; ///< User pointer that can link this instance with other objects
  230. };
  231. /**
  232. * This structure represents a received transfer for the application.
  233. * An instance of it is passed to the application via callback when the library receives a new transfer.
  234. * Pointers to the structure and all its fields are invalidated after the callback returns.
  235. */
  236. struct CanardRxTransfer
  237. {
  238. /**
  239. * Timestamp at which the first frame of this transfer was received.
  240. */
  241. uint64_t timestamp_usec;
  242. /**
  243. * Payload is scattered across three storages:
  244. * - Head points to CanardRxState.buffer_head (length of which is up to CANARD_PAYLOAD_HEAD_SIZE), or to the
  245. * payload field (possibly with offset) of the last received CAN frame.
  246. *
  247. * - Middle is located in the linked list of dynamic blocks (only for multi-frame transfers).
  248. *
  249. * - Tail points to the payload field (possibly with offset) of the last received CAN frame
  250. * (only for multi-frame transfers).
  251. *
  252. * The tail offset depends on how much data of the last frame was accommodated in the last allocated block.
  253. *
  254. * For single-frame transfers, middle and tail will be NULL, and the head will point at first byte
  255. * of the payload of the CAN frame.
  256. *
  257. * In simple cases it should be possible to get data directly from the head and/or tail pointers.
  258. * Otherwise it is advised to use canardDecodeScalar().
  259. */
  260. const uint8_t* payload_head; ///< Always valid, i.e. not NULL.
  261. ///< For multi frame transfers, the maximum size is defined in the constant
  262. ///< CANARD_MULTIFRAME_RX_PAYLOAD_HEAD_SIZE.
  263. ///< For single-frame transfers, the size is defined in the
  264. ///< field payload_len.
  265. CanardBufferBlock* payload_middle; ///< May be NULL if the buffer was not needed. Always NULL for single-frame
  266. ///< transfers.
  267. const uint8_t* payload_tail; ///< Last bytes of multi-frame transfers. Always NULL for single-frame
  268. ///< transfers.
  269. uint16_t payload_len; ///< Effective length of the payload in bytes.
  270. /**
  271. * These fields identify the transfer for the application.
  272. */
  273. uint16_t data_type_id; ///< 0 to 255 for services, 0 to 65535 for messages
  274. uint8_t transfer_type; ///< See CanardTransferType
  275. uint8_t transfer_id; ///< 0 to 31
  276. uint8_t priority; ///< 0 to 31
  277. uint8_t source_node_id; ///< 1 to 127, or 0 if the source is anonymous
  278. };
  279. /**
  280. * Initializes a library instance.
  281. * Local node ID will be set to zero, i.e. the node will be anonymous.
  282. *
  283. * Typically, size of the memory pool should not be less than 1K, although it depends on the application. The
  284. * recommended way to detect the required pool size is to measure the peak pool usage after a stress-test. Refer to
  285. * the function canardGetPoolAllocatorStatistics().
  286. */
  287. void canardInit(CanardInstance* out_ins, ///< Uninitialized library instance
  288. void* mem_arena, ///< Raw memory chunk used for dynamic allocation
  289. size_t mem_arena_size, ///< Size of the above, in bytes
  290. CanardOnTransferReception on_reception, ///< Callback, see CanardOnTransferReception
  291. CanardShouldAcceptTransfer should_accept, ///< Callback, see CanardShouldAcceptTransfer
  292. void* user_reference); ///< Optional pointer for user's convenience, can be NULL
  293. /**
  294. * Returns the value of the user pointer.
  295. * The user pointer is configured once during initialization.
  296. * It can be used to store references to any user-specific data, or to link the instance object with C++ objects.
  297. */
  298. void* canardGetUserReference(CanardInstance* ins);
  299. /**
  300. * Assigns a new node ID value to the current node.
  301. * Node ID can be assigned only once.
  302. */
  303. void canardSetLocalNodeID(CanardInstance* ins,
  304. uint8_t self_node_id);
  305. /**
  306. * Returns node ID of the local node.
  307. * Returns zero (broadcast) if the node ID is not set, i.e. if the local node is anonymous.
  308. */
  309. uint8_t canardGetLocalNodeID(const CanardInstance* ins);
  310. /**
  311. * Sends a broadcast transfer.
  312. * If the node is in passive mode, only single frame transfers will be allowed (they will be transmitted as anonymous).
  313. *
  314. * For anonymous transfers, maximum data type ID is limited to 3 (see specification for details).
  315. *
  316. * Please refer to the specification for more details about data type signatures. Signature for any data type can be
  317. * obtained in many ways; for example, using the command line tool distributed with Libcanard (see the repository).
  318. *
  319. * Pointer to the Transfer ID should point to a persistent variable (e.g. static or heap allocated, not on the stack);
  320. * it will be updated by the library after every transmission. The Transfer ID value cannot be shared between
  321. * transfers that have different descriptors! More on this in the transport layer specification.
  322. *
  323. * Returns the number of frames enqueued, or negative error code.
  324. */
  325. int16_t canardBroadcast(CanardInstance* ins, ///< Library instance
  326. uint64_t data_type_signature, ///< See above
  327. uint16_t data_type_id, ///< Refer to the specification
  328. uint8_t* inout_transfer_id, ///< Pointer to a persistent variable containing the transfer ID
  329. uint8_t priority, ///< Refer to definitions CANARD_TRANSFER_PRIORITY_*
  330. const void* payload, ///< Transfer payload
  331. uint16_t payload_len); ///< Length of the above, in bytes
  332. /**
  333. * Sends a request or a response transfer.
  334. * Fails if the node is in passive mode.
  335. *
  336. * Please refer to the specification for more details about data type signatures. Signature for any data type can be
  337. * obtained in many ways; for example, using the command line tool distributed with Libcanard (see the repository).
  338. *
  339. * For Request transfers, the pointer to the Transfer ID should point to a persistent variable (e.g. static or heap
  340. * allocated, not on the stack); it will be updated by the library after every request. The Transfer ID value
  341. * cannot be shared between requests that have different descriptors! More on this in the transport layer
  342. * specification.
  343. *
  344. * For Response transfers, the pointer to the Transfer ID will be treated as const (i.e. read-only), and normally it
  345. * should point to the transfer_id field of the structure CanardRxTransfer.
  346. *
  347. * Returns the number of frames enqueued, or negative error code.
  348. */
  349. int16_t canardRequestOrRespond(CanardInstance* ins, ///< Library instance
  350. uint8_t destination_node_id, ///< Node ID of the server/client
  351. uint64_t data_type_signature, ///< See above
  352. uint8_t data_type_id, ///< Refer to the specification
  353. uint8_t* inout_transfer_id, ///< Pointer to a persistent variable with transfer ID
  354. uint8_t priority, ///< Refer to definitions CANARD_TRANSFER_PRIORITY_*
  355. CanardRequestResponse kind, ///< Refer to CanardRequestResponse
  356. const void* payload, ///< Transfer payload
  357. uint16_t payload_len); ///< Length of the above, in bytes
  358. /**
  359. * Returns a pointer to the top priority frame in the TX queue.
  360. * Returns NULL if the TX queue is empty.
  361. * The application will call this function after canardBroadcast() or canardRequestOrRespond() to transmit generated
  362. * frames over the CAN bus.
  363. */
  364. const CanardCANFrame* canardPeekTxQueue(const CanardInstance* ins);
  365. /**
  366. * Removes the top priority frame from the TX queue.
  367. * The application will call this function after canardPeekTxQueue() once the obtained frame has been processed.
  368. * Calling canardBroadcast() or canardRequestOrRespond() between canardPeekTxQueue() and canardPopTxQueue()
  369. * is NOT allowed, because it may change the frame at the top of the TX queue.
  370. */
  371. void canardPopTxQueue(CanardInstance* ins);
  372. /**
  373. * Processes a received CAN frame with a timestamp.
  374. * The application will call this function when it receives a new frame from the CAN bus.
  375. *
  376. * Return value will report any errors in decoding packets.
  377. */
  378. int16_t canardHandleRxFrame(CanardInstance* ins,
  379. const CanardCANFrame* frame,
  380. uint64_t timestamp_usec);
  381. /**
  382. * Traverses the list of transfers and removes those that were last updated more than timeout_usec microseconds ago.
  383. * This function must be invoked by the application periodically, about once a second.
  384. * Also refer to the constant CANARD_RECOMMENDED_STALE_TRANSFER_CLEANUP_INTERVAL_USEC.
  385. */
  386. void canardCleanupStaleTransfers(CanardInstance* ins,
  387. uint64_t current_time_usec);
  388. /**
  389. * This function can be used to extract values from received UAVCAN transfers. It decodes a scalar value -
  390. * boolean, integer, character, or floating point - from the specified bit position in the RX transfer buffer.
  391. * Simple single-frame transfers can also be parsed manually.
  392. *
  393. * Returns the number of bits successfully decoded, which may be less than requested if operation ran out of
  394. * buffer boundaries, or negated error code, such as invalid argument.
  395. *
  396. * Caveat: This function works correctly only on platforms that use two's complement signed integer representation.
  397. * I am not aware of any modern microarchitecture that uses anything else than two's complement, so it should
  398. * not affect portability in any way.
  399. *
  400. * The type of value pointed to by 'out_value' is defined as follows:
  401. *
  402. * | bit_length | value_is_signed | out_value points to |
  403. * |------------|-----------------|------------------------------------------|
  404. * | 1 | false | bool (may be incompatible with uint8_t!) |
  405. * | 1 | true | N/A |
  406. * | [2, 8] | false | uint8_t, or char |
  407. * | [2, 8] | true | int8_t, or char |
  408. * | [9, 16] | false | uint16_t |
  409. * | [9, 16] | true | int16_t |
  410. * | [17, 32] | false | uint32_t |
  411. * | [17, 32] | true | int32_t, or 32-bit float |
  412. * | [33, 64] | false | uint64_t |
  413. * | [33, 64] | true | int64_t, or 64-bit float |
  414. */
  415. int16_t canardDecodeScalar(const CanardRxTransfer* transfer, ///< The RX transfer where the data will be copied from
  416. uint32_t bit_offset, ///< Offset, in bits, from the beginning of the transfer
  417. uint8_t bit_length, ///< Length of the value, in bits; see the table
  418. bool value_is_signed, ///< True if the value can be negative; see the table
  419. void* out_value); ///< Pointer to the output storage; see the table
  420. /**
  421. * This function can be used to encode values for later transmission in a UAVCAN transfer. It encodes a scalar value -
  422. * boolean, integer, character, or floating point - and puts it to the specified bit position in the specified
  423. * contiguous buffer.
  424. * Simple single-frame transfers can also be encoded manually.
  425. *
  426. * Caveat: This function works correctly only on platforms that use two's complement signed integer representation.
  427. * I am not aware of any modern microarchitecture that uses anything else than two's complement, so it should
  428. * not affect portability in any way.
  429. *
  430. * The type of value pointed to by 'value' is defined as follows:
  431. *
  432. * | bit_length | value points to |
  433. * |------------|------------------------------------------|
  434. * | 1 | bool (may be incompatible with uint8_t!) |
  435. * | [2, 8] | uint8_t, int8_t, or char |
  436. * | [9, 16] | uint16_t, int16_t |
  437. * | [17, 32] | uint32_t, int32_t, or 32-bit float |
  438. * | [33, 64] | uint64_t, int64_t, or 64-bit float |
  439. */
  440. void canardEncodeScalar(void* destination, ///< Destination buffer where the result will be stored
  441. uint32_t bit_offset, ///< Offset, in bits, from the beginning of the destination buffer
  442. uint8_t bit_length, ///< Length of the value, in bits; see the table
  443. const void* value); ///< Pointer to the value; see the table
  444. /**
  445. * This function can be invoked by the application to release pool blocks that are used
  446. * to store the payload of the transfer.
  447. *
  448. * If the application needs to send new transfers from the transfer reception callback, this function should be
  449. * invoked right before calling canardBroadcast() or canardRequestOrRespond(). Not releasing the buffers before
  450. * transmission may cause higher peak usage of the memory pool.
  451. *
  452. * If the application didn't call this function before returning from the callback, the library will do that,
  453. * so it is guaranteed that the memory will not leak.
  454. */
  455. void canardReleaseRxTransferPayload(CanardInstance* ins,
  456. CanardRxTransfer* transfer);
  457. /**
  458. * Returns a copy of the pool allocator usage statistics.
  459. * Refer to the type CanardPoolAllocatorStatistics.
  460. * Use this function to determine worst case memory needs of your application.
  461. */
  462. CanardPoolAllocatorStatistics canardGetPoolAllocatorStatistics(CanardInstance* ins);
  463. /**
  464. * Float16 marshaling helpers.
  465. * These functions convert between the native float and 16-bit float.
  466. * It is assumed that the native float is IEEE 754 single precision float, otherwise results will be unpredictable.
  467. * Vast majority of modern computers and microcontrollers use IEEE 754, so this limitation should not affect
  468. * portability.
  469. */
  470. uint16_t canardConvertNativeFloatToFloat16(float value);
  471. float canardConvertFloat16ToNativeFloat(uint16_t value);
  472. /// Abort the build if the current platform is not supported.
  473. CANARD_STATIC_ASSERT(((uint32_t)CANARD_MULTIFRAME_RX_PAYLOAD_HEAD_SIZE) < 32,
  474. "Platforms where sizeof(void*) > 4 are not supported. "
  475. "On AMD64 use 32-bit mode (e.g. GCC flag -m32).");
  476. #ifdef __cplusplus
  477. }
  478. #endif
  479. #endif