<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.paparazziuav.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lida2003</id>
	<title>PaparazziUAV - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.paparazziuav.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lida2003"/>
	<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/wiki/Special:Contributions/Lida2003"/>
	<updated>2026-05-19T23:03:06Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26122</id>
		<title>ABI</title>
		<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26122"/>
		<updated>2022-04-13T07:37:00Z</updated>

		<summary type="html">&lt;p&gt;Lida2003: change abi.h #include location&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page presents some idea for an embedded middleware named ABI based on publish/subscribe like Ivy.&lt;br /&gt;
&lt;br /&gt;
= General idea =&lt;br /&gt;
&lt;br /&gt;
*Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.&lt;br /&gt;
*The components don't need to know each other, they only need the message format.&lt;br /&gt;
*Each subscriber set a callback function that will be called when new data are sent.&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== Message definition ==&lt;br /&gt;
&lt;br /&gt;
The messages are described in ''conf/abi.xml'' analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. &amp;quot;type&amp;quot; field should be a real C type. Field name might be useless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;class name=&amp;quot;airborne&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;message name=&amp;quot;DATA&amp;quot; id=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;a&amp;quot; type=&amp;quot;float&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;b&amp;quot; type=&amp;quot;struct bla&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
 &amp;lt;/class&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code generation ==&lt;br /&gt;
