Skip to content

Commit 3f71e99

Browse files
committed
dbus support dma usart
1 parent 3380b39 commit 3f71e99

15 files changed

+833
-51
lines changed

flight/make/apps-defs.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ SRC += $(PIOSCOMMON)/pios_rfm22b_com.c
9494
SRC += $(PIOSCOMMON)/pios_rcvr.c
9595
SRC += $(PIOSCOMMON)/pios_dsm.c
9696
SRC += $(PIOSCOMMON)/pios_sbus.c
97+
SRC += $(PIOSCOMMON)/pios_dbus.c
9798
SRC += $(PIOSCOMMON)/pios_hott.c
9899
SRC += $(PIOSCOMMON)/pios_srxl.c
99100
SRC += $(PIOSCOMMON)/pios_exbus.c

flight/pios/common/pios_board_io.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
# ifdef PIOS_INCLUDE_SBUS
4242
# include <pios_sbus_priv.h>
4343
# endif
44+
# ifdef PIOS_INCLUDE_DBUS
45+
# include <pios_dbus_priv.h>
46+
# endif
4447
# ifdef PIOS_INCLUDE_IBUS
4548
# include <pios_ibus_priv.h>
4649
# endif
@@ -295,6 +298,13 @@ static int32_t PIOS_SBus_Not_Inverted_Init_Helper(uint32_t *id, const struct pio
295298
return PIOS_SBus_Init(id, &sbus_cfg, driver, lower_id);
296299
}
297300
# endif /* ifdef PIOS_INCLUDE_SBUS */
301+
# ifdef PIOS_INCLUDE_DBUS
302+
303+
static int32_t PIOS_DBus_Init_Helper(uint32_t *id, const struct pios_com_driver *driver, uint32_t lower_id) {
304+
// only support usart dma double buffer mode
305+
return PIOS_DBus_Init(id, driver, lower_id);
306+
}
307+
# endif // PIOS_INCLUDE_DBUS
298308
#endif /* ifdef PIOS_INCLUDE_RCVR */
299309

300310
struct uart_function {
@@ -433,6 +443,14 @@ static const struct uart_function uart_function_map[] = {
433443
.rcvr_group = MANUALCONTROLSETTINGS_CHANNELGROUPS_SBUS,
434444
},
435445
# endif /* PIOS_INCLUDE_SBUS */
446+
447+
# ifdef PIOS_INCLUDE_DBUS
448+
[PIOS_BOARD_IO_UART_DBUS] = {
449+
.rcvr_init = &PIOS_DBus_Init_Helper,
450+
.rcvr_driver = &pios_dbus_rcvr_driver,
451+
.rcvr_group = MANUALCONTROLSETTINGS_CHANNELGROUPS_DBUS,
452+
}
453+
# endif /* PIOS_INCLUDE_DBUS */
436454
#endif /* PIOS_INCLUDE_RCVR */
437455
};
438456

