Merged in f5soh/librepilot/laurent/LP-92_Feed_forward_remove (pull request #33)
[librepilot.git] / flight / pios / common / pios_com_msg.c
blob3e109ce351ddc92bcd1360d5c975dcf1cebb4a43
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_COM COM MSG layer functions
6 * @brief Hardware communication layer
7 * @{
9 * @file pios_com_msg.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
11 * @brief COM MSG layer functions
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "pios.h"
33 #ifdef PIOS_INCLUDE_COM_MSG
35 #include "pios_com.h"
37 #define PIOS_COM_MSG_MAX_LEN 63
39 struct pios_com_msg_dev {
40 uint32_t lower_id;
41 const struct pios_com_driver *driver;
43 uint8_t rx_msg_buffer[PIOS_COM_MSG_MAX_LEN];
44 volatile bool rx_msg_full;
46 uint8_t tx_msg_buffer[PIOS_COM_MSG_MAX_LEN];
47 volatile bool tx_msg_full;
50 static struct pios_com_msg_dev com_msg_dev;
52 static uint16_t PIOS_COM_MSG_TxOutCallback(uint32_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *need_yield);
53 static uint16_t PIOS_COM_MSG_RxInCallback(uint32_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *need_yield);
55 int32_t PIOS_COM_MSG_Init(uint32_t *com_id, const struct pios_com_driver *driver, uint32_t lower_id)
57 PIOS_Assert(com_id);
58 PIOS_Assert(driver);
60 PIOS_Assert(driver->bind_tx_cb);
61 PIOS_Assert(driver->bind_rx_cb);
63 struct pios_com_msg_dev *com_dev = &com_msg_dev;
65 com_dev->driver = driver;
66 com_dev->lower_id = lower_id;
68 com_dev->rx_msg_full = false;
69 (com_dev->driver->bind_rx_cb)(lower_id, PIOS_COM_MSG_RxInCallback, (uint32_t)com_dev);
70 (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer));
72 com_dev->tx_msg_full = false;
73 (com_dev->driver->bind_tx_cb)(lower_id, PIOS_COM_MSG_TxOutCallback, (uint32_t)com_dev);
75 *com_id = (uint32_t)com_dev;
76 return 0;
79 static uint16_t PIOS_COM_MSG_TxOutCallback(uint32_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, __attribute__((unused)) bool *need_yield)
81 struct pios_com_msg_dev *com_dev = (struct pios_com_msg_dev *)context;
83 PIOS_Assert(buf);
84 PIOS_Assert(buf_len);
86 uint16_t bytes_from_fifo = 0;
88 if (com_dev->tx_msg_full && (buf_len >= sizeof(com_dev->tx_msg_buffer))) {
89 /* Room for an entire message, send it */
90 memcpy(buf, com_dev->tx_msg_buffer, sizeof(com_dev->tx_msg_buffer));
91 bytes_from_fifo = sizeof(com_dev->tx_msg_buffer);
92 com_dev->tx_msg_full = false;
95 if (headroom) {
96 if (com_dev->tx_msg_full) {
97 *headroom = sizeof(com_dev->tx_msg_buffer);
98 } else {
99 *headroom = 0;
103 return bytes_from_fifo;
106 static uint16_t PIOS_COM_MSG_RxInCallback(uint32_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, __attribute__((unused)) bool *need_yield)
108 struct pios_com_msg_dev *com_dev = (struct pios_com_msg_dev *)context;
110 uint16_t bytes_into_fifo = 0;
112 if (!com_dev->rx_msg_full && (buf_len >= sizeof(com_dev->rx_msg_buffer))) {
113 memcpy(com_dev->rx_msg_buffer, buf, sizeof(com_dev->rx_msg_buffer));
114 bytes_into_fifo = sizeof(com_dev->rx_msg_buffer);
115 com_dev->rx_msg_full = true;
118 if (headroom) {
119 if (!com_dev->rx_msg_full) {
120 *headroom = sizeof(com_dev->rx_msg_buffer);
121 } else {
122 *headroom = 0;
126 return bytes_into_fifo;
129 int32_t PIOS_COM_MSG_Send(uint32_t com_id, const uint8_t *msg, uint16_t msg_len)
131 PIOS_Assert(msg);
132 PIOS_Assert(msg_len);
134 struct pios_com_msg_dev *com_dev = (struct pios_com_msg_dev *)com_id;
136 PIOS_Assert(msg_len == sizeof(com_dev->tx_msg_buffer));
138 /* Wait forever for room in the tx buffer */
139 while (com_dev->tx_msg_full) {
140 /* Kick the transmitter while we wait */
141 if (com_dev->driver->tx_start) {
142 (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer));
146 memcpy((void *)com_dev->tx_msg_buffer, msg, msg_len);
147 com_dev->tx_msg_full = true;
149 /* Kick the transmitter now that we've queued our message */
150 if (com_dev->driver->tx_start) {
151 (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer));
154 return 0;
157 uint16_t PIOS_COM_MSG_Receive(uint32_t com_id, uint8_t *msg, uint16_t msg_len)
159 PIOS_Assert(msg);
160 PIOS_Assert(msg_len);
162 struct pios_com_msg_dev *com_dev = (struct pios_com_msg_dev *)com_id;
164 PIOS_Assert(msg_len == sizeof(com_dev->rx_msg_buffer));
166 if (!com_dev->rx_msg_full) {
167 /* There's room in our buffer, kick the receiver */
168 (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer));
169 } else {
170 memcpy(msg, com_dev->rx_msg_buffer, msg_len);
171 com_dev->rx_msg_full = false;
173 return msg_len;
176 return 0;
180 * Change the port speed without re-initializing
181 * \param[in] port COM port
182 * \param[in] baud Requested baud rate
183 * \return -1 if port not available
184 * \return 0 on success
186 int32_t PIOS_COM_MSG_ChangeBaud(uint32_t com_id, uint32_t baud)
188 struct pios_com_msg_dev *com_dev = (struct pios_com_msg_dev *)com_id;
190 if (!com_dev) {
191 /* Undefined COM port for this board (see pios_board.c) */
192 return -1;
195 /* Invoke the driver function if it exists */
196 if (com_dev->driver->set_baud) {
197 com_dev->driver->set_baud(com_dev->lower_id, baud);
200 return 0;
203 #endif /* PIOS_INCLUDE_COM_MSG */
206 * @}
207 * @}