Skip to content

Commit 47cfbce

Browse files
committed
comments updated
1 parent 2ccc0b6 commit 47cfbce

File tree

9 files changed

+172
-131
lines changed

9 files changed

+172
-131
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# SimLinkModule-Software
22

3-
This is the software for a BLE game controller expansion module for the TBS Tango 2. The data transfer between the module and the remote control takes place via CRSF. An output for the BLE connection status is done via an OLED display type SSD1306.
3+
This is the software for a BLE game controller expansion module for the TBS Tango 2. The data transfer between the module and the remote control takes place via CRSF. The first eight channels are transmitted analog and the remaining eight channels are transmitted digital. An output for the BLE connection status is done via an OLED display type SSD1306. ESP-32 Dev Kit C V4 from AZ- Delivery used.
44

55
## Tested operating systems
6-
- [x] Windows 11
7-
- [x] Android 10
8-
- [x] Pop! OS 22.04 LTS
6+
- [x] Windows 11 (tested with Velocidrone)
7+
- [x] Android 10 (tested with FPV.SkyDive)
8+
- [x] Pop! OS 22.04 LTS (tested with Velocidrone)
99

1010
## TODO
1111
- [ ] Create a case → will be provided to another repo
@@ -17,5 +17,5 @@ This is the software for a BLE game controller expansion module for the TBS Tang
1717
- [ ] iOS not working. Connection can be established and automatic reconnection also works. RPA works. HID data is also subscribed and sent, but not processed by iOS.
1818
- Probably needs a closer look with XCode and Packetlogger (Mac required :thinking: )
1919
- Or a ticket to the Apple Developer Technical Support Team (Apple Developer account required :thinking: )
20-
- [ ] Pop! OS kernel doesn't recognize HID version when connecting via BLE (always version 0.0) → Works with an XBox Controller
21-
- [ ] For an Xbox controller, the client configuration descriptor of the report is set to 01 00 (by default). Here the default is 00 00 → Should be according to the specification.
20+
- [ ] Pop! OS kernel doesn't recognize HID version when connecting via BLE (always version 0.0) → Linux Kernel output is correct with an XBox controller
21+
- [ ] For an XBox controller, the client configuration descriptor of the report is set to 01 00 (by default). Here the default is 00 00 → Should be according to the specification.

components/crsf/crsf.c

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,30 @@ static uint8_t scale_Range_Digital(uint16_t value);
1818

1919
ChannelDataStruct channelData = {0};
2020

21+
/**
22+
* Calc crc for a single char.
23+
*
24+
* @param crc current crc value
25+
* @param a char to check
26+
* @return new crc value
27+
*/
2128
static uint8_t crcSingleChar(uint8_t crc, uint8_t a)
2229
{
30+
//move char bitstring eight times to the left and every time there is a 1 at the msb then xor with the generatorpolynom 0xD5 --> normal crc calculation
2331
crc ^= a;
24-
//zeichen wird acht mal nach links geschoben und jedes mal geschaut ob höchste stelle eine 1 ist, wenn dann polynom xor --> klassisches crc rechnen
2532
for (int i = 0; i < 8; i++) {
2633
crc = (crc << 1) ^ ((crc & 0x80) ? 0xD5 : 0);
2734
}
2835
return crc;
2936
}
3037

31-
//get crc from message
38+
/**
39+
* CRC calculation for a whole string
40+
*
41+
* @param message get crc for this string
42+
* @param length length of the string
43+
* @return return the crc value
44+
*/
3245
static uint8_t crcMessage(uint8_t message[], uint8_t length)
3346
{
3447
uint8_t crc = 0;
@@ -38,12 +51,22 @@ static uint8_t crcMessage(uint8_t message[], uint8_t length)
3851
return crc;
3952
}
4053

41-
//scale from range [173,1811] to range [0,2047]
54+
/**
55+
* scale range from [173,1811] to [0,2047]
56+
*
57+
* @param value value to scale
58+
* @return new scaled value
59+
*/
4260
static uint16_t scale_Range_Analog(uint16_t value){
4361
return (uint16_t)((value-173)*1.25);
4462
}
4563