flight/pios/common/pios_dbus.c

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/**
2+
******************************************************************************
3+
* @addtogroup PIOS PIOS Core hardware abstraction layer
4+
* @{
5+
* @addtogroup PIOS_DBus DJI DBus receiver functions
6+
* @brief Code to read DJI DBus receiver serial stream
7+
* @{
8+
*
9+
* @file pios_dbus.c
10+
* @author The SantyPilot Team, copyright (C) 2023.
11+
* @brief Code to read DJI DBus receiver serial stream
12+
* @see The GNU Public License (GPL) Version 3
13+
*
14+
*****************************************************************************/
15+
/*
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.
20+
*
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.
25+
*
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
29+
*/
30+
31+
#include "pios.h"
32+
33+
#ifdef PIOS_INCLUDE_DBUS
34+
35+
#define DBUS_RX_BUF_NUM 36u // avoid overflow
36+
#define DBUS_FRAME_LENGTH 18u
37+
#define DBUS_CH_VALUE_OFFSET ((uint16_t)1024)
38+
#define DBUS_CHANNEL_ERROR_VALUE 700
39+
#define DBUS_SW_DOWN 2
40+
41+
#ifndef PIOS_DBUS_BAUD_RATE
42+
#define PIOS_DBUS_BAUD_RATE 100000
43+
#endif // PIOS_DBUS_BAUD_RATE
44+
45+
#include <uavobjectmanager.h>
46+
#include "pios_dbus_priv.h"
47+
48+
/* Forward Declarations */
49+
static int32_t PIOS_DBus_Get(uint32_t rcvr_id, uint8_t channel);
50+
static uint16_t PIOS_DBus_RxInCallback(uint32_t context,
51+
uint8_t *buf,
52+
uint16_t buf_len,
53+
uint16_t *headroom,
54+
bool *need_yield);
55+
static uint8_t PIOS_DBus_Quality_Get(uint32_t rcvr_id);
56+
57+
/* Local Variables */
58+
const struct pios_rcvr_driver pios_dbus_rcvr_driver = {
59+
.read = PIOS_DBus_Get,
60+
.get_quality = PIOS_DBus_Quality_Get
61+
};
62+
63+
enum pios_dbus_dev_magic {
64+
PIOS_DBUS_DEV_MAGIC = 0x53427600,
65+
};
66+
67+
struct pios_dbus_state {
68+
uint16_t channel_data[PIOS_DBUS_NUM_INPUTS];
69+
uint8_t received_data[DBUS_FRAME_LENGTH];
70+
float quality;
71+
};
72+
73+
struct pios_dbus_dev {
74+
enum pios_dbus_dev_magic magic;
75+
struct pios_dbus_state state;
76+
};
77+
78+
/* Allocate DBus device descriptor */
79+
#if defined(PIOS_INCLUDE_FREERTOS)
80+
static struct pios_dbus_dev *PIOS_DBus_Alloc(void)
81+
{
82+
struct pios_dbus_dev *dbus_dev;
83+
84+
dbus_dev = (struct pios_dbus_dev *)pios_malloc(sizeof(*dbus_dev));
85+
if (!dbus_dev) {
86+
return NULL;
87+
}
88+
89+
dbus_dev->magic = PIOS_DBUS_DEV_MAGIC;
90+
return dbus_dev;
91+
}
92+
#else // mem malloc interface differs
93+
static struct pios_dbus_dev pios_dbus_devs[PIOS_DBUS_MAX_DEVS];
94+
static uint8_t pios_dbus_num_devs;
95+
static struct pios_dbus_dev *PIOS_DBus_Alloc(void)
96+
{
97+
struct pios_dbus_dev *dbus_dev;
98+
99+
if (pios_dbus_num_devs >= PIOS_DBUS_MAX_DEVS) {
100+
return NULL;
101+
}
102+
103+
dbus_dev = &pios_dbus_devs[pios_dbus_num_devs++];
104+
dbus_dev->magic = PIOS_DBUS_DEV_MAGIC;
105+
106+
return dbus_dev;
107+
}
108+
#endif /* if defined(PIOS_INCLUDE_FREERTOS) */
109+
110+
/* Validate DBus device descriptor */
111+
static bool PIOS_DBus_Validate(struct pios_dbus_dev *dbus_dev)
112+
{
113+
return dbus_dev->magic == PIOS_DBUS_DEV_MAGIC;
114+
}
115+
116+
/* Reset channels in case of lost signal or explicit failsafe receiver flag */
117+
static void PIOS_DBus_ResetChannels(struct pios_dbus_state *state)
118+
{
119+
for (int i = 0; i < PIOS_DBUS_NUM_INPUTS; i++) {
120+
state->channel_data[i] = PIOS_RCVR_TIMEOUT;
121+
state->quality = 0.0f;
122+
}
123+
}
124+
125+
/* Reset DBus receiver state */
126+
static void PIOS_DBus_ResetState(struct pios_dbus_state *state)
127+
{
128+
state->quality = 0.0f;
129+
PIOS_DBus_ResetChannels(state);
130+
}
131+
132+
/* Initialise DBus receiver interface */
133+
int32_t PIOS_DBus_Init(uint32_t *dbus_id,
134+
const struct pios_com_driver *driver,
135+
uint32_t lower_id) {
136+
PIOS_DEBUG_Assert(dbus_id);
137+
PIOS_DEBUG_Assert(driver);
138+
139+
struct pios_dbus_dev *dbus_dev;
140+
141+
dbus_dev = (struct pios_dbus_dev *)PIOS_DBus_Alloc();
142+
if (!dbus_dev) {
143+
return -1;
144+
}
145+
146+
PIOS_DBus_ResetState(&(dbus_dev->state));
147+
148+
*dbus_id = (uint32_t)dbus_dev;
149+
150+
/* Set rest of the parameters and enable */
151+
// there is one USART_Init before
152+
if (driver->set_config) {
153+
driver->set_config(lower_id, PIOS_COM_Word_length_8b, PIOS_COM_Parity_Even, PIOS_COM_StopBits_1, PIOS_DBUS_BAUD_RATE);
154+
}
155+
156+
/* Set inverted UART and IRQ priority */
157+
//if (driver->ioctl) {
158+
// enum PIOS_USART_Inverted param = cfg->non_inverted ? 0 : PIOS_USART_Inverted_Rx;
159+
// driver->ioctl(lower_id, PIOS_IOCTL_USART_SET_INVERTED, &param);
160+
161+
// uint8_t irq_prio = PIOS_IRQ_PRIO_HIGH;
162+
// driver->ioctl(lower_id, PIOS_IOCTL_USART_SET_IRQ_PRIO, &irq_prio);
163+
//}
164+
165+
/* Set comm driver callback */
166+
driver->bind_rx_cb(lower_id, PIOS_DBus_RxInCallback, *dbus_id);
167+
168+
//if (!PIOS_RTC_RegisterTickCallback(PIOS_DBus_Supervisor, *dbus_id)) {
169+
// PIOS_DEBUG_Assert(0);
170+
//}
171+
172+
return 0;
173+
}
174+
175+
/**
176+
* Get the value of an input channel
177+
* \param[in] channel Number of the channel desired (zero based)
178+
* \output PIOS_RCVR_INVALID channel not available
179+
* \output PIOS_RCVR_TIMEOUT failsafe condition or missing receiver
180+
* \output >=0 channel value
181+
*/
182+
static int32_t PIOS_DBus_Get(uint32_t rcvr_id, uint8_t channel)
183+
{
184+
struct pios_dbus_dev *dbus_dev = (struct pios_dbus_dev *)rcvr_id;
185+
186+
if (!PIOS_DBus_Validate(dbus_dev)) {
187+
return PIOS_RCVR_INVALID;
188+
}
189+
190+
/* return error if channel is not available */
191+
if (channel >= PIOS_DBUS_NUM_INPUTS) {
192+
return PIOS_RCVR_INVALID;
193+
}
194+
195+
return dbus_dev->state.channel_data[channel];
196+
}
197+
198+
/**
199+
* Compute channel_data[] from received_data[].
200+
* For efficiency it unrolls first 8 channels without loops and does the
201+
* same for other 8 channels. Also 2 discrete channels will be set.
202+
*/
203+
static void PIOS_DBus_UnrollChannels(struct pios_dbus_state *state)
204+
{
205+
uint8_t *s = state->received_data;
206+
uint16_t *d = state->channel_data;
207+
208+
#define F(v, s) (((v) >> (s)) & 0x7ff)
209+
210+
/* unroll channels 1-8 */
211+
d[0] = F(s[0] | s[1] << 8, 0); // Channel0
212+
d[1] = F(s[1] | s[2] << 8, 3); // Channel1
213+
d[2] = F(s[2] | s[3] << 8 | s[4] << 16, 6); // Channel2
214+
d[3] = F(s[4] | s[5] << 8, 1); // Channel3
215+
d[4] = s[16] | (s[17] << 8); //NULL
216+
217+
d[5] = ((s[5] >> 4) & 0x0003); //!< Switch left
218+
d[6] = ((s[5] >> 4) & 0x000C) >> 2; //!< Switch right
219+
d[7] = s[6] | (s[7] << 8); //!< Mouse X axis
220+
d[8] = s[8] | (s[9] << 8); //!< Mouse Y axis
221+
d[9] = s[10] | (s[11] << 8); //!< Mouse Z axis
222+
d[10] = s[12]; //!< Mouse Left Is Press ?
223+
d[11] = s[13]; //!< Mouse Right Is Press ?
224+
d[12] = s[14] | (s[15] << 8); //!< KeyBoard value
225+
226+
d[0] -= DBUS_CH_VALUE_OFFSET;
227+
d[1] -= DBUS_CH_VALUE_OFFSET;
228+
d[2] -= DBUS_CH_VALUE_OFFSET;
229+
d[3] -= DBUS_CH_VALUE_OFFSET;
230+
d[4] -= DBUS_CH_VALUE_OFFSET;
231+
}
232+
233+
static uint8_t PIOS_DBus_ChannelDataValid(struct pios_dbus_state *state) {
234+
uint16_t *ch = state->channel_data;
235+
#define ABS(x) (x > 0 ? x : -x)
236+
if (ABS(ch[0]) > DBUS_CHANNEL_ERROR_VALUE ||
237+
ABS(ch[1]) > DBUS_CHANNEL_ERROR_VALUE ||
238+
ABS(ch[2]) > DBUS_CHANNEL_ERROR_VALUE ||
239+
ABS(ch[3]) > DBUS_CHANNEL_ERROR_VALUE ||
240+
ch[5] == 0 || ch[6] == 0) {
241+
for (uint8_t i = 0; i < 5; i++) { //ch0~4
242+
ch[i] = 0;
243+
}
244+
ch[5] = DBUS_SW_DOWN; //sw
245+
ch[6] = DBUS_SW_DOWN;
246+
for (uint8_t i = 7; i < 13; i++) { // mouse * 5 + key * 1
247+
ch[i] = 0;
248+
}
249+
return 0; // invalid
250+
}
251+
}
252+
253+
/* Comm byte received callback */
254+
static uint16_t PIOS_DBus_RxInCallback(uint32_t context,
255+
uint8_t *buf,
256+
uint16_t buf_len,
257+
uint16_t *headroom,
258+
bool *need_yield)
259+
{
260+
if (buf_len != DBUS_FRAME_LENGTH) {
261+
return 0;
262+
}
263+
struct pios_dbus_dev *dbus_dev = (struct pios_dbus_dev *)context;
264+
bool valid = PIOS_DBus_Validate(dbus_dev);
265+
PIOS_Assert(valid);
266+
struct pios_dbus_state *state = &(dbus_dev->state);
267+
for (auto i = 0; i < buf_len; i++) {
268+
state->received_data[i] = buf[i];
269+
}
270+
PIOS_DBus_UnrollChannels(state);
271+
volatile uint16_t ch[16];
272+
for (auto i = 0; i < 13; i++) {
273+
ch[i] = state->channel_data[i];
274+
}
275+
if (!PIOS_DBus_ChannelDataValid(state)) {
276+
//PIOS_USART_DMA_Reinit(context);
277+
return 0;
278+
}
279+
/* We never need a yield */
280+
*need_yield = false;
281+
return buf_len;
282+
}
283+
284+
static uint8_t PIOS_DBus_Quality_Get(uint32_t dbus_id)
285+
{
286+
//TBD
287+
return 255;
288+
}
289+
290+
#endif /* PIOS_INCLUDE_DBUS */
291+
292+
/**
293+
* @}
294+
* @}
295+
*/

