dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uavocrossfiretelemetry.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
28 
29 #include "pios.h"
30 #if defined(PIOS_INCLUDE_CROSSFIRE)
31 
32 #include "openpilot.h"
33 #include "pios_hal.h"
34 #include "pios_thread.h"
35 #include "pios_modules.h"
36 #include "pios_crc.h"
37 #include "taskmonitor.h"
38 #include "taskinfo.h"
39 
40 #include "uavocrossfiretelemetry.h"
41 
42 #include "modulesettings.h"
43 #include "flightbatterystate.h"
44 #include "flightbatterysettings.h"
45 #include "gpsposition.h"
46 #include "attitudeactual.h"
47 #include "manualcontrolsettings.h"
48 
49 // Private constants
50 #define STACK_SIZE_BYTES 600 // Reevaluate.
51 #define TASK_PRIORITY PIOS_THREAD_PRIO_LOW
52 
53 #define DEG2RAD(x) ((float)x * (float)M_PI / 180.0f)
54 
55 // Private variables
56 static struct pios_thread *uavoCrossfireTelemetryTaskHandle;
57 static bool module_enabled;
58 
59 // Crossfire receiver device
60 static uintptr_t crsf_telem_dev_id;
61 
62 static void uavoCrossfireTelemetryTask(void *parameters);
63 
69 static int32_t uavoCrossfireTelemetryStart(void)
70 {
71  uintptr_t rcvr = PIOS_HAL_GetReceiver(MANUALCONTROLSETTINGS_CHANNELGROUPS_TBSCROSSFIRE);
72 
73  // We shouldn't need to check whether it's a valid Crossfire device, because if
74  // something else was read out of the channel group, something's really borked.
75  if(rcvr) {
76  crsf_telem_dev_id = PIOS_RCVR_GetLowerDevice(rcvr);
77  if (module_enabled && (PIOS_Crossfire_InitTelemetry(crsf_telem_dev_id) == 0)) {
78  // Start task
79  uavoCrossfireTelemetryTaskHandle = PIOS_Thread_Create(
80  uavoCrossfireTelemetryTask, "uavoCrossfireTelemetry",
82  TaskMonitorAdd(TASKINFO_RUNNING_UAVOCROSSFIRETELEMETRY,
83  uavoCrossfireTelemetryTaskHandle);
84  return 0;
85  }
86  }
87 
88  return -1;
89 }
90 
91 static int32_t uavoCrossfireTelemetryInitialize(void)
92 {
94  return 0;
95 }
96 MODULE_INITCALL(uavoCrossfireTelemetryInitialize, uavoCrossfireTelemetryStart)
97 
98 // Stupid big endian stuff.
99 #define WRITE_VAL(buf,p,x) { typeof(x) v = x; uint8_t *q = (uint8_t*)&v, n = sizeof(v); do{ buf[p++] = q[--n]; } while(n); }
100 #define WRITE_VAL16(buf,p,x) { typeof(x) v = x; uint8_t *q = (uint8_t*)&v; buf[p++] = q[1]; buf[p++] = q[0]; }
101 #define WRITE_VAL32(buf,p,x) { typeof(x) v = x; uint8_t *q = (uint8_t*)&v; buf[p++] = q[3]; buf[p++] = q[2]; buf[p++] = q[1]; buf[p++] = q[0]; }
102 
103 static int crsftelem_create_attitude(uint8_t *buf)
104 {
105  int pos = 0;
106 
107  if(AttitudeActualHandle()) {
108  AttitudeActualData attitudeData;
109  AttitudeActualGet(&attitudeData);
110 
111  buf[pos++] = 0;
113  buf[pos++] = CRSF_FRAME_ATTITUDE;
114 
115  WRITE_VAL16(buf, pos, (int16_t)(DEG2RAD(attitudeData.Pitch)*10000.0f));
116  WRITE_VAL16(buf, pos, (int16_t)(DEG2RAD(attitudeData.Roll)*10000.0f));
117  WRITE_VAL16(buf, pos, (int16_t)(DEG2RAD(attitudeData.Yaw)*10000.0f));
118 
119  buf[pos++] = PIOS_CRC_updateCRC_TBS(0, buf+2, buf[1] - CRSF_CRC_LEN);
120  }
121 
122  return pos;
123 }
124 
125 static int crsftelem_create_battery(uint8_t *buf)
126 {
127  int pos = 0;
128 
129  if(FlightBatteryStateHandle() && FlightBatterySettingsHandle()) {
130  FlightBatteryStateData batteryData;
131  FlightBatterySettingsData batterySettings;
132 
133  FlightBatteryStateGet(&batteryData);
134  FlightBatterySettingsGet(&batterySettings);
135 
136  buf[pos++] = 0;
138  buf[pos++] = CRSF_FRAME_BATTERY;
139 
140  WRITE_VAL16(buf, pos, (uint16_t)(batteryData.Voltage * 10.0f))
141  WRITE_VAL16(buf, pos, (uint16_t)(batteryData.Current * 10.0f))
142 
143  // Should apparently be capacity used?
144  buf[pos++] = (uint8_t)((batterySettings.Capacity & 0x00FF0000) >> 16);
145  buf[pos++] = (uint8_t)((batterySettings.Capacity & 0x0000FF00) >> 8);
146  buf[pos++] = (uint8_t)(batterySettings.Capacity & 0x000000FF);
147 
148  float charge_state = batterySettings.Capacity == 0 ? 100.0f : (batteryData.ConsumedEnergy / batterySettings.Capacity);
149  if(charge_state < 0) charge_state = 0;
150  else if(charge_state > 100) charge_state = 100;
151  buf[pos++] = (uint8_t)charge_state;
152 
153  buf[pos++] = PIOS_CRC_updateCRC_TBS(0, buf+2, buf[1] - CRSF_CRC_LEN);
154  }
155 
156  return pos;
157 }
158 
159 static int crsftelem_create_gps(uint8_t *buf)
160 {
161  int pos = 0;
162 
163  if(GPSPositionHandle()) {
164  GPSPositionData gpsData;
165  GPSPositionGet(&gpsData);
166 
167  if(gpsData.Status >= GPSPOSITION_STATUS_FIX2D) {
168  buf[pos++] = 0;
169  buf[pos++] = CRSF_PAYLOAD_LEN(CRSF_PAYLOAD_GPS);
170  buf[pos++] = CRSF_FRAME_GPS;
171 
172  // Latitude (x10^7, as dRonin)
173  WRITE_VAL32(buf, pos, (int32_t)gpsData.Latitude);
174  // Longitude (x10^7, as dRonin)
175  WRITE_VAL32(buf, pos, (int32_t)gpsData.Longitude);
176  // Groundspeed (apparently tenth of km/h)
177  WRITE_VAL16(buf, pos, (uint16_t)(gpsData.Groundspeed*10.0f));
178  // Heading (apparently hundreth of a degree)
179  WRITE_VAL16(buf, pos, (uint16_t)(gpsData.Heading*100.0f));
180  // Altitude 1000 = 0m
181  WRITE_VAL16(buf, pos, (uint16_t)(1000.0f+
182  (gpsData.Status >= GPSPOSITION_STATUS_FIX3D ? gpsData.Altitude : 0.0f)));
183  // Satellites
184  buf[pos++] = gpsData.Satellites;
185 
186  buf[pos++] = PIOS_CRC_updateCRC_TBS(0, buf+2, buf[1] - CRSF_CRC_LEN);
187  }
188  }
189 
190  return pos;
191 }
192 
193 static void uavoCrossfireTelemetryTask(void *parameters)
194 {
195  // Three objects, each at UPDATE_HZ
196  uint32_t idledelay = 1000 / (3 * UPDATE_HZ);
197  uint8_t counter = 0;
198 
199  // Wait for stuff to setup?
200  PIOS_Thread_Sleep(1000);
201 
202  while (1) {
203  uint8_t buf[CRSF_MAX_FRAMELEN];
204  uint8_t len = 0;
205 
206  if(!PIOS_Crossfire_IsFailsafed(crsf_telem_dev_id)) {
207 
208  switch(counter++ % 3) {
209  default:
210  case 0: // Attitude
211  len = crsftelem_create_attitude(buf);
212  break;
213  case 1: // Battery
214  len = crsftelem_create_battery(buf);
215  break;
216  case 2: // GPS
217  len = crsftelem_create_gps(buf);
218  break;
219  }
220 
221  if(len) {
222  while(PIOS_Crossfire_SendTelemetry(crsf_telem_dev_id, buf, len)) {
223  // Keep repeating until telemetry went through, without
224  // locking up the whole thing.
226  }
227  }
228  }
229 
230  PIOS_Thread_Sleep(idledelay);
231  }
232 }
233 
234 
235 #endif // PIOS_INCLUDE_CROSSFIRE
CRC functions header.
int PIOS_Crossfire_SendTelemetry(uintptr_t crsf_id, uint8_t *buf, uint8_t bytes)
#define CRSF_FRAME_BATTERY
#define CRSF_PAYLOAD_ATTITUDE
#define CRSF_PAYLOAD_LEN(x)
Main PiOS header to include all the compiled in PiOS options.
#define CRSF_PAYLOAD_BATTERY
#define CRSF_FRAME_GPS
bool PIOS_Modules_IsEnabled(enum pios_modules module)
Definition: pios_modules.c:41
#define STACK_SIZE_BYTES
Definition: actuator.c:62
bool module_enabled
#define CRSF_MAX_FRAMELEN
#define CRSF_CRC_LEN
#define TASK_PRIORITY
Definition: actuator.c:65
Task monitoring library.
#define MODULE_INITCALL(ifn, sfn)
Definition: pios_initcall.h:67
struct _msp_pid_item pos
Definition: msp_messages.h:100
int PIOS_Crossfire_InitTelemetry(uintptr_t crsf_id)
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
uint8_t PIOS_CRC_updateCRC_TBS(uint8_t crc, const uint8_t *data, int32_t length)
Definition: pios_crc.c:185
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
Definition: taskmonitor.c:67
uintptr_t PIOS_RCVR_GetLowerDevice(uintptr_t rcvr_id)
#define CRSF_FRAME_ATTITUDE
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
uintptr_t PIOS_HAL_GetReceiver(int receiver_type)
tuple f
Definition: px_mkfw.py:81
Includes PiOS and core architecture components.
#define CRSF_PAYLOAD_GPS
bool PIOS_Crossfire_IsFailsafed()
if(BaroAltitudeHandle()!=NULL)
#define UPDATE_HZ