Skip to content

Commit 20f252a

Browse files
authored
Merge pull request #2 from SimLinkModule/uart
Uart
2 parents 8a25d02 + 4b41fb2 commit 20f252a

File tree

10 files changed

+509
-4
lines changed

10 files changed

+509
-4
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"string": "c",
1010
"string_view": "c",
1111
"ble_svc_gap.h": "c",
12-
"console.h": "c"
12+
"console.h": "c",
13+
"esp_nimble_hci.h": "c"
1314
}
1415
}

components/crsf/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(srcs "crsf.c")
2+
3+
idf_component_register(SRCS "${srcs}"
4+
INCLUDE_DIRS "include")

components/crsf/crsf.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include "crsf.h"
2+
3+
uint8_t crcSingleChar(uint8_t crc, uint8_t a)
4+
{
5+
crc ^= a;
6+
//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
7+
for (int i = 0; i < 8; i++) {
8+
crc = (crc << 1) ^ ((crc & 0x80) ? 0xD5 : 0);
9+
}
10+
return crc;
11+
}
12+
13+
//get crc from message
14+
uint8_t crcMessage(uint8_t message[], uint8_t length)
15+
{
16+
uint8_t crc = 0;
17+
for (int i = 0; i < length; i++) {
18+
crc = crcSingleChar(crc, message[i]);
19+
}
20+
return crc;
21+
}
22+
23+
void initCRSF_read(){
24+
/* Configure parameters of an UART driver,
25+
* communication pins and install the driver */
26+
//uart driver erstellt eigene interrupts
27+
uart_config_t uart_config = {
28+
.baud_rate = 420000,
29+
.data_bits = UART_DATA_8_BITS,
30+
.parity = UART_PARITY_DISABLE,
31+
.stop_bits = UART_STOP_BITS_1,
32+
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
33+
.source_clk = UART_SCLK_APB,
34+
};
35+
36+
//UART 2 verwenden, da uart 0 für console benötigt wird und uart1 hab ich gelesen für spi oder irgendetwas anderes
37+
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, 1024 * 2, 0, 0, NULL, 0));
38+
uart_set_line_inverse(UART_NUM_2,UART_SIGNAL_RXD_INV);
39+
ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_config));
40+
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
41+
42+
//interrupt auslösen bei timeout (primär) und bei überlauf eines thresholds
43+
uart_intr_config_t uart_intr = {
44+
.intr_enable_mask = UART_INTR_RXFIFO_TOUT | UART_INTR_RXFIFO_FULL,
45+
.rx_timeout_thresh = 10,
46+
.rxfifo_full_thresh = 200,
47+
};
48+
//diese interrupt schwellwellen speichern
49+
ESP_ERROR_CHECK(uart_intr_config(UART_NUM_2, &uart_intr));
50+
ESP_ERROR_CHECK(uart_enable_rx_intr(UART_NUM_2));
51+
}
52+
53+
void crsf_get_ChannelData_task(void *arg)
54+
{
55+
// Configure a temporary buffer for the incoming data
56+
uint8_t *data = (uint8_t *) malloc(1024);
57+
58+
while (1) {
59+
// get size in uart buffer
60+
int length = 0;
61+
ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_2, (size_t*)&length));
62+
63+
//mit daten arbeiten, wenn welche vorhanden sind
64+
if(length){
65+
66+
//read uart data
67+
int len = uart_read_bytes(UART_NUM_2, data, length, 20 / portTICK_RATE_MS);
68+
69+
//RX Buffer leeren wenn Frame im temporären buffer
70+
uart_flush(UART_NUM_2);
71+
72+
//len of data read from rx buffer
73+
if(len > 0){
74+
//daten durchgehen
75+
for(int i = 0; i < len; i++){
76+
//Paketaufbau: 0xEE (Addresse) + 0x18 (Länge in Byte) + 0x16 (Typenfeld: Kanaldaten)
77+
if((data[i] == 0xEE) && (i+25)<len){
78+
if(data[i+2] == 0x16){
79+
//CRC überprüfen ob kein rest rauskommst
80+
if(crcMessage(data+i+2, data[i+1]) == 0){
81+
82+
//used = wie viel Bits bereits in einen Byte verwendet wurden
83+
int used = 0;
84+
//dataIndex = Index des Datenbytes im Buffer
85+
int dataIndex = i+3;
86+
87+
//Da 16 kanäle vorhanden sind muss es 16 mal durchgegangen werden
88+
for(int j = 0; j<16; j++){
89+
//Die restlichen vorhandenen Daten eines Bytes an LSB setzen
90+
uint16_t value = data[dataIndex] >> used;
91+
92+
//ein neues Byte muss verwendet werden
93+
dataIndex++;
94+
95+
//Anzahl der noch vorhanden Bits eines Bytes im angefangenen Byte
96+
uint8_t availableBits = 8-used;
97+
98+
if(11-availableBits > 8){
99+
//3Bytes werden benötigt, wenn für ein Kanal (11Bit) noch mehr als 8 Bit benötigt werden
100+
101+
//komplettes zweites Byte verwenden
102+
value = value | (data[dataIndex] << availableBits);
103+
//ein neues Byte muss verwendet werden
104+
dataIndex++;
105+
106+
//vom dritten Byte noch die benötigten Bits in die MSB stellen schieben
107+
value = value | ((data[dataIndex]&((1U << (11-(8+availableBits))) - 1U)) << (8+availableBits));
108+
109+
//Anzahl der verwendeten Bits im akutellen Byte neu berechnen
110+
used = 11-(8+availableBits);
111+
} else {
112+
//Wenn nur ein zweites Byte für 11Bit-Daten benötigt wird
113+
114+
//Aus dem zweiten Byte noch die fehlenden Bits an die MSB stellen schieben von 11 Bit
115+
value = value | ((data[dataIndex]&((1U << (11-availableBits)) - 1U)) << availableBits);
116+
117+
//berechnen wie viele Bits im aktuellen Byte schon verwendet wurden
118+
used = 11-availableBits;
119+
}
120+
121+
//Kanaldaten abspeichern
122+
channelData[j] = value;
123+
}
124+
//Kanaldaten ausgeben
125+
//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
126+
//ESP_LOGI("Channel-Data","%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d", channelData[0], channelData[1], channelData[2], channelData[3], channelData[4], channelData[5], channelData[6], channelData[7], channelData[8], channelData[9], channelData[10], channelData[11], channelData[12], channelData[13], channelData[14], channelData[15]);
127+
break;
128+
}
129+
}
130+
}
131+
}
132+
}
133+
} else {
134+
vTaskDelay(10 / portTICK_PERIOD_MS);
135+
}
136+
}
137+
}