&lt;br /&gt;
The generated code will be in var/include/abi_messages.h and include some structure definition from sw/airborne/modules/core/abi_common.h (sw/airborne/modules/core/abi.h is a convenience header that only includes var/include/abi_messages.h). Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.&lt;br /&gt;
&lt;br /&gt;
 // Code in abi_common.h&lt;br /&gt;
 // Here, include header custom structures you may want to use in ABI messages&lt;br /&gt;
 // Default is to include pprz algebra libraries&lt;br /&gt;
 &lt;br /&gt;
 typedef void (*abi_callback)(void); // Generic callback definition&lt;br /&gt;
 &lt;br /&gt;
 struct _abi_event_struct {&lt;br /&gt;
  uint8_t id;&lt;br /&gt;
  abi_callback cb;&lt;br /&gt;
  struct _abi_event_struct * next;&lt;br /&gt;
 };&lt;br /&gt;
 typedef struct _abi_event_struct abi_event;&lt;br /&gt;
 &lt;br /&gt;
 #ifdef ABI_C&lt;br /&gt;
 #define ABI_EXTERN&lt;br /&gt;
 #else&lt;br /&gt;
 #define ABI_EXTERN extern&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 #define ABI_FOREACH(head,el) for(el=head; el; el=el-&amp;gt;next)&lt;br /&gt;
 #define ABI_PREPEND(head,new) { (add)-&amp;gt;next = head; head = add; }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // Code generated in var/include/abi_messages.h&lt;br /&gt;
 #include &amp;quot;modules/core/abi_common.h&amp;quot;&lt;br /&gt;
 // Message IDs&lt;br /&gt;
 #define DATA_ID 0&lt;br /&gt;
 &lt;br /&gt;
 // Callbacks&lt;br /&gt;
 typedef void (*abi_callbackDATA)(uint8_t sender_id, const float * a, const struct bla * b); // Specific callback for DATA message (arguments are const to prevent modifying them)&lt;br /&gt;
 &lt;br /&gt;
 // Array and linked list&lt;br /&gt;
 #define ABI_MESSAGE_NB &amp;lt;highest id of the messages in airborne class + 1&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 EXTERN abi_event abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file&lt;br /&gt;
 &lt;br /&gt;
 // Bind and Send for each messages&lt;br /&gt;
 static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {&lt;br /&gt;
  ev-&amp;gt;id = sender_id; // Store sender ID&lt;br /&gt;
  ev-&amp;gt;cb = (abi_callback)cb; // Store callback&lt;br /&gt;
  ABI_PREPEND(abi_queues[DATA_ID],ev); // add to the head of the list (because I'm lazy)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 static inline void AbiSendMsgDATA(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // Call all callback functions&lt;br /&gt;
  abi_event* e;&lt;br /&gt;
  ABI_FOREACH(abi_queues[DATA_ID],e) {&lt;br /&gt;
   if (e-&amp;gt;id == ABI_BROADCAST || e-&amp;gt;id == sender_id) { // call function only if selected source or broadcast address&lt;br /&gt;
    abi_callbackDATA cb = (abi_callbackDATA)(e-&amp;gt;cb); // C black magic&lt;br /&gt;
    cb(sender_id, a, b);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Airborne code for main AP ==&lt;br /&gt;
&lt;br /&gt;
This part of the code should be written and called only once in a .c file (like main.c, but it can be somewhere else)&lt;br /&gt;
&lt;br /&gt;
 #define ABI_C 1&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Airborne code for subscriber ==&lt;br /&gt;
&lt;br /&gt;
Include header and declare an abi_event as a global variable. Write the callback function with the proper prototype.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 abi_event ev;&lt;br /&gt;
 &lt;br /&gt;
 void data_cb(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // do something here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the initialization function (or later) call the binding functions for the message you want to receive. ABI_BROADCAST is a macro equals to 0 and is used as a broadcast address, which means that input values will be received from all sources for this message.&lt;br /&gt;
&lt;br /&gt;
 AbiBindMsgDATA(ABI_BROADCAST, &amp;amp;ev, data_cb);&lt;br /&gt;
&lt;br /&gt;
== Airborne code for publisher ==&lt;br /&gt;
&lt;br /&gt;
Include header of course.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In any function, call the send function. Sender id 0 is reserved (broadcast address).&lt;br /&gt;
&lt;br /&gt;
 #define SENDER_ID 1&lt;br /&gt;
 float var = 2.;&lt;br /&gt;
 struct bla s;&lt;br /&gt;
 AbiSendMsgDATA(SENDER_ID, &amp;amp;var, &amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That's it !&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer_Documentation]]&lt;/div&gt;</summary>
		<author><name>Lida2003</name></author>
	</entry>
	<entry>
		<id>http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26121</id>
		<title>ABI</title>
		<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26121"/>
		<updated>2022-04-13T07:36:33Z</updated>

		<summary type="html">&lt;p&gt;Lida2003: change abi.h #include location&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page presents some idea for an embedded middleware named ABI based on publish/subscribe like Ivy.&lt;br /&gt;
&lt;br /&gt;
= General idea =&lt;br /&gt;
&lt;br /&gt;
*Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.&lt;br /&gt;
*The components don't need to know each other, they only need the message format.&lt;br /&gt;
*Each subscriber set a callback function that will be called when new data are sent.&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== Message definition ==&lt;br /&gt;
&lt;br /&gt;
The messages are described in ''conf/abi.xml'' analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. &amp;quot;type&amp;quot; field should be a real C type. Field name might be useless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;class name=&amp;quot;airborne&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;message name=&amp;quot;DATA&amp;quot; id=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;a&amp;quot; type=&amp;quot;float&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;b&amp;quot; type=&amp;quot;struct bla&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
 &amp;lt;/class&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code generation ==&lt;br /&gt;
&lt;br /&gt;
The generated code will be in var/include/abi_messages.h and include some structure definition from sw/airborne/modules/core/abi_common.h (sw/airborne/modules/core/abi.h is a convenience header that only includes var/include/abi_messages.h). Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.&lt;br /&gt;
&lt;br /&gt;
 // Code in abi_common.h&lt;br /&gt;
 // Here, include header custom structures you may want to use in ABI messages&lt;br /&gt;
 // Default is to include pprz algebra libraries&lt;br /&gt;
 &lt;br /&gt;
 typedef void (*abi_callback)(void); // Generic callback definition&lt;br /&gt;
 &lt;br /&gt;
 struct _abi_event_struct {&lt;br /&gt;
  uint8_t id;&lt;br /&gt;
  abi_callback cb;&lt;br /&gt;
  struct _abi_event_struct * next;&lt;br /&gt;
 };&lt;br /&gt;
 typedef struct _abi_event_struct abi_event;&lt;br /&gt;
 &lt;br /&gt;
 #ifdef ABI_C&lt;br /&gt;
 #define ABI_EXTERN&lt;br /&gt;
 #else&lt;br /&gt;
 #define ABI_EXTERN extern&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 #define ABI_FOREACH(head,el) for(el=head; el; el=el-&amp;gt;next)&lt;br /&gt;
 #define ABI_PREPEND(head,new) { (add)-&amp;gt;next = head; head = add; }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // Code generated in var/include/abi_messages.h&lt;br /&gt;
 #include &amp;quot;modules/core/abi_common.h&amp;quot;&lt;br /&gt;
 // Message IDs&lt;br /&gt;
 #define DATA_ID 0&lt;br /&gt;
 &lt;br /&gt;
 // Callbacks&lt;br /&gt;
 typedef void (*abi_callbackDATA)(uint8_t sender_id, const float * a, const struct bla * b); // Specific callback for DATA message (arguments are const to prevent modifying them)&lt;br /&gt;
 &lt;br /&gt;
 // Array and linked list&lt;br /&gt;
 #define ABI_MESSAGE_NB &amp;lt;highest id of the messages in airborne class + 1&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 EXTERN abi_event abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file&lt;br /&gt;
 &lt;br /&gt;
 // Bind and Send for each messages&lt;br /&gt;
 static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {&lt;br /&gt;
  ev-&amp;gt;id = sender_id; // Store sender ID&lt;br /&gt;
  ev-&amp;gt;cb = (abi_callback)cb; // Store callback&lt;br /&gt;
  ABI_PREPEND(abi_queues[DATA_ID],ev); // add to the head of the list (because I'm lazy)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 static inline void AbiSendMsgDATA(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // Call all callback functions&lt;br /&gt;
  abi_event* e;&lt;br /&gt;
  ABI_FOREACH(abi_queues[DATA_ID],e) {&lt;br /&gt;
   if (e-&amp;gt;id == ABI_BROADCAST || e-&amp;gt;id == sender_id) { // call function only if selected source or broadcast address&lt;br /&gt;
    abi_callbackDATA cb = (abi_callbackDATA)(e-&amp;gt;cb); // C black magic&lt;br /&gt;
    cb(sender_id, a, b);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Airborne code for main AP ==&lt;br /&gt;
&lt;br /&gt;
This part of the code should be written and called only once in a .c file (like main.c, but it can be somewhere else)&lt;br /&gt;
&lt;br /&gt;
 #define ABI_C 1&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Airborne code for subscriber ==&lt;br /&gt;
&lt;br /&gt;
Include header and declare an abi_event as a global variable. Write the callback function with the proper prototype.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 abi_event ev;&lt;br /&gt;
 &lt;br /&gt;
 void data_cb(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // do something here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the initialization function (or later) call the binding functions for the message you want to receive. ABI_BROADCAST is a macro equals to 0 and is used as a broadcast address, which means that input values will be received from all sources for this message.&lt;br /&gt;
&lt;br /&gt;
 AbiBindMsgDATA(ABI_BROADCAST, &amp;amp;ev, data_cb);&lt;br /&gt;
&lt;br /&gt;
== Airborne code for publisher ==&lt;br /&gt;
&lt;br /&gt;
Include header of course.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In any function, call the send function. Sender id 0 is reserved (broadcast address).&lt;br /&gt;
&lt;br /&gt;
 #define SENDER_ID 1&lt;br /&gt;
 float var = 2.;&lt;br /&gt;
 struct bla s;&lt;br /&gt;
 AbiSendMsgDATA(SENDER_ID, &amp;amp;var, &amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That's it !&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer_Documentation]]&lt;/div&gt;</summary>
		<author><name>Lida2003</name></author>
	</entry>
	<entry>
		<id>http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26120</id>
		<title>ABI</title>
		<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26120"/>
		<updated>2022-04-13T07:35:53Z</updated>

		<summary type="html">&lt;p&gt;Lida2003: change abi.h #include location&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page presents some idea for an embedded middleware named ABI based on publish/subscribe like Ivy.&lt;br /&gt;
&lt;br /&gt;
= General idea =&lt;br /&gt;
&lt;br /&gt;
*Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.&lt;br /&gt;
*The components don't need to know each other, they only need the message format.&lt;br /&gt;
*Each subscriber set a callback function that will be called when new data are sent.&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== Message definition ==&lt;br /&gt;
&lt;br /&gt;
The messages are described in ''conf/abi.xml'' analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. &amp;quot;type&amp;quot; field should be a real C type. Field name might be useless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;class name=&amp;quot;airborne&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;message name=&amp;quot;DATA&amp;quot; id=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;a&amp;quot; type=&amp;quot;float&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;b&amp;quot; type=&amp;quot;struct bla&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
 &amp;lt;/class&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code generation ==&lt;br /&gt;
&lt;br /&gt;
The generated code will be in var/include/abi_messages.h and include some structure definition from sw/airborne/modules/core/abi_common.h (sw/airborne/modules/core/abi.h is a convenience header that only includes var/include/abi_messages.h). Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.&lt;br /&gt;
&lt;br /&gt;
 // Code in abi_common.h&lt;br /&gt;
 // Here, include header custom structures you may want to use in ABI messages&lt;br /&gt;
 // Default is to include pprz algebra libraries&lt;br /&gt;
 &lt;br /&gt;
 typedef void (*abi_callback)(void); // Generic callback definition&lt;br /&gt;
 &lt;br /&gt;
 struct _abi_event_struct {&lt;br /&gt;
  uint8_t id;&lt;br /&gt;
  abi_callback cb;&lt;br /&gt;
  struct _abi_event_struct * next;&lt;br /&gt;
 };&lt;br /&gt;
 typedef struct _abi_event_struct abi_event;&lt;br /&gt;
 &lt;br /&gt;
 #ifdef ABI_C&lt;br /&gt;
 #define ABI_EXTERN&lt;br /&gt;
 #else&lt;br /&gt;
 #define ABI_EXTERN extern&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 #define ABI_FOREACH(head,el) for(el=head; el; el=el-&amp;gt;next)&lt;br /&gt;
 #define ABI_PREPEND(head,new) { (add)-&amp;gt;next = head; head = add; }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // Code generated in var/include/abi_messages.h&lt;br /&gt;
 #include &amp;quot;modules/core/abi_common.h&amp;quot;&lt;br /&gt;
 // Message IDs&lt;br /&gt;
 #define DATA_ID 0&lt;br /&gt;
 &lt;br /&gt;
 // Callbacks&lt;br /&gt;
 typedef void (*abi_callbackDATA)(uint8_t sender_id, const float * a, const struct bla * b); // Specific callback for DATA message (arguments are const to prevent modifying them)&lt;br /&gt;
 &lt;br /&gt;
 // Array and linked list&lt;br /&gt;
 #define ABI_MESSAGE_NB &amp;lt;highest id of the messages in airborne class + 1&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 EXTERN abi_event abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file&lt;br /&gt;
 &lt;br /&gt;
 // Bind and Send for each messages&lt;br /&gt;
 static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {&lt;br /&gt;
  ev-&amp;gt;id = sender_id; // Store sender ID&lt;br /&gt;
  ev-&amp;gt;cb = (abi_callback)cb; // Store callback&lt;br /&gt;
  ABI_PREPEND(abi_queues[DATA_ID],ev); // add to the head of the list (because I'm lazy)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 static inline void AbiSendMsgDATA(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // Call all callback functions&lt;br /&gt;
  abi_event* e;&lt;br /&gt;
  ABI_FOREACH(abi_queues[DATA_ID],e) {&lt;br /&gt;
   if (e-&amp;gt;id == ABI_BROADCAST || e-&amp;gt;id == sender_id) { // call function only if selected source or broadcast address&lt;br /&gt;
    abi_callbackDATA cb = (abi_callbackDATA)(e-&amp;gt;cb); // C black magic&lt;br /&gt;
    cb(sender_id, a, b);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Airborne code for main AP ==&lt;br /&gt;
&lt;br /&gt;
This part of the code should be written and called only once in a .c file (like main.c, but it can be somewhere else)&lt;br /&gt;
&lt;br /&gt;
 #define ABI_C 1&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;modules/core/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Airborne code for subscriber ==&lt;br /&gt;
&lt;br /&gt;
Include header and declare an abi_event as a global variable. Write the callback function with the proper prototype.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 abi_event ev;&lt;br /&gt;
 &lt;br /&gt;
 void data_cb(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // do something here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the initialization function (or later) call the binding functions for the message you want to receive. ABI_BROADCAST is a macro equals to 0 and is used as a broadcast address, which means that input values will be received from all sources for this message.&lt;br /&gt;
&lt;br /&gt;
 AbiBindMsgDATA(ABI_BROADCAST, &amp;amp;ev, data_cb);&lt;br /&gt;
&lt;br /&gt;
== Airborne code for publisher ==&lt;br /&gt;
&lt;br /&gt;
Include header of course.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In any function, call the send function. Sender id 0 is reserved (broadcast address).&lt;br /&gt;
&lt;br /&gt;
 #define SENDER_ID 1&lt;br /&gt;
 float var = 2.;&lt;br /&gt;
 struct bla s;&lt;br /&gt;
 AbiSendMsgDATA(SENDER_ID, &amp;amp;var, &amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That's it !&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer_Documentation]]&lt;/div&gt;</summary>
		<author><name>Lida2003</name></author>
	</entry>
	<entry>
		<id>http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26119</id>
		<title>ABI</title>
		<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26119"/>
		<updated>2022-04-13T07:34:18Z</updated>

		<summary type="html">&lt;p&gt;Lida2003: change abi_common.h include location&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page presents some idea for an embedded middleware named ABI based on publish/subscribe like Ivy.&lt;br /&gt;
&lt;br /&gt;
= General idea =&lt;br /&gt;
&lt;br /&gt;
*Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.&lt;br /&gt;
*The components don't need to know each other, they only need the message format.&lt;br /&gt;
*Each subscriber set a callback function that will be called when new data are sent.&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== Message definition ==&lt;br /&gt;
&lt;br /&gt;
The messages are described in ''conf/abi.xml'' analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. &amp;quot;type&amp;quot; field should be a real C type. Field name might be useless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;class name=&amp;quot;airborne&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;message name=&amp;quot;DATA&amp;quot; id=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;a&amp;quot; type=&amp;quot;float&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;b&amp;quot; type=&amp;quot;struct bla&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
 &amp;lt;/class&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code generation ==&lt;br /&gt;
&lt;br /&gt;
The generated code will be in var/include/abi_messages.h and include some structure definition from sw/airborne/modules/core/abi_common.h (sw/airborne/modules/core/abi.h is a convenience header that only includes var/include/abi_messages.h). Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.&lt;br /&gt;
&lt;br /&gt;
 // Code in abi_common.h&lt;br /&gt;
 // Here, include header custom structures you may want to use in ABI messages&lt;br /&gt;
 // Default is to include pprz algebra libraries&lt;br /&gt;
 &lt;br /&gt;
 typedef void (*abi_callback)(void); // Generic callback definition&lt;br /&gt;
 &lt;br /&gt;
 struct _abi_event_struct {&lt;br /&gt;
  uint8_t id;&lt;br /&gt;
  abi_callback cb;&lt;br /&gt;
  struct _abi_event_struct * next;&lt;br /&gt;
 };&lt;br /&gt;
 typedef struct _abi_event_struct abi_event;&lt;br /&gt;
 &lt;br /&gt;
 #ifdef ABI_C&lt;br /&gt;
 #define ABI_EXTERN&lt;br /&gt;
 #else&lt;br /&gt;
 #define ABI_EXTERN extern&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 #define ABI_FOREACH(head,el) for(el=head; el; el=el-&amp;gt;next)&lt;br /&gt;
 #define ABI_PREPEND(head,new) { (add)-&amp;gt;next = head; head = add; }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // Code generated in var/include/abi_messages.h&lt;br /&gt;
 #include &amp;quot;modules/core/abi_common.h&amp;quot;&lt;br /&gt;
 // Message IDs&lt;br /&gt;
 #define DATA_ID 0&lt;br /&gt;
 &lt;br /&gt;
 // Callbacks&lt;br /&gt;
 typedef void (*abi_callbackDATA)(uint8_t sender_id, const float * a, const struct bla * b); // Specific callback for DATA message (arguments are const to prevent modifying them)&lt;br /&gt;
 &lt;br /&gt;
 // Array and linked list&lt;br /&gt;
 #define ABI_MESSAGE_NB &amp;lt;highest id of the messages in airborne class + 1&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 EXTERN abi_event abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file&lt;br /&gt;
 &lt;br /&gt;
 // Bind and Send for each messages&lt;br /&gt;
 static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {&lt;br /&gt;
  ev-&amp;gt;id = sender_id; // Store sender ID&lt;br /&gt;
  ev-&amp;gt;cb = (abi_callback)cb; // Store callback&lt;br /&gt;
  ABI_PREPEND(abi_queues[DATA_ID],ev); // add to the head of the list (because I'm lazy)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 static inline void AbiSendMsgDATA(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // Call all callback functions&lt;br /&gt;
  abi_event* e;&lt;br /&gt;
  ABI_FOREACH(abi_queues[DATA_ID],e) {&lt;br /&gt;
   if (e-&amp;gt;id == ABI_BROADCAST || e-&amp;gt;id == sender_id) { // call function only if selected source or broadcast address&lt;br /&gt;
    abi_callbackDATA cb = (abi_callbackDATA)(e-&amp;gt;cb); // C black magic&lt;br /&gt;
    cb(sender_id, a, b);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Airborne code for main AP ==&lt;br /&gt;
&lt;br /&gt;
This part of the code should be written and called only once in a .c file (like main.c, but it can be somewhere else)&lt;br /&gt;
&lt;br /&gt;
 #define ABI_C 1&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Airborne code for subscriber ==&lt;br /&gt;
&lt;br /&gt;
Include header and declare an abi_event as a global variable. Write the callback function with the proper prototype.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 abi_event ev;&lt;br /&gt;
 &lt;br /&gt;
 void data_cb(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // do something here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the initialization function (or later) call the binding functions for the message you want to receive. ABI_BROADCAST is a macro equals to 0 and is used as a broadcast address, which means that input values will be received from all sources for this message.&lt;br /&gt;
&lt;br /&gt;
 AbiBindMsgDATA(ABI_BROADCAST, &amp;amp;ev, data_cb);&lt;br /&gt;
&lt;br /&gt;
== Airborne code for publisher ==&lt;br /&gt;
&lt;br /&gt;
Include header of course.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In any function, call the send function. Sender id 0 is reserved (broadcast address).&lt;br /&gt;
&lt;br /&gt;
 #define SENDER_ID 1&lt;br /&gt;
 float var = 2.;&lt;br /&gt;
 struct bla s;&lt;br /&gt;
 AbiSendMsgDATA(SENDER_ID, &amp;amp;var, &amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That's it !&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer_Documentation]]&lt;/div&gt;</summary>
		<author><name>Lida2003</name></author>
	</entry>
	<entry>
		<id>http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26118</id>
		<title>ABI</title>
		<link rel="alternate" type="text/html" href="http://wiki.paparazziuav.org/w/index.php?title=ABI&amp;diff=26118"/>
		<updated>2022-04-13T07:29:07Z</updated>

		<summary type="html">&lt;p&gt;Lida2003: abi is now in modules/core, there is no subsystems anymore&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page presents some idea for an embedded middleware named ABI based on publish/subscribe like Ivy.&lt;br /&gt;
&lt;br /&gt;
= General idea =&lt;br /&gt;
&lt;br /&gt;
*Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.&lt;br /&gt;
*The components don't need to know each other, they only need the message format.&lt;br /&gt;
*Each subscriber set a callback function that will be called when new data are sent.&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== Message definition ==&lt;br /&gt;
&lt;br /&gt;
The messages are described in ''conf/abi.xml'' analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. &amp;quot;type&amp;quot; field should be a real C type. Field name might be useless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;class name=&amp;quot;airborne&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;message name=&amp;quot;DATA&amp;quot; id=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;a&amp;quot; type=&amp;quot;float&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;field name=&amp;quot;b&amp;quot; type=&amp;quot;struct bla&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
 &amp;lt;/class&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code generation ==&lt;br /&gt;
&lt;br /&gt;
The generated code will be in var/include/abi_messages.h and include some structure definition from sw/airborne/modules/core/abi_common.h (sw/airborne/modules/core/abi.h is a convenience header that only includes var/include/abi_messages.h). Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.&lt;br /&gt;
&lt;br /&gt;
 // Code in abi_common.h&lt;br /&gt;
 // Here, include header custom structures you may want to use in ABI messages&lt;br /&gt;
 // Default is to include pprz algebra libraries&lt;br /&gt;
 &lt;br /&gt;
 typedef void (*abi_callback)(void); // Generic callback definition&lt;br /&gt;
 &lt;br /&gt;
 struct _abi_event_struct {&lt;br /&gt;
  uint8_t id;&lt;br /&gt;
  abi_callback cb;&lt;br /&gt;
  struct _abi_event_struct * next;&lt;br /&gt;
 };&lt;br /&gt;
 typedef struct _abi_event_struct abi_event;&lt;br /&gt;
 &lt;br /&gt;
 #ifdef ABI_C&lt;br /&gt;
 #define ABI_EXTERN&lt;br /&gt;
 #else&lt;br /&gt;
 #define ABI_EXTERN extern&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 #define ABI_FOREACH(head,el) for(el=head; el; el=el-&amp;gt;next)&lt;br /&gt;
 #define ABI_PREPEND(head,new) { (add)-&amp;gt;next = head; head = add; }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // Code generated in var/include/abi_messages.h&lt;br /&gt;
 #include &amp;quot;subsystems/abi_common.h&lt;br /&gt;
 // Message IDs&lt;br /&gt;
 #define DATA_ID 0&lt;br /&gt;
 &lt;br /&gt;
 // Callbacks&lt;br /&gt;
 typedef void (*abi_callbackDATA)(uint8_t sender_id, const float * a, const struct bla * b); // Specific callback for DATA message (arguments are const to prevent modifying them)&lt;br /&gt;
 &lt;br /&gt;
 // Array and linked list&lt;br /&gt;
 #define ABI_MESSAGE_NB &amp;lt;highest id of the messages in airborne class + 1&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 EXTERN abi_event abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file&lt;br /&gt;
 &lt;br /&gt;
 // Bind and Send for each messages&lt;br /&gt;
 static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {&lt;br /&gt;
  ev-&amp;gt;id = sender_id; // Store sender ID&lt;br /&gt;
  ev-&amp;gt;cb = (abi_callback)cb; // Store callback&lt;br /&gt;
  ABI_PREPEND(abi_queues[DATA_ID],ev); // add to the head of the list (because I'm lazy)&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 static inline void AbiSendMsgDATA(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // Call all callback functions&lt;br /&gt;
  abi_event* e;&lt;br /&gt;
  ABI_FOREACH(abi_queues[DATA_ID],e) {&lt;br /&gt;
   if (e-&amp;gt;id == ABI_BROADCAST || e-&amp;gt;id == sender_id) { // call function only if selected source or broadcast address&lt;br /&gt;
    abi_callbackDATA cb = (abi_callbackDATA)(e-&amp;gt;cb); // C black magic&lt;br /&gt;
    cb(sender_id, a, b);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Airborne code for main AP ==&lt;br /&gt;
&lt;br /&gt;
This part of the code should be written and called only once in a .c file (like main.c, but it can be somewhere else)&lt;br /&gt;
&lt;br /&gt;
 #define ABI_C 1&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Airborne code for subscriber ==&lt;br /&gt;
&lt;br /&gt;
Include header and declare an abi_event as a global variable. Write the callback function with the proper prototype.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 abi_event ev;&lt;br /&gt;
 &lt;br /&gt;
 void data_cb(uint8_t sender_id, const float * a, const struct bla * b) {&lt;br /&gt;
  // do something here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the initialization function (or later) call the binding functions for the message you want to receive. ABI_BROADCAST is a macro equals to 0 and is used as a broadcast address, which means that input values will be received from all sources for this message.&lt;br /&gt;
&lt;br /&gt;
 AbiBindMsgDATA(ABI_BROADCAST, &amp;amp;ev, data_cb);&lt;br /&gt;
&lt;br /&gt;
== Airborne code for publisher ==&lt;br /&gt;
&lt;br /&gt;
Include header of course.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;subsystems/abi.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In any function, call the send function. Sender id 0 is reserved (broadcast address).&lt;br /&gt;
&lt;br /&gt;
 #define SENDER_ID 1&lt;br /&gt;
 float var = 2.;&lt;br /&gt;
 struct bla s;&lt;br /&gt;
 AbiSendMsgDATA(SENDER_ID, &amp;amp;var, &amp;amp;s);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That's it !&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer_Documentation]]&lt;/div&gt;</summary>
		<author><name>Lida2003</name></author>
	</entry>
</feed>