46-
//scale from range [173,1811] to range [0,1]
64+
/**
65+
* @brief scale range from [173,1811] to [0,1]
66+
*
67+
* @param value value to scale
68+
* @return new scaled value
69+
*/
4770
static uint8_t scale_Range_Digital(uint16_t value){
4871
if(value <= 992){
4972
return 0;
@@ -53,9 +76,9 @@ static uint8_t scale_Range_Digital(uint16_t value){
5376
}
5477

5578
void initCRSF_read(){
56-
/* Configure parameters of an UART driver,
57-
* communication pins and install the driver */
58-
//uart driver erstellt eigene interrupts
79+
/* configure the uart driver
80+
* the uart driver creates his own interrupt
81+
*/
5982
uart_config_t uart_config = {
6083
.baud_rate = 420000,
6184
.data_bits = UART_DATA_8_BITS,
@@ -65,19 +88,20 @@ void initCRSF_read(){
6588
.source_clk = UART_SCLK_APB,
6689
};
6790

68-
//UART 2 verwenden, da uart 0 für console benötigt wird und uart1 hab ich gelesen für spi oder irgendetwas anderes
91+
//use uart 2, because uart 0 is used for the console and uart1 could be used for spi
6992
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, 1024 * 2, 0, 0, NULL, 0));
7093
uart_set_line_inverse(UART_NUM_2,UART_SIGNAL_RXD_INV);
7194
ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_config));
7295
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
7396

74-
//interrupt auslösen bei timeout (primär) und bei überlauf eines thresholds
97+
//trigger interrupt after the timeout (primary) or if a overflow happens
7598
uart_intr_config_t uart_intr = {
7699
.intr_enable_mask = UART_INTR_RXFIFO_TOUT | UART_INTR_RXFIFO_FULL,
77100
.rx_timeout_thresh = 10,
78101
.rxfifo_full_thresh = 200,
79102
};
80-
//diese interrupt schwellwellen speichern
103+
104+
//store the interrupt thresholds
81105
ESP_ERROR_CHECK(uart_intr_config(UART_NUM_2, &uart_intr));
82106
ESP_ERROR_CHECK(uart_enable_rx_intr(UART_NUM_2));
83107
}
@@ -88,72 +112,72 @@ void crsf_get_ChannelData_task(void *arg)
88112
uint8_t *data = (uint8_t *) malloc(1024);
89113

90114
while (1) {
91-
//bool if channel data changed from channeldata t-1
115+
//bool if channel data changed from channeldata t-1. Used to send a BLE update
92116
bool changed = false;
93117

94118
// get size in uart buffer
95119
int length = 0;
96120
ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_2, (size_t*)&length));
97121