flight/pios/common/pios_dma.c

Whitespace-only changes.

flight/pios/inc/pios_board_io.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ typedef enum {
212212
PIOS_BOARD_IO_UART_SBUS, /* rcvr, normal vs not-inverted from HwSettings.SBusMode */
213213
PIOS_BOARD_IO_UART_SBUS_NORMAL, /* helper only */
214214
PIOS_BOARD_IO_UART_SBUS_NOT_INVERTED, /* helper only */
215+
PIOS_BOARD_IO_UART_DBUS,
215216
PIOS_BOARD_IO_UART_DSM_MAIN, /* rcvr */
216217
PIOS_BOARD_IO_UART_DSM_FLEXI, /* rcvr */
217218
PIOS_BOARD_IO_UART_DSM_RCVR, /* rcvr */

flight/pios/inc/pios_dbus.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
******************************************************************************
3+
* @addtogroup PIOS PIOS Core hardware abstraction layer
4+
* @{
5+
* @addtogroup PIOS_DBus DBus receiver functions
6+
* @{
7+
*
8+
* @file pios_dbus.h
9+
* @author The SantyPilot Team, Copyright (C) 2023.
10+
* @brief DJI DBus functions header.
11+
* @see The GNU Public License (GPL) Version 3
12+
*
13+
*****************************************************************************/
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, write to the Free Software Foundation, Inc.,
27+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28+
*/
29+
30+
#ifndef PIOS_DBUS_H
31+
#define PIOS_DBUS_H
32+
33+
/* Global Types */
34+
35+
/* Public Functions */
36+
37+
#endif /* PIOS_DBUS_H */
38+
39+
/**
40+
* @}
41+
* @}
42+
*/

0 commit comments

Comments
 (0)