components/crsf/include/crsf.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef CRSF_H
2+
#define CRSF_H
3+
4+
#include "hal/uart_hal.h"
5+
#include "driver/uart.h"
6+
#include "freertos/task.h"
7+
#include "esp_log.h"
8+
9+
//store channel data in array
10+
static uint16_t channelData[16] = {0};
11+
12+
uint8_t crcSingleChar(uint8_t crc, uint8_t a);
13+
uint8_t crcMessage(uint8_t message[], uint8_t length);
14+
void initCRSF_read();
15+
void crsf_get_ChannelData_task(void *arg);
16+
17+
#endif

components/ssd1306/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(srcs "ssd1306.c")
2+
3+
idf_component_register(SRCS "${srcs}"
4+
INCLUDE_DIRS "include")
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#ifndef SSD1306_H
2+
#define SSD1306_H
3+
4+
//credits: https://github.com/nopnop2002/esp-idf-ssd1306
5+
// http://robotcantalk.blogspot.com/2015/03/interfacing-arduino-with-ssd1306-driven.html
6+
7+
#include "driver/i2c.h"
8+
#include "esp_log.h"
9+
#include <string.h>
10+
#include <stdbool.h>
11+
12+
//SLA (0x3C) + WRITE_MODE (0x00) = 0x78 (0b01111000)
13+
#define SSD1306_ADDRESS 0x3C
14+
15+
//allgemeine infos
16+
//startup des ssd1306 wird durch Kondensatoren auf dem PCB geregelt --> beachten bei pcb design
17+
#define SSD1306_WIDTH 128
18+
#define SSD1306_HEIGHT 32
19+
#define SSD1306_PAGES 8
20+
#define SSD1306_TAG "SSD1306"
21+
#define SSD1306_I2C_NUM_CON I2C_NUM_0
22+
23+
//setzen des controllbytes für die art der daten die folgend kommen
24+
#define SSD1306_CONTROL_BYTE_CMD_STREAM 0x00
25+
#define SSD1306_CONTROL_BYTE_CMD_SINGLE 0x80
26+
#define SSD1306_CONTROL_BYTE_DATA_SINGLE 0xC0
27+
#define SSD1306_CONTROL_BYTE_DATA_STREAM 0x40
28+
29+
//grundbefehle
30+
#define SSD1306_CMD_SET_CONTRAST 0x81 // gefolgt von 0x7F
31+
#define SSD1306_CMD_DISPLAY_RAM 0xA4
32+
#define SSD1306_CMD_DISPLAY_ALLON 0xA5
33+
#define SSD1306_CMD_DISPLAY_NORMAL 0xA6
34+
#define SSD1306_CMD_DISPLAY_INVERTED 0xA7
35+
#define SSD1306_CMD_DISPLAY_OFF 0xAE
36+
#define SSD1306_CMD_DISPLAY_ON 0xAF
37+
38+
//GDDRAM (Graphic Display Data RAM) adressierung
39+
#define SSD1306_CMD_SET_MEMORY_ADDR_MODE 0x20
40+
#define SSD1306_CMD_SET_HORI_ADDR_MODE 0x00 // horizontaler adressierungsmodus
41+
#define SSD1306_CMD_SET_VERT_ADDR_MODE 0x01 // vertikaler adressierungsmodus
42+
#define SSD1306_CMD_SET_PAGE_ADDR_MODE 0x02 // page adressierungsmodus
43+
#define SSD1306_CMD_SET_COLUMN_RANGE 0x21 // can be used only in HORZ/VERT mode - follow with 0x00 and 0x7F = COL127
44+
#define SSD1306_CMD_SET_PAGE_RANGE 0x22 // can be used only in HORZ/VERT mode - follow with 0x00 and 0x07 = PAGE7
45+
46+
//Hardwarekonfiguration
47+
#define SSD1306_CMD_SET_DISPLAY_START_LINE 0x40
48+
#define SSD1306_CMD_SET_SEGMENT_REMAP_0 0xA0
49+
#define SSD1306_CMD_SET_SEGMENT_REMAP_1 0xA1
50+
#define SSD1306_CMD_SET_MUX_RATIO 0xA8 // follow with 0x3F = 64 MUX
51+
#define SSD1306_CMD_SET_COM_SCAN_MODE_1 0xC8
52+
#define SSD1306_CMD_SET_COM_SCAN_MODE_0 0xC0
53+
#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3 // follow with 0x00
54+
#define SSD1306_CMD_SET_COM_PIN_MAP 0xDA // follow with 0x12
55+
#define SSD1306_CMD_NOP 0xE3 // NOP
56+
57+
// Timing and Driving Scheme
58+
#define SSD1306_CMD_SET_DISPLAY_CLK_DIV 0xD5 // follow with 0x80
59+
#define SSD1306_CMD_SET_PRECHARGE 0xD9 // follow with 0xF1
60+
#define SSD1306_CMD_SET_VCOMH_DESELECT 0xDB // follow with 0x30
61+
62+
// Charge Pump
63+
#define SSD1306_CMD_SET_CHARGE_PUMP 0x8D // follow with 0x14
64+
65+
// Scrolling Befehle
66+
#define SSD1306_CMD_DEACTIVE_SCROLL 0x2E
67+
68+
//buffer damit der aktuelle Output auch im Speicher des ESP vorhanden ist
69+
uint8_t* ssd1306_buffer;
70+
71+
void ssd1306_init();
72+
void I2C_master_init();
73+
void ssd1306_clear();
74+
void ssd1306_display();
75+
void ssd1306_setPixel(uint8_t x, uint8_t y, bool status);
76+
void ssd1306_setChar(char c, uint8_t x, uint8_t y);
77+
void ssd1306_setString(const char* str, uint8_t x, uint8_t y);
78+
79+
#endif
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef SSD1306_FONT_H
2+
#define SSD1306_FONT_H
3+
4+
#define CHAR_WIDTH 10
5+
#define CHAR_HEIGHT 14
6+
7+
//Ein Hex wert stellt eine Spalte eines Zeichen dar
8+
//lsb sind die unteren pixel des zeichens
9+
//die 2 msb werden immer übersprungen
10+
const uint16_t VCR_OSD_MONO[43][10] = {
11+
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}, //
12+
{0x0038,0x00FE,0x19C7,0x1983,0x1983,0x1983,0x1983,0x1CC6,0x0FFF,0x07FF}, // a
13+
{0x3FFF,0x3FFF,0x01FC,0x038E,0x0707,0x0603,0x0707,0x038E,0x01FC,0x00F8}, // b
14+
{0x01FC,0x03FE,0x0707,0x0603,0x0603,0x0603,0x0603,0x0707,0x038E,0x018C}, // c
15+
{0x00F8,0x01FC,0x038E,0x0707,0x0603,0x0707,0x038E,0x01FC,0x3FFF,0x3FFF}, // d
16+
{0x01FC,0x03FE,0x0767,0x0663,0x0663,0x0663,0x0663,0x0767,0x03E6,0x01C4}, // e
17+
{0x0000,0x0300,0x0300,0x0300,0x1FFF,0x3FFF,0x3300,0x3300,0x3300,0x0000}, // f
18+
{0x0380,0x07C6,0x0EE7,0x0C63,0x0C63,0x0C63,0x0C63,0x0EC7,0x07FE,0x03FC}, // g
19+
{0x3FFF,0x3FFF,0x01C0,0x0380,0x0700,0x0600,0x0700,0x0380,0x01FF,0x00FF}, // h
20+
{0x0000,0x0000,0x0180,0x0180,0x19FC,0x19FE,0x0007,0x0003,0x0000,0x0000}, // i
21+
{0x0000,0x0000,0x0003,0x0003,0x0603,0x0607,0x37FE,0x37FC,0x0000,0x0000}, // j
22+
{0x3FFF,0x3FFF,0x001C,0x0038,0x0070,0x00F8,0x01DC,0x038E,0x0707,0x0603}, // k
23+
{0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000}, // l
24+
{0x07FF,0x07FF,0x0300,0x0600,0x07FF,0x07FF,0x0600,0x0700,0x03FF,0x01FF}, // m
25+
{0x07FF,0x07FF,0x0300,0x0600,0x0600,0x0600,0x0600,0x0700,0x03FF,0x01FF}, // n
26+
{0x01FC,0x03FE,0x0707,0x0603,0x0603,0x0603,0x0603,0x0707,0x03FE,0x01FC}, // o
27+
{0x0FFF,0x0FFF,0x07F0,0x0E38,0x0C18,0x0C18,0x0C18,0x0E38,0x07F0,0x03E0}, // p
28+
{0x03E0,0x07F0,0x0E38,0x0C18,0x0C18,0x0C18,0x0E38,0x07F0,0x0FFF,0x0FFF}, // q
29+
{0x07FF,0x07FF,0x01C0,0x0380,0x0700,0x0600,0x0600,0x0700,0x0380,0x0180}, // r
30+
{0x018C,0x03CE,0x07C7,0x0663,0x0663,0x0673,0x0633,0x073F,0x039E,0x018C}, // s
31+
{0x0000,0x0000,0x0600,0x0600,0x3FFC,0x3FFE,0x0607,0x0603,0x0000,0x0000}, // t
32+
{0x07FC,0x07FE,0x0007,0x0003,0x0003,0x0003,0x0003,0x0007,0x07FE,0x07FC}, // u
33+
{0x07F0,0x07F8,0x001C,0x000E,0x0007,0x0007,0x000E,0x001C,0x07F8,0x07F0}, // v
34+
{0x07FC,0x07FE,0x0007,0x0003,0x007E,0x007E,0x0003,0x0007,0x07FE,0x07FC}, // w
35+
{0x0603,0x0707,0x038E,0x01DC,0x00F8,0x00F8,0x01DC,0x038E,0x0707,0x0603}, // x
36+
{0x0FC0,0x0FE0,0x0073,0x0033,0x0033,0x0073,0x00E3,0x03C7,0x0FFE,0x0FFC}, // y
37+
{0x0603,0x0607,0x060F,0x061F,0x063B,0x0673,0x06E3,0x07C3,0x0783,0x0703}, // z
38+
{0x0FFC,0x1FFE,0x3837,0x3073,0x30E3,0x31C3,0x3383,0x3B07,0x1FFE,0x0FFC}, // 0
39+
{0x0000,0x0000,0x0C03,0x1C03,0x3FFF,0x3FFF,0x0003,0x0003,0x0000,0x0000}, // 1
40+
{0x0C3F,0x1C7F,0x38E3,0x30C3,0x30C3,0x30C3,0x30C3,0x39C3,0x1F83,0x0F03}, // 2
41+
{0x0C0C,0x1C0E,0x3807,0x3003,0x30C3,0x30C3,0x30C3,0x39E7,0x1FFE,0x0F3C}, // 3
42+
{0x00F0,0x01F0,0x03B0,0x0730,0x0E30,0x1C30,0x3FFF,0x3FFF,0x0030,0x0030}, // 4
43+
{0x3F0C,0x3F0E,0x3307,0x3303,0x3303,0x3303,0x3303,0x3387,0x31FE,0x30FC}, // 5
44+
{0x0FFC,0x1FFE,0x38C7,0x30C3,0x30C3,0x30C3,0x30C3,0x38E7,0x1C7E,0x0C3C}, // 6
45+
{0x3000,0x3000,0x3000,0x3000,0x307F,0x30FF,0x31C0,0x3380,0x3F00,0x3E00}, // 7
46+
{0x0F3C,0x1FFE,0x39E7,0x30C3,0x30C3,0x30C3,0x30C3,0x39E7,0x1FFE,0x0F3C}, // 8
47+
{0x0F0C,0x1F8E,0x39C7,0x30C3,0x30C3,0x30C3,0x30C3,0x38C7,0x1FFE,0x0FFC}, // 9
48+
{0x1E0F,0x3F1F,0x3338,0x3F70,0x1EE0,0x01DE,0x03BF,0x0733,0x3E3F,0x3C1E}, // %
49+
{0x0C00,0x1C00,0x3800,0x3000,0x3033,0x3073,0x30E0,0x39C0,0x1F80,0x0F00}, // ?
50+
{0x0000,0x0000,0x0000,0x0000,0x07F3,0x07F3,0x0000,0x0000,0x0000,0x0000}, // !
51+
{0x0000,0x0000,0x0000,0x0000,0x0003,0x0003,0x0000,0x0000,0x0000,0x0000}, // .
52+
{0x0000,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x00C0,0x0000}, // -
53+
{0x0000,0x3FFF,0x3FFF,0x3003,0x3003,0x3003,0x3003,0x3FFF,0x3FFF,0x0000}, // unknown
54+
};
55+
56+
#endif

0 commit comments

Comments
 (0)