98-
//mit daten arbeiten, wenn welche vorhanden sind
122+
//work with the data, if data exists
99123
if(length){
100124

101125
//read uart data
102126
int len = uart_read_bytes(UART_NUM_2, data, length, 20 / portTICK_PERIOD_MS);
103127

104-
//RX Buffer leeren wenn Frame im temporären buffer
128+
//clear rx buffer after the data is in the temp buffer
105129
uart_flush(UART_NUM_2);
106130

107-
//len of data read from rx buffer
131+
//check again the length of the data in the temp buffer
108132
if(len > 0){
109-
//daten durchgehen
133+
//loop through data
110134
for(int i = 0; i < len; i++){
111-
//Paketaufbau: 0xEE (Addresse) + 0x18 (Länge in Byte) + 0x16 (Typenfeld: Kanaldaten)
135+
//check for packets with the data: 0xEE(address) + 0x18(length in Bytes) + 0x16(typefield: channel data)
112136
if((data[i] == 0xEE) && (i+25)<len){
113137
if(data[i+2] == 0x16){
114-
//CRC überprüfen ob kein rest rauskommst
138+
//CRC check. should be zero
115139
if(crcMessage(data+i+2, data[i+1]) == 0){
116140

117-
//used = wie viel Bits bereits in einen Byte verwendet wurden
141+
//used = How many bits were used in a temp buffer byte.
118142
int used = 0;
119-
//dataIndex = Index des Datenbytes im Buffer
143+
//dataIndex = Index of the data byte in the buffer
120144
int dataIndex = i+3;
121145

122-
//Da 16 kanäle vorhanden sind muss es 16 mal durchgegangen werden
146+
//loop through all 16 channels
123147
for(int j = 0; j<16; j++){
124-
//Die restlichen vorhandenen Daten eines Bytes an LSB setzen
148+
//Set the remaining existing data of a temp buffer byte to LSB.
125149
uint16_t value = data[dataIndex] >> used;
126150

127-
//ein neues Byte muss verwendet werden
151+
//use a new byte from the temp buffer.
128152
dataIndex++;
129153

130-
//Anzahl der noch vorhanden Bits eines Bytes im angefangenen Byte
154+
//Number of remaining channel bits of a byte in the started temp buffer byte.
131155
uint8_t availableBits = 8-used;
132156

133157
if(11-availableBits > 8){
134-
//3Bytes werden benötigt, wenn für ein Kanal (11Bit) noch mehr als 8 Bit benötigt werden
158+
//3bytes are required if more than 8 bits are still needed for one channel (11bit)
135159

136-
//komplettes zweites Byte verwenden
160+
//use entire second byte
137161
value = value | (data[dataIndex] << availableBits);
138-
//ein neues Byte muss verwendet werden
162+
//use a new Byte
139163
dataIndex++;
140164

141-
//vom dritten Byte noch die benötigten Bits in die MSB stellen schieben
165+
//from the third byte still shift the needed bits into the MSB
142166
value = value | ((data[dataIndex]&((1U << (11-(8+availableBits))) - 1U)) << (8+availableBits));
143167

144-
//Anzahl der verwendeten Bits im akutellen Byte neu berechnen
168+
//Recalculate number of used bits in current temp buffer byte
145169
used = 11-(8+availableBits);
146170
} else {
147-
//Wenn nur ein zweites Byte für 11Bit-Daten benötigt wird
171+
//If only a second byte is needed for 11Bit data
148172

149-
//Aus dem zweiten Byte noch die fehlenden Bits an die MSB stellen schieben von 11 Bit
173+
//Move the missing bits from the second byte to the MSB positions. (11Bit per channel)
150174
value = value | ((data[dataIndex]&((1U << (11-availableBits)) - 1U)) << availableBits);
151175

152-
//berechnen wie viele Bits im aktuellen Byte schon verwendet wurden
176+
//calculate how many bits in the current temp buffer byte have already been used
153177
used = 11-availableBits;
154178
}
155179

156-
//Kanaldaten abspeichern --> ersten 8 kanäle sind analog rest digital
180+
//store channel data --> first 8 channel are analog rest ist digital
157181
uint16_t newVal;
158182
uint8_t origDataButtons;
159183
switch(j){
@@ -235,18 +259,18 @@ void crsf_get_ChannelData_task(void *arg)
235259
break;
236260
}
237261
}
238-
//Kanaldaten ausgeben
239-
//wenn esp_logi ausgegeben wird dann kann es sein das watchdog timer für den task nicht zurückgesetzt wird ist aber nicht so schlimm solang der output einfach weggelassen wird in stpäteren code
262+
240263
if(changed){
241264
if(notify_state_report_data){
242265
struct os_mbuf *om;
243266

244-
//dann passt die größe vom paket zu den report deskriptor wenn 17 fesst vorprogrammiert ist --> sizeof(channelData) gibt 18
267+
//set size to 17, because of padding bits in the struct channelData calculates 18
245268
om = ble_hs_mbuf_from_flat(&channelData, 17);
246269
//Deprecated. Should not be used. Use ble_gatts_notify_custom instead.
247270
ble_gattc_notify_custom(conn_handle, report_data_handle, om);
248271
}
249272
}
273+
//if esp_logi is used then the watchdog timer for the task may not be reset
250274
//ESP_LOGI("Channel-Data","%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d", channelData.throttle, channelData.yaw, channelData.pitch, channelData.roll, channelData.aux1, channelData.aux2, channelData.aux3, channelData.aux4, (channelData.buttons & (0x01<<0)), (channelData.buttons & (0x01<<1)), (channelData.buttons & (0x01<<2)), (channelData.buttons & (0x01<<3)), (channelData.buttons & (0x01<<4)), (channelData.buttons & (0x01<<5)), (channelData.buttons & (0x01<<6)), (channelData.buttons & (0x01<<7)));
251275
break;
252276
}
@@ -255,6 +279,7 @@ void crsf_get_ChannelData_task(void *arg)
255279
}
256280
}
257281
} else {
282+
//Create a delay if no data could be loaded
258283
vTaskDelay(10 / portTICK_PERIOD_MS);
259284
}
260285
}

components/crsf/include/crsf.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,19 @@ typedef struct ChannelDataStruct{
1616
uint8_t buttons; //buttons = aux12(b8) .. aux5(b1)
1717
} ChannelDataStruct;
1818

19-
//store for channeldata
19+
//global store for channeldata
2020
extern ChannelDataStruct channelData;
2121

22+
/**
23+
* initializes UART to read remote control channel data.
24+
*/
2225
void initCRSF_read();
26+
27+
/**
28+
* Read the UART data. Check if it is the right frame and make a CRC check. Then process the channel data and convert it to a range from 0 to 2047.
29+
*
30+
* @param arg Required for FreeRTOS. Not used.
31+
*/
2332
void crsf_get_ChannelData_task(void *arg);
2433

2534
#endif

components/ssd1306/include/ssd1306_font.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
#ifndef SSD1306_FONT_H
2-
#define SSD1306_FONT_H
3-
41
//font: VCR OSD Mono by Riciery Leal
52
//font is free even for commercial purposes.
63
//https://www.dafont.com/font-comment.php?file=vcr_osd_mono
74
//https://www.dafont.com/de/vcr-osd-mono.font
85

6+
#ifndef SSD1306_FONT_H
7+
#define SSD1306_FONT_H
8+
99
#define CHAR_WIDTH 10
1010
#define CHAR_HEIGHT 14
1111

12-
//Ein Hex wert stellt eine Spalte eines Zeichen dar
13-
//lsb sind die unteren pixel des zeichens
14-
//die 2 msb werden immer übersprungen
12+
/*One hex-value is a column of a char
13+
*the LSB of a hex-value are the bottom pixel of a char
14+
*two MSBs are skipped
15+
*/
1516
const uint16_t VCR_OSD_MONO[43][10] = {
1617
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}, //
1718
{0x0038,0x00FE,0x19C7,0x1983,0x1983,0x1983,0x1983,0x1CC6,0x0FFF,0x07FF}, // a
@@ -55,7 +56,7 @@ const uint16_t VCR_OSD_MONO[43][10] = {
5556
{0x0000,0x0000,0x0000,0x0000,0x07F3,0x07F3,0x0000,0x0000,0x0000,0x0000}, // !
5657
{0x0000,0x0000,0x0000,0x0000,0x0003,0x0003,0x0000,0x0000,0x0000,0x0000}, // .
5758
{0x0000,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x0000}, // -
58-
{0x0000,0x3FFF,0x3FFF,0x3003,0x3003,0x3003,0x3003,0x3FFF,0x3FFF,0x0000}, // unknown
59+
{0x0000,0x3FFF,0x3FFF,0x3003,0x3003,0x3003,0x3003,0x3FFF,0x3FFF,0x0000}, // unknown char
5960
};
6061

6162
#endif

components/ssd1306/include/ssd1306_images.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
//drawn in: https://www.pixilart.com/draw
55
//converted from png to bitstring with: https://www.dcode.fr/binary-image
6-
//convert bitstring to hex array: Bin2Hex.py <filename> in tools folder
7-
6+
//convert bitstring to hex array: bin2ByteArray.py <filename> in tools folder
87
const uint8_t connectedImage[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,0xF8,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xE0,0xE0,0x60,0x60,0x60,0x60,0xE0,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xF0,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x06,0x06,0x06,0x06,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xF0,0xE0,0xE0,0x60,0x60,0x60,0x70,0x30,0x30,0x30,0x38,0x18,0x18,0x18,0x18,0x18,0x1C,0x0C,0x0E,0x0E,0x06,0x06,0x06,0x06,0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x1C,0x1C,0x18,0x18,0x38,0x38,0x30,0x30,0x70,0xE0,0xE0,0xC0,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0x07,0x06,0x0E,0x0E,0x0C,0x1C,0x18,0x18,0x18,0x18,0x18,0x1C,0x0C,0x0C,0x0C,0x0C,0x0E,0x0E,0x06,0x06,0x06,0x07,0x03,0x03,0x03,0x03,0x01,0x01,0x0F,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60,0x60,0x60,0x60,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x1F,0x3F,0x3F,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F,0x3F,0x3F,0x1F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
98

109
#endif

0 commit comments

Comments
 (0)