Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / flight / modules / OveroSync / simulated / overosync.c
blobc9b73b866e941f66ab4e4fab8bb7961cc2da3482
1 /**
2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
4 * @{
5 * @addtogroup TelemetryModule Telemetry Module
6 * @brief Main telemetry module
7 * Starts three tasks (RX, TX, and priority TX) that watch event queues
8 * and handle all the telemetry of the UAVobjects
9 * @{
11 * @file telemetry.c
12 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
13 * @brief Telemetry module, handles telemetry and UAVObject updates
14 * @see The GNU Public License (GPL) Version 3
16 *****************************************************************************/
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 * for more details.
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include <openpilot.h>
35 #include "overosync.h"
37 #include "overosyncstats.h"
38 #include "systemstats.h"
39 #include "taskinfo.h"
41 // Private constants
42 #define OVEROSYNC_PACKET_SIZE 1024
43 #define MAX_QUEUE_SIZE 40
44 #define STACK_SIZE_BYTES 512
45 #define TASK_PRIORITY (tskIDLE_PRIORITY + 0)
47 // Private types
49 // Private variables
50 static xQueueHandle queue;
51 static UAVTalkConnection uavTalkCon;
52 static xTaskHandle overoSyncTaskHandle;
53 volatile bool buffer_swap_failed;
54 volatile uint32_t buffer_swap_timeval;
55 FILE *fid;
57 // Private functions
58 static void overoSyncTask(void *parameters);
59 static int32_t packData(uint8_t *data, int32_t length);
60 static void registerObject(UAVObjHandle obj);
62 struct dma_transaction {
63 uint8_t tx_buffer[OVEROSYNC_PACKET_SIZE] __attribute__((aligned(4)));
64 uint8_t rx_buffer[OVEROSYNC_PACKET_SIZE] __attribute__((aligned(4)));
67 struct overosync {
68 struct dma_transaction transactions[2];
69 uint32_t active_transaction_id;
70 uint32_t loading_transaction_id;
71 xSemaphoreHandle transaction_lock;
72 xSemaphoreHandle buffer_lock;
73 volatile bool transaction_done;
74 uint32_t sent_bytes;
75 uint32_t write_pointer;
76 uint32_t sent_objects;
77 uint32_t failed_objects;
78 uint32_t received_objects;
79 uint32_t framesync_error;
82 struct overosync *overosync;
84 /**
85 * Initialise the telemetry module
86 * \return -1 if initialisation failed
87 * \return 0 on success
89 int32_t OveroSyncInitialize(void)
91 OveroSyncStatsInitialize();
93 // Create object queues
94 queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent));
96 // Initialise UAVTalk
97 uavTalkCon = UAVTalkInitialize(&packData);
99 return 0;
103 * Initialise the telemetry module
104 * \return -1 if initialisation failed
105 * \return 0 on success
107 int32_t OveroSyncStart(void)
109 overosync = (struct overosync *)pios_malloc(sizeof(*overosync));
110 if (overosync == NULL) {
111 return -1;
114 overosync->transaction_lock = xSemaphoreCreateMutex();
115 if (overosync->transaction_lock == NULL) {
116 return -1;
119 overosync->buffer_lock = xSemaphoreCreateMutex();
120 if (overosync->buffer_lock == NULL) {
121 return -1;
124 overosync->active_transaction_id = 0;
125 overosync->loading_transaction_id = 0;
126 overosync->write_pointer = 0;
127 overosync->sent_bytes = 0;
128 overosync->framesync_error = 0;
130 // Process all registered objects and connect queue for updates
131 UAVObjIterate(&registerObject);
133 // Start telemetry tasks
134 xTaskCreate(overoSyncTask, (signed char *)"OveroSync", STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &overoSyncTaskHandle);
136 PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_OVEROSYNC, overoSyncTaskHandle);
138 return 0;
141 MODULE_INITCALL(OveroSyncInitialize, OveroSyncStart);
144 * Register a new object, adds object to local list and connects the queue depending on the object's
145 * telemetry settings.
146 * \param[in] obj Object to connect
148 static void registerObject(UAVObjHandle obj)
150 int32_t eventMask;
152 eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
153 if (UAVObjIsMetaobject(obj)) {
154 eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
156 UAVObjConnectQueue(obj, queue, eventMask);
160 * Telemetry transmit task, regular priority
162 * Logic: We need to double buffer the DMA transfers. Pack the buffer until either
163 * 1) it is full (and then we should record the number of missed events then)
164 * 2) the current transaction is done (we should immediately schedule since we are slave)
165 * when done packing the buffer we should call PIOS_SPI_TransferBlock, change the active buffer
166 * and then take the semaphrore
168 static void overoSyncTask(__attribute__((unused)) void *parameters)
170 UAVObjEvent ev;
172 // Kick off SPI transfers (once one is completed another will automatically transmit)
173 overosync->transaction_done = true;
174 overosync->sent_objects = 0;
175 overosync->failed_objects = 0;
176 overosync->received_objects = 0;
178 portTickType lastUpdateTime = xTaskGetTickCount();
179 portTickType updateTime;
181 fid = fopen("sim_log.opl", "w");
183 // Loop forever
184 while (1) {
185 // Wait for queue message
186 if (xQueueReceive(queue, &ev, portMAX_DELAY) == pdTRUE) {
187 // Check it will fit before packetizing
188 if ((overosync->write_pointer + UAVObjGetNumBytes(ev.obj) + 12) >=
189 sizeof(overosync->transactions[overosync->loading_transaction_id].tx_buffer)) {
190 overosync->failed_objects++;
191 } else {
192 // Process event. This calls transmitData
193 UAVTalkSendObject(uavTalkCon, ev.obj, ev.instId, false, 0);
196 updateTime = xTaskGetTickCount();
197 if (((portTickType)(updateTime - lastUpdateTime)) > 1000) {
198 // Update stats. This will trigger a local send event too
199 OveroSyncStatsData syncStats;
200 syncStats.Send = overosync->sent_bytes;
201 syncStats.Received = 0;
202 syncStats.Connected = syncStats.Send > 500 ? OVEROSYNCSTATS_CONNECTED_TRUE : OVEROSYNCSTATS_CONNECTED_FALSE;
203 syncStats.DroppedUpdates = overosync->failed_objects;
204 OveroSyncStatsSet(&syncStats);
205 overosync->failed_objects = 0;
206 overosync->sent_bytes = 0;
207 lastUpdateTime = updateTime;
214 * Transmit data buffer to the modem or USB port.
215 * \param[in] data Data buffer to send
216 * \param[in] length Length of buffer
217 * \return -1 on failure
218 * \return number of bytes transmitted on success
220 static int32_t packData(uint8_t *data, int32_t length)
222 // Get the lock for manipulating the buffer
223 xSemaphoreTake(overosync->buffer_lock, portMAX_DELAY);
225 portTickType tickTime = xTaskGetTickCount();
226 uint64_t packetSize = data[2] + (data[3] << 8);
227 fwrite((void *)&tickTime, 1, sizeof(tickTime), fid);
228 fwrite((void *)&packetSize, sizeof(packetSize), 1, fid);
229 fwrite((void *)data, 1, length, fid);
230 overosync->sent_bytes += length;
231 overosync->sent_objects++;
233 xSemaphoreGive(overosync->buffer_lock);
235 return length;
239 * @}
240 * @}