├── .gitignore ├── extras └── schema │ └── esp32-sn65hvd230-iso-a.png ├── library.properties ├── .vscode ├── settings.json ├── tasks.json └── c_cpp_properties.json ├── keywords.txt ├── license ├── src ├── Esp32RmtReader.h ├── esp32_arduino_rmt_van_rx.h ├── Esp32RmtReader.cpp └── esp32_arduino_rmt_van_rx.cpp ├── examples └── esp32_arduino_van_monitor │ └── esp32_arduino_van_monitor.ino └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/BROWSE.* 3 | .vs/ 4 | release/ 5 | __vm/ 6 | *.vcxproj.filters 7 | *.sln 8 | *.vcxproj -------------------------------------------------------------------------------- /extras/schema/esp32-sn65hvd230-iso-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morcibacsi/esp32_rmt_van_rx/HEAD/extras/schema/esp32-sn65hvd230-iso-a.png -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ESP32 RMT Peripheral VAN bus reader library 2 | version=2.0.2 3 | author=Peter Pinter 4 | maintainer=Peter Pinter 5 | sentence=ESP32 RMT Peripheral VAN bus reader library 6 | paragraph=It is intended to interface the automotive bus used in cars made by the PSA (Peugeot and Citroen) 7 | category=Communication 8 | url=https://github.com/morcibacsi/esp32_rmt_van_rx 9 | architectures=esp32 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stdio.h": "c", 4 | "esp_spi_flash.h": "c" 5 | }, 6 | "terminal.explorerKind": "external", 7 | //"terminal.integrated.shell.windows":"C:\\WINDOWS\\System32\\cmd.exe" 8 | "terminal.integrated.shell.windows": "C:/msys32/usr/bin/bash.exe", 9 | "terminal.integrated.shellArgs.windows": [ 10 | "--login", 11 | ], 12 | "terminal.integrated.env.windows": { 13 | "CHERE_INVOKING": "1", 14 | "MSYSTEM": "MINGW32", 15 | }, 16 | 17 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ESP32_RMT_VAN_RX KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | Start KEYWORD2 16 | ReceiveData KEYWORD2 17 | Stop KEYWORD2 18 | IsCrcOk KEYWORD2 19 | Crc15 KEYWORD2 20 | 21 | ####################################### 22 | # Constants (LITERAL1) 23 | ####################################### 24 | VAN_LINE_LEVEL LITERAL1 25 | VAN_NETWORK_TYPE LITERAL1 -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 haxplore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/Esp32RmtReader.h: -------------------------------------------------------------------------------- 1 | // Esp32RmtReader.h 2 | #pragma once 3 | 4 | #ifndef _Esp32RmtReader_h 5 | #define _Esp32RmtReader_h 6 | 7 | #include 8 | #include "driver/rmt.h" 9 | #include "driver/periph_ctrl.h" 10 | #include "soc/rmt_reg.h" 11 | 12 | /* 13 | This is a base class around the RMT peripheral of the ESP32. Can't be used directly, you need to create a derived class 14 | and implemement the virtual methods. 15 | */ 16 | class Esp32RmtReader 17 | { 18 | #define RMT_READER_MAX_DATA 255 19 | protected: 20 | uint16_t _idleTreshold; 21 | uint8_t _clkDiv; 22 | uint8_t _channel; 23 | uint8_t _memoryBlocks; 24 | uint8_t _rxPin; 25 | int8_t _ledPin; 26 | uint8_t _messageLength; 27 | uint8_t _message[RMT_READER_MAX_DATA]; 28 | 29 | Esp32RmtReader(uint8_t clkDiv, uint16_t idleTreshold, uint8_t channel, uint8_t rxPin, int8_t ledPin); 30 | void InitLed(); 31 | void SwitchLed(uint8_t state); 32 | 33 | /* 34 | It is called before the ProcessSignal is executed. You can initialize variables, prepare for incoming data etc... 35 | The derived class should implement it. 36 | */ 37 | virtual void BeforeProcessSignal() = 0; 38 | /* 39 | It is called after the ProcessSignal is executed. The derived class should implement it. 40 | */ 41 | virtual void AfterProcessSignal() = 0; 42 | // Used to convert the level and duration to real data. It is up to the derived class to implement the parsing logic. 43 | virtual void ProcessSignal(uint32_t level, uint32_t duration) = 0; 44 | public: 45 | // Start receiving RMT data 46 | int32_t Start(); 47 | // Stop receiving RMT data 48 | void Stop(); 49 | // This should be called regularly from a loop to get the parsed data from the RMT peripheral. 50 | void ReceiveData(uint8_t *messageLength, uint8_t message[]); 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/esp32_arduino_rmt_van_rx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _esp32_arduino_rmt_van_rx_h 4 | #define _esp32_arduino_rmt_van_rx_h 5 | 6 | #include "Esp32RmtReader.h" 7 | 8 | typedef enum { 9 | VAN_LINE_LEVEL_LOW = 0, 10 | VAN_LINE_LEVEL_HIGH = 1, 11 | } VAN_LINE_LEVEL; 12 | 13 | typedef enum { 14 | VAN_NETWORK_TYPE_BODY = 0, 15 | VAN_NETWORK_TYPE_COMFORT = 1, 16 | } VAN_NETWORK_TYPE; 17 | 18 | class ESP32_RMT_VAN_RX: public Esp32RmtReader 19 | { 20 | private: 21 | uint8_t _bitCounter = 0; 22 | uint8_t _tempByte = 0; 23 | uint8_t _mask = 1 << 7; 24 | uint8_t _timeSliceDivisor = 0; 25 | VAN_LINE_LEVEL _vanLineLevel = VAN_LINE_LEVEL_LOW; 26 | 27 | uint8_t RoundToNearest(uint8_t numToRound, uint8_t multiple); 28 | void BeforeProcessSignal() override; 29 | void AfterProcessSignal() override; 30 | void ProcessSignal(uint32_t level, uint32_t duration) override; 31 | 32 | public: 33 | ESP32_RMT_VAN_RX(uint8_t channel, uint8_t rxPin, int8_t ledPin, VAN_LINE_LEVEL vanLineLevel, VAN_NETWORK_TYPE vanNetworkType) : Esp32RmtReader(80, 80, channel, rxPin, ledPin) 34 | { 35 | // Longer messages doesn't fit in one memory block of the RMT peripheral 36 | _memoryBlocks = 2; 37 | _vanLineLevel = vanLineLevel; 38 | if(vanNetworkType == VAN_NETWORK_TYPE_COMFORT) 39 | { 40 | _timeSliceDivisor = 8; 41 | _idleTreshold = 80; // we consider the packet whole after this number of ticks of unchanged line state 42 | } 43 | else if(vanNetworkType == VAN_NETWORK_TYPE_BODY) 44 | { 45 | _timeSliceDivisor = 16; 46 | _idleTreshold = 160; // we consider the packet whole after this number of ticks of unchanged line state 47 | } 48 | } 49 | 50 | ~ESP32_RMT_VAN_RX(); 51 | 52 | // You can check the CRC of the received message with this function 53 | bool IsCrcOk(uint8_t vanMessage[], uint8_t vanMessageLength); 54 | 55 | // This function calculates the CRC of a message 56 | uint16_t Crc15(uint8_t data[], uint8_t lengthOfData); 57 | }; 58 | #endif 59 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build app", 8 | "command": "make", 9 | "type": "shell", 10 | "args": [ 11 | "-j8", 12 | "app" 13 | ], 14 | "presentation": { 15 | "reveal": "always", 16 | "echo": true 17 | }, 18 | "problemMatcher": { 19 | "owner": "cpp", 20 | "fileLocation": "absolute", 21 | "pattern": { 22 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", 23 | "file": 1, 24 | "line": 2, 25 | "column": 3, 26 | "severity": 4, 27 | "message": 5 28 | } 29 | }, 30 | "group": { 31 | "kind": "build", 32 | "isDefault": true 33 | } 34 | }, 35 | { 36 | "label": "clean app", 37 | "command": "idf.py", 38 | "type": "shell", 39 | "args": [ 40 | "clean" 41 | ], 42 | "presentation": { 43 | "reveal": "always" 44 | } 45 | }, 46 | { 47 | "label": "flash app", 48 | "command": "idf.py", 49 | "type": "shell", 50 | "args": [ 51 | "-p", 52 | "COM12", 53 | "flash" 54 | ], 55 | "presentation": { 56 | "reveal": "always" 57 | } 58 | }, 59 | { 60 | "label": "monitor", 61 | "type": "process", 62 | "windows": { 63 | "command": "", 64 | "args": [ 65 | "idf.py", 66 | "monitor" 67 | ] 68 | }, 69 | "presentation": { 70 | "reveal": "always" 71 | }, 72 | "problemMatcher": [] 73 | }, 74 | { 75 | "label": "menuconfig", 76 | "type": "shell", 77 | "windows": { 78 | "command": "", 79 | "args": [ 80 | "idf.py", 81 | "menuconfig" 82 | ] 83 | }, 84 | "presentation": { 85 | "reveal": "always" 86 | }, 87 | "problemMatcher": [] 88 | } 89 | ] 90 | } -------------------------------------------------------------------------------- /examples/esp32_arduino_van_monitor/esp32_arduino_van_monitor.ino: -------------------------------------------------------------------------------- 1 | /* Arduino version of the ESP32 RMT VAN bus receive example, 2 | * displaying the received VAN messages on the serial console 3 | * 4 | * The software is distributed under the MIT License 5 | * 6 | * Unless required by applicable law or agreed to in writing, this 7 | * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | * CONDITIONS OF ANY KIND, either express or implied. 9 | */ 10 | #include 11 | 12 | TaskHandle_t VANReadDataTask; 13 | 14 | ESP32_RMT_VAN_RX *VAN_RX; 15 | 16 | const uint8_t VAN_DATA_RX_RMT_CHANNEL = 0; 17 | const uint8_t VAN_DATA_RX_PIN = 21; 18 | const uint8_t VAN_DATA_RX_LED_INDICATOR_PIN = 2; 19 | 20 | uint8_t vanMessageLength; 21 | uint8_t vanMessage[34]; 22 | 23 | uint32_t lastMillis = 0; 24 | 25 | void VANReadDataTaskFunction(void * parameter) 26 | { 27 | VAN_RX = new ESP32_RMT_VAN_RX(VAN_DATA_RX_RMT_CHANNEL, VAN_DATA_RX_PIN, VAN_DATA_RX_LED_INDICATOR_PIN, VAN_LINE_LEVEL_HIGH, VAN_NETWORK_TYPE_COMFORT); 28 | //VAN_RX = new ESP32_RMT_VAN_RX(VAN_DATA_RX_RMT_CHANNEL, VAN_DATA_RX_PIN, VAN_DATA_RX_LED_INDICATOR_PIN, VAN_LINE_LEVEL_HIGH, VAN_NETWORK_TYPE_BODY); 29 | VAN_RX->Start(); 30 | 31 | for (;;) 32 | { 33 | VAN_RX->ReceiveData(&vanMessageLength, vanMessage); 34 | 35 | if (vanMessageLength > 0) 36 | { 37 | if(!VAN_RX->IsCrcOk(vanMessage, vanMessageLength)) 38 | { 39 | printf("CRC ERROR: "); 40 | } 41 | { 42 | for (size_t i = 0; i < vanMessageLength; i++) 43 | { 44 | if (i != vanMessageLength - 1) 45 | { 46 | printf("%02X ", vanMessage[i]); 47 | } 48 | else 49 | { 50 | printf("%02X", vanMessage[i]); 51 | } 52 | } 53 | printf("\n"); 54 | } 55 | } 56 | vTaskDelay(5 / portTICK_PERIOD_MS); 57 | } 58 | } 59 | 60 | void setup() 61 | { 62 | Serial.begin(500000); 63 | printf("ESP32 Arduino VAN bus monitor\n"); 64 | 65 | xTaskCreatePinnedToCore( 66 | VANReadDataTaskFunction, // Function to implement the task 67 | "VANReadDataTask", // Name of the task 68 | 20000, // Stack size in words 69 | NULL, // Task input parameter 70 | 1, // Priority of the task (higher the number, higher the priority) 71 | &VANReadDataTask, // Task handle. 72 | 0); // Core where the task should run 73 | } 74 | 75 | void loop() 76 | { 77 | vTaskDelay(50 / portTICK_PERIOD_MS); 78 | } 79 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ESP32 RMT peripheral Vehicle Area Network (VAN bus) reader 2 | 3 | Arduino [VAN bus][van_network] reader library utilizing ESP32 RMT peripheral. 4 | 5 | VAN bus is pretty similar to CAN bus. It was used in many cars (Peugeot, Citroen) made by PSA. 6 | 7 | ### ESP8266 support 8 | This library is built around the [RMT (Remote control) peripheral][rmt_peripheral] of the ESP32. Therefore **ESP8266 is NOT supported** by this library as it does not have the peripheral built in. However on these boards you can use this library: [PSA VAN bus reader for Arduino-ESP8266][van_reader_for_esp8266] 9 | 10 | ### Schematics 11 | 12 | ![schema](https://github.com/morcibacsi/esp32_rmt_van_rx/raw/master/extras/schema/esp32-sn65hvd230-iso-a.png) 13 | 14 | ### Arduino 15 | Copy the following files to your **documents\Arduino\libraries\esp32_arduino_rmt_van_rx** folder 16 | - esp32_arduino_rmt_van_rx.cpp 17 | - esp32_arduino_rmt_van_rx.h 18 | - Esp32RmtReader.cpp 19 | - Esp32RmtReader.h 20 | - keywords.txt 21 | - library.properties 22 | 23 | Check the **esp32_arduino_van_monitor** folder for an example 24 | 25 | ### Breaking change 26 | 27 | In version 2.0.0 the library was rewritten and ESP-IDF support was dropped in favor of simpler code in Arduino framework. The change also makes it possible to monitor the VAN_COMFORT and VAN_BODY bus simultaneously by creating two separate instances of the ```ESP32_RMT_VAN_RX``` class. The example was updated to reflect the change, so you can check that as well. 28 | 29 | #### Example code 30 | ```cpp 31 | // Instead of calling the Init function with the following parameters: 32 | VAN_RX.Init(VAN_DATA_RX_RMT_CHANNEL, VAN_DATA_RX_PIN, VAN_DATA_RX_LED_INDICATOR_PIN, VAN_LINE_LEVEL_HIGH, VAN_NETWORK_TYPE_COMFORT); 33 | //Receive() method was renamed to ReceiveData() 34 | VAN_RX.Receive(&vanMessageLength, vanMessage) 35 | 36 | // You need to pass the same parameters to the constructor like this: 37 | VAN_RX = new ESP32_RMT_VAN_RX(VAN_DATA_RX_RMT_CHANNEL, VAN_DATA_RX_PIN, VAN_DATA_RX_LED_INDICATOR_PIN, VAN_LINE_LEVEL_HIGH, VAN_NETWORK_TYPE_COMFORT); 38 | // And call the Start() method: 39 | VAN_RX->Start(); 40 | // Receive data from the bus 41 | VAN_RX->ReceiveData(&vanMessageLength, vanMessage); 42 | ``` 43 | 44 | ## See also 45 | - [VAN Analyzer for Saleae Logic Analyzer][van_analyzer] 46 | - [TSS463/461 library for reading and also safely writing the VAN bus][tss_46x library] 47 | - [VAN bus reader for STM32F103 (Blue Pill)][stm32_van_bus] 48 | 49 | [van_network]: https://en.wikipedia.org/wiki/Vehicle_Area_Network 50 | [van_analyzer]: https://github.com/morcibacsi/VanAnalyzer/ 51 | [rmt_peripheral]: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html 52 | [van_reader_for_esp8266]: https://github.com/0xCAFEDECAF/VanBus 53 | [tss_46x library]: https://github.com/morcibacsi/arduino_tss463_van 54 | [stm32_van_bus]: https://github.com/morcibacsi/stm32_arduino_van_bus 55 | -------------------------------------------------------------------------------- /src/Esp32RmtReader.cpp: -------------------------------------------------------------------------------- 1 | #include "Esp32RmtReader.h" 2 | #include 3 | #include 4 | 5 | Esp32RmtReader::Esp32RmtReader(uint8_t clkDiv, uint16_t idleTreshold, uint8_t channel, uint8_t rxPin, int8_t ledPin) 6 | { 7 | _clkDiv = clkDiv; 8 | _idleTreshold = idleTreshold; 9 | _channel = channel; 10 | _rxPin = rxPin; 11 | _ledPin = ledPin; 12 | _memoryBlocks = 1; 13 | _messageLength = 0; 14 | } 15 | 16 | void Esp32RmtReader::InitLed() 17 | { 18 | if (_ledPin > -1) 19 | { 20 | gpio_pad_select_gpio(_ledPin); 21 | gpio_set_direction((gpio_num_t)_ledPin, GPIO_MODE_OUTPUT); 22 | } 23 | } 24 | 25 | void Esp32RmtReader::SwitchLed(uint8_t state) 26 | { 27 | if (_ledPin > -1) 28 | { 29 | gpio_set_level((gpio_num_t)_ledPin, state); 30 | } 31 | } 32 | 33 | int32_t Esp32RmtReader::Start() 34 | { 35 | InitLed(); 36 | 37 | rmt_config_t rmt_rx; 38 | 39 | rmt_rx.rx_config.idle_threshold = _idleTreshold; // we consider the packet whole after this number of ticks of unchanged line state 40 | 41 | rmt_rx.channel = (rmt_channel_t)_channel; 42 | rmt_rx.gpio_num = (gpio_num_t)_rxPin; 43 | rmt_rx.clk_div = _clkDiv; //80 = 1 MHz, 1 us - we take samples every 1 microseconds 44 | rmt_rx.mem_block_num = _memoryBlocks; 45 | rmt_rx.rmt_mode = RMT_MODE_RX; 46 | rmt_rx.flags = 0; 47 | 48 | rmt_rx.rx_config.filter_en = false; 49 | rmt_rx.rx_config.filter_ticks_thresh = 0; 50 | 51 | rmt_config(&rmt_rx); 52 | rmt_driver_install(rmt_rx.channel, 1000, 0); 53 | 54 | // start receiving data 55 | esp_err_t result = rmt_rx_start((rmt_channel_t)_channel, true); 56 | 57 | return result; 58 | } 59 | 60 | void Esp32RmtReader::Stop() 61 | { 62 | rmt_driver_uninstall((rmt_channel_t)_channel); 63 | } 64 | 65 | void Esp32RmtReader::ReceiveData(uint8_t *messageLength, uint8_t message[]) 66 | { 67 | *messageLength = 0; 68 | _messageLength = 0; 69 | memset(_message, 0x00, RMT_READER_MAX_DATA*sizeof(*_message)); 70 | 71 | size_t i; 72 | size_t rx_size = 0; 73 | rmt_item32_t* items = NULL; 74 | 75 | // define ringbuffer handle 76 | RingbufHandle_t rb; 77 | 78 | // get the ring buffer handle 79 | esp_err_t result = rmt_get_ringbuf_handle((rmt_channel_t)_channel, &rb); 80 | 81 | if (result == ESP_OK) 82 | { 83 | // get items, if there are any 84 | items = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 8); 85 | if (items) 86 | { 87 | // turn on visible led 88 | SwitchLed(1); 89 | 90 | // call to virtual method which should be implemented in derived class 91 | BeforeProcessSignal(); 92 | 93 | for (i = 0; i < rx_size / 4; i++) 94 | { 95 | // call to virtual method which should be implemented in derived class 96 | ProcessSignal(items[i].level0, items[i].duration0); 97 | ProcessSignal(items[i].level1, items[i].duration1); 98 | } 99 | *messageLength = _messageLength; 100 | memcpy(message, _message, _messageLength); 101 | 102 | // call to virtual method which should be implemented in derived class 103 | AfterProcessSignal(); 104 | 105 | // turn off visible led 106 | SwitchLed(0); 107 | 108 | // free up data space 109 | vRingbufferReturnItem(rb, (void*) items); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/esp32_arduino_rmt_van_rx.cpp: -------------------------------------------------------------------------------- 1 | #include "esp32_arduino_rmt_van_rx.h" 2 | #include 3 | 4 | void ESP32_RMT_VAN_RX::BeforeProcessSignal() 5 | { 6 | _bitCounter = 0; 7 | _mask = 1 << 7; 8 | _tempByte = 0; 9 | _messageLength = 0; 10 | } 11 | 12 | void ESP32_RMT_VAN_RX::AfterProcessSignal() 13 | { 14 | } 15 | 16 | uint8_t ESP32_RMT_VAN_RX::RoundToNearest(uint8_t numToRound, uint8_t multiple) 17 | { 18 | if (multiple == 0) 19 | return numToRound; 20 | 21 | uint8_t remainder = numToRound % multiple; 22 | 23 | // If the remainder is greater than half of the multiple, then round up. Otherwise, round down. 24 | if (remainder > multiple / 2) 25 | return numToRound + multiple - remainder; 26 | else 27 | return numToRound - remainder; 28 | } 29 | 30 | void ESP32_RMT_VAN_RX::ProcessSignal(uint32_t level, uint32_t duration) 31 | { 32 | if (_vanLineLevel == VAN_LINE_LEVEL_LOW) 33 | { 34 | level = !level; 35 | } 36 | 37 | // on the bus the time slices are a little off from the multiple of the TS microseconds, so we round it to the nearest multiple of the TS before dividing 38 | uint8_t countOfTimeSlices = RoundToNearest(duration, _timeSliceDivisor) / _timeSliceDivisor; 39 | 40 | for (int i = 0; i < countOfTimeSlices; i++) 41 | { 42 | // every 5th bit is a manchester bit, we must skip them while we are building our byte 43 | bool isManchesterBit = (_bitCounter + 1) % 5 == 0; 44 | if (!isManchesterBit) 45 | { 46 | if (level == 1) 47 | { 48 | _tempByte |= _mask; 49 | } 50 | _mask = _mask >> 1; 51 | } 52 | else if (_bitCounter == 9) 53 | { 54 | // if we found the second manchester bit, then we have the full byte in the _tempByte variable, so we place it in _message array and we can start building the next byte 55 | _bitCounter = -1; 56 | _mask = 1 << 7; 57 | _message[_messageLength] = _tempByte; 58 | _messageLength++; 59 | _tempByte = 0; 60 | } 61 | 62 | _bitCounter++; 63 | } 64 | } 65 | 66 | uint16_t ESP32_RMT_VAN_RX::Crc15(uint8_t data[], uint8_t lengthOfData) 67 | { 68 | const uint8_t order = 15; 69 | const uint16_t polynom = 0xF9D; 70 | const uint16_t xorValue = 0x7FFF; 71 | const uint16_t mask = 0x7FFF; 72 | 73 | uint16_t crc = 0x7FFF; 74 | 75 | for (uint8_t i = 0; i < lengthOfData; i++) 76 | { 77 | uint8_t currentByte = data[i]; 78 | 79 | // rotate one data byte including crcmask 80 | for (uint8_t j = 0; j < 8; j++) 81 | { 82 | bool bit = (crc & (1 << (order - 1))) != 0; 83 | if ((currentByte & 0x80) != 0) 84 | { 85 | bit = !bit; 86 | } 87 | currentByte <<= 1; 88 | 89 | crc = ((crc << 1) & mask) ^ (-bit & polynom); 90 | } 91 | } 92 | 93 | // perform xor and multiply result by 2 to turn 15 bit result into 16 bit representation 94 | return (crc ^ xorValue) << 1; 95 | } 96 | 97 | bool ESP32_RMT_VAN_RX::IsCrcOk(uint8_t vanMessage[], uint8_t vanMessageLength) 98 | { 99 | // The VAN message must contain the SOF, IDEN bytes and the CRC bytes 100 | if (vanMessageLength < 4) 101 | { 102 | return false; 103 | } 104 | 105 | // Extract the CRC value from the message 106 | uint8_t crcByte1 = vanMessage[vanMessageLength - 2]; 107 | uint8_t crcByte2 = vanMessage[vanMessageLength - 1]; 108 | uint16_t crcValueInMessage = crcByte1 << 8 | crcByte2; 109 | 110 | // Create a new array containing the message without the SOF and CRC bytes 111 | uint8_t vanMessageWithIdWithoutCrc[32]; 112 | if(vanMessageLength - 3 <= 32){ 113 | memcpy(vanMessageWithIdWithoutCrc, vanMessage + 1, vanMessageLength - 3); 114 | 115 | // Calculate the CRC of the message with the ID but without the CRC bytes 116 | uint16_t calculatedCrc = Crc15(vanMessageWithIdWithoutCrc, vanMessageLength - 3); 117 | 118 | // Return true if the calculated CRC matches the CRC in the message 119 | return crcValueInMessage == calculatedCrc; 120 | } 121 | 122 | return false; 123 | } 124 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "ESP32-Win", 5 | "includePath": [ 6 | "${workspaceRoot}", 7 | "${workspaceRoot}/components", 8 | "${workspaceRoot}/build", 9 | "${workspaceRoot}/build/include", 10 | "${env:IDF_PATH}/components/bt/bluedroid/utils/include", 11 | "${env:IDF_PATH}/components/bt/bluedroid/stack/smp/include", 12 | "${env:IDF_PATH}/components/bt/bluedroid/stack/sdp/include", 13 | "${env:IDF_PATH}/components/bt/bluedroid/stack/rfcomm/include", 14 | "${env:IDF_PATH}/components/bt/bluedroid/stack/l2cap/include", 15 | "${env:IDF_PATH}/components/bt/bluedroid/stack/gatt/include", 16 | "${env:IDF_PATH}/components/bt/bluedroid/stack/gap/include", 17 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avrc/include", 18 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avdt/include", 19 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avct/include", 20 | "${env:IDF_PATH}/components/bt/bluedroid/stack/a2dp/include", 21 | "${env:IDF_PATH}/components/bt/bluedroid/stack/include", 22 | "${env:IDF_PATH}/components/bt/bluedroid/osi/include", 23 | "${env:IDF_PATH}/components/bt/bluedroid/hci/include", 24 | "${env:IDF_PATH}/components/bt/bluedroid/gki/include", 25 | "${env:IDF_PATH}/components/bt/bluedroid/external/sbc/encoder/include", 26 | "${env:IDF_PATH}/components/bt/bluedroid/external/sbc/decoder/include", 27 | "${env:IDF_PATH}/components/bt/bluedroid/device/include", 28 | "${env:IDF_PATH}/components/bt/bluedroid/btcore/include", 29 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/smp/include", 30 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/hid/include", 31 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/dis/include", 32 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/battery/include", 33 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/a2dp/include", 34 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/include", 35 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/esp/blufi/include", 36 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/esp/include", 37 | "${env:IDF_PATH}/components/bt/bluedroid/btc/include", 38 | "${env:IDF_PATH}/components/bt/bluedroid/bta/sys/include", 39 | "${env:IDF_PATH}/components/bt/bluedroid/bta/include", 40 | "${env:IDF_PATH}/components/bt/bluedroid/api/include", 41 | "${env:IDF_PATH}/components/bt/bluedroid/include", 42 | "${env:IDF_PATH}/components/aws_iot/include", 43 | "${env:IDF_PATH}/components/aws_iot/aws-iot-device-sdk-embedded-C/include", 44 | "${env:IDF_PATH}/components/app_trace/include", 45 | "${env:IDF_PATH}/components/app_update/include", 46 | "${env:IDF_PATH}/components/xtensa-debug-module/include", 47 | "${env:IDF_PATH}/components/bootloader_support/include", 48 | "${env:IDF_PATH}/components/bootloader_support/include_priv", 49 | "${env:IDF_PATH}/components/bt/include", 50 | "${env:IDF_PATH}/components/coap/port/include", 51 | "${env:IDF_PATH}/components/coap/port/include/coap", 52 | "${env:IDF_PATH}/components/coap/libcoap/include", 53 | "${env:IDF_PATH}/components/coap/libcoap/include/coap", 54 | "${env:IDF_PATH}/components/cxx/include", 55 | "${env:IDF_PATH}/components/driver/include", 56 | "${env:IDF_PATH}/components/driver/include/driver", 57 | "${env:IDF_PATH}/components/esp32/include", 58 | "${env:IDF_PATH}/components/ethernet/include", 59 | "${env:IDF_PATH}/components/expat/include/expat", 60 | "${env:IDF_PATH}/components/expat/port/include", 61 | "${env:IDF_PATH}/components/fatfs/src", 62 | "${env:IDF_PATH}/components/freertos/include", 63 | "${env:IDF_PATH}/components/heap/include", 64 | "${env:IDF_PATH}/components/jsmn/include", 65 | "${env:IDF_PATH}/components/json/include", 66 | "${env:IDF_PATH}/components/json/port/include", 67 | "${env:IDF_PATH}/components/json/cJSON", 68 | "${env:IDF_PATH}/components/libsodium/libsodium/src/libsodium/include", 69 | "${env:IDF_PATH}/components/libsodium/libsodium/src/libsodium/include/sodium", 70 | "${env:IDF_PATH}/components/log/include", 71 | "${env:IDF_PATH}/components/lwip/include/lwip", 72 | "${env:IDF_PATH}/components/lwip/include/lwip/port", 73 | "${env:IDF_PATH}/components/lwip/include/lwip/posix", 74 | "${env:IDF_PATH}/components/lwip/apps/ping", 75 | "${env:IDF_PATH}/components/lwip/include/lwip/apps", 76 | "${env:IDF_PATH}/components/lwip/include/lwip/apps/sntp", 77 | "${env:IDF_PATH}/components/lwip/include/lwip/lwip", 78 | "${env:IDF_PATH}/components/lwip/include/lwip/lwip/priv", 79 | "${env:IDF_PATH}/components/lwip/include/lwip/netif", 80 | "${env:IDF_PATH}/components/lwip/include/lwip/netif/ppp", 81 | "${env:IDF_PATH}/components/lwip/include/lwip/netif/ppp/polarssl", 82 | "${env:IDF_PATH}/components/lwip/include/lwip/port", 83 | "${env:IDF_PATH}/components/lwip/include/lwip/port/arch", 84 | "${env:IDF_PATH}/components/lwip/include/lwip/port/arpa", 85 | "${env:IDF_PATH}/components/lwip/include/lwip/port/netif", 86 | "${env:IDF_PATH}/components/lwip/include/lwip/port/netinet", 87 | "${env:IDF_PATH}/components/lwip/include/lwip/posix", 88 | "${env:IDF_PATH}/components/lwip/include/lwip/posix/sys", 89 | "${env:IDF_PATH}/components/mbedtls/port/include", 90 | "${env:IDF_PATH}/components/mbedtls/include", 91 | "${env:IDF_PATH}/components/mbedtls/port/include/mbedtls", 92 | "${env:IDF_PATH}/components/mdns/include", 93 | "${env:IDF_PATH}/components/micro-ecc/micro-ecc", 94 | "${env:IDF_PATH}/components/newlib/include", 95 | "${env:IDF_PATH}/components/newlib/include/sys", 96 | "${env:IDF_PATH}/components/newlib/platform_include", 97 | "${env:IDF_PATH}/components/nghttp/include", 98 | "${env:IDF_PATH}/components/nghttp/port/include", 99 | "${env:IDF_PATH}/components/nvs_flash/include", 100 | "${env:IDF_PATH}/components/openssl/include", 101 | "${env:IDF_PATH}/components/openssl/include/internal", 102 | "${env:IDF_PATH}/components/openssl/include/platform", 103 | "${env:IDF_PATH}/components/openssl/include/openssl", 104 | "${env:IDF_PATH}/components/pthread/include", 105 | "${env:IDF_PATH}/components/sdmmc/include", 106 | "${env:IDF_PATH}/components/spi_flash/include", 107 | "${env:IDF_PATH}/components/tcpip_adapter/include", 108 | "${env:IDF_PATH}/components/soc/esp32/include", 109 | "${env:IDF_PATH}/components/soc/include", 110 | "${env:IDF_PATH}/components/soc/esp32/include/soc", 111 | "${env:IDF_PATH}/components/spi_flash", 112 | "${env:IDF_PATH}/components/spiffs/include", 113 | "${env:IDF_PATH}/components/tcpip_adapter/include", 114 | "${env:IDF_PATH}/components/heap/include", 115 | "${env:IDF_PATH}/components/ulp/include", 116 | "${env:IDF_PATH}/components/ulp/include/esp32", 117 | "${env:IDF_PATH}/components/vfs/include", 118 | "${env:IDF_PATH}/components/vfs/include/sys", 119 | "${env:IDF_PATH}/components/wear_levelling/include", 120 | "${env:IDF_PATH}/components/wpa_supplicant/include", 121 | "${env:IDF_PATH}/components/wpa_supplicant/port/include", 122 | "${env:IDF_PATH}/components/wpa_supplicant/include/crypto", 123 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa", 124 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/eap_peer", 125 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/tls", 126 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/utils", 127 | "${env:IDF_PATH}/components/xtensa-debug-module/include", 128 | "C:/Program Files/Espressif/ESP-IDF Tools/toolchain/lib/gcc/xtensa-esp32-elf/5.2.0/include" 129 | ], 130 | "intelliSenseMode": "clang-x64", 131 | "browse": { 132 | "path": [ 133 | "${workspaceRoot}", 134 | "${workspaceRoot}/components", 135 | "${workspaceRoot}/build", 136 | "${workspaceRoot}/build/include", 137 | "${env:IDF_PATH}/components/bt/bluedroid/utils/include", 138 | "${env:IDF_PATH}/components/bt/bluedroid/stack/smp/include", 139 | "${env:IDF_PATH}/components/bt/bluedroid/stack/sdp/include", 140 | "${env:IDF_PATH}/components/bt/bluedroid/stack/rfcomm/include", 141 | "${env:IDF_PATH}/components/bt/bluedroid/stack/l2cap/include", 142 | "${env:IDF_PATH}/components/bt/bluedroid/stack/gatt/include", 143 | "${env:IDF_PATH}/components/bt/bluedroid/stack/gap/include", 144 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avrc/include", 145 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avdt/include", 146 | "${env:IDF_PATH}/components/bt/bluedroid/stack/avct/include", 147 | "${env:IDF_PATH}/components/bt/bluedroid/stack/a2dp/include", 148 | "${env:IDF_PATH}/components/bt/bluedroid/stack/include", 149 | "${env:IDF_PATH}/components/bt/bluedroid/osi/include", 150 | "${env:IDF_PATH}/components/bt/bluedroid/hci/include", 151 | "${env:IDF_PATH}/components/bt/bluedroid/gki/include", 152 | "${env:IDF_PATH}/components/bt/bluedroid/external/sbc/encoder/include", 153 | "${env:IDF_PATH}/components/bt/bluedroid/external/sbc/decoder/include", 154 | "${env:IDF_PATH}/components/bt/bluedroid/device/include", 155 | "${env:IDF_PATH}/components/bt/bluedroid/btcore/include", 156 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/smp/include", 157 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/hid/include", 158 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/dis/include", 159 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/battery/include", 160 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/a2dp/include", 161 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/std/include", 162 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/esp/blufi/include", 163 | "${env:IDF_PATH}/components/bt/bluedroid/btc/profile/esp/include", 164 | "${env:IDF_PATH}/components/bt/bluedroid/btc/include", 165 | "${env:IDF_PATH}/components/bt/bluedroid/bta/sys/include", 166 | "${env:IDF_PATH}/components/bt/bluedroid/bta/include", 167 | "${env:IDF_PATH}/components/bt/bluedroid/api/include", 168 | "${env:IDF_PATH}/components/bt/bluedroid/include", 169 | "${env:IDF_PATH}/components/aws_iot/include", 170 | "${env:IDF_PATH}/components/aws_iot/aws-iot-device-sdk-embedded-C/include", 171 | "${env:IDF_PATH}/components/app_trace/include", 172 | "${env:IDF_PATH}/components/app_update/include", 173 | "${env:IDF_PATH}/components/xtensa-debug-module/include", 174 | "${env:IDF_PATH}/components/bootloader_support/include", 175 | "${env:IDF_PATH}/components/bootloader_support/include_priv", 176 | "${env:IDF_PATH}/components/bt/include", 177 | "${env:IDF_PATH}/components/coap/port/include", 178 | "${env:IDF_PATH}/components/coap/port/include/coap", 179 | "${env:IDF_PATH}/components/coap/libcoap/include", 180 | "${env:IDF_PATH}/components/coap/libcoap/include/coap", 181 | "${env:IDF_PATH}/components/cxx/include", 182 | "${env:IDF_PATH}/components/driver/include", 183 | "${env:IDF_PATH}/components/driver/include/driver", 184 | "${env:IDF_PATH}/components/esp32/include", 185 | "${env:IDF_PATH}/components/ethernet/include", 186 | "${env:IDF_PATH}/components/expat/include/expat", 187 | "${env:IDF_PATH}/components/expat/port/include", 188 | "${env:IDF_PATH}/components/fatfs/src", 189 | "${env:IDF_PATH}/components/freertos/include", 190 | "${env:IDF_PATH}/components/heap/include", 191 | "${env:IDF_PATH}/components/jsmn/include", 192 | "${env:IDF_PATH}/components/json/include", 193 | "${env:IDF_PATH}/components/json/port/include", 194 | "${env:IDF_PATH}/components/json/cJSON", 195 | "${env:IDF_PATH}/components/libsodium/libsodium/src/libsodium/include", 196 | "${env:IDF_PATH}/components/libsodium/libsodium/src/libsodium/include/sodium", 197 | "${env:IDF_PATH}/components/log/include", 198 | "${env:IDF_PATH}/components/lwip/include/lwip", 199 | "${env:IDF_PATH}/components/lwip/include/lwip/port", 200 | "${env:IDF_PATH}/components/lwip/include/lwip/posix", 201 | "${env:IDF_PATH}/components/lwip/apps/ping", 202 | "${env:IDF_PATH}/components/lwip/include/lwip/apps", 203 | "${env:IDF_PATH}/components/lwip/include/lwip/apps/sntp", 204 | "${env:IDF_PATH}/components/lwip/include/lwip/lwip", 205 | "${env:IDF_PATH}/components/lwip/include/lwip/lwip/priv", 206 | "${env:IDF_PATH}/components/lwip/include/lwip/netif", 207 | "${env:IDF_PATH}/components/lwip/include/lwip/netif/ppp", 208 | "${env:IDF_PATH}/components/lwip/include/lwip/netif/ppp/polarssl", 209 | "${env:IDF_PATH}/components/lwip/include/lwip/port", 210 | "${env:IDF_PATH}/components/lwip/include/lwip/port/arch", 211 | "${env:IDF_PATH}/components/lwip/include/lwip/port/arpa", 212 | "${env:IDF_PATH}/components/lwip/include/lwip/port/netif", 213 | "${env:IDF_PATH}/components/lwip/include/lwip/port/netinet", 214 | "${env:IDF_PATH}/components/lwip/include/lwip/posix", 215 | "${env:IDF_PATH}/components/lwip/include/lwip/posix/sys", 216 | "${env:IDF_PATH}/components/mbedtls/port/include", 217 | "${env:IDF_PATH}/components/mbedtls/include", 218 | "${env:IDF_PATH}/components/mbedtls/port/include/mbedtls", 219 | "${env:IDF_PATH}/components/mdns/include", 220 | "${env:IDF_PATH}/components/micro-ecc/micro-ecc", 221 | "${env:IDF_PATH}/components/newlib/include", 222 | "${env:IDF_PATH}/components/newlib/include/sys", 223 | "${env:IDF_PATH}/components/newlib/platform_include", 224 | "${env:IDF_PATH}/components/nghttp/include", 225 | "${env:IDF_PATH}/components/nghttp/port/include", 226 | "${env:IDF_PATH}/components/nvs_flash/include", 227 | "${env:IDF_PATH}/components/openssl/include", 228 | "${env:IDF_PATH}/components/openssl/include/internal", 229 | "${env:IDF_PATH}/components/openssl/include/platform", 230 | "${env:IDF_PATH}/components/openssl/include/openssl", 231 | "${env:IDF_PATH}/components/pthread/include", 232 | "${env:IDF_PATH}/components/sdmmc/include", 233 | "${env:IDF_PATH}/components/spi_flash/include", 234 | "${env:IDF_PATH}/components/tcpip_adapter/include", 235 | "${env:IDF_PATH}/components/soc/esp32/include", 236 | "${env:IDF_PATH}/components/soc/include", 237 | "${env:IDF_PATH}/components/soc/esp32/include/soc", 238 | "${env:IDF_PATH}/components/spi_flash", 239 | "${env:IDF_PATH}/components/spiffs/include", 240 | "${env:IDF_PATH}/components/tcpip_adapter/include", 241 | "${env:IDF_PATH}/components/heap/include", 242 | "${env:IDF_PATH}/components/ulp/include", 243 | "${env:IDF_PATH}/components/ulp/include/esp32", 244 | "${env:IDF_PATH}/components/vfs/include", 245 | "${env:IDF_PATH}/components/vfs/include/sys", 246 | "${env:IDF_PATH}/components/wear_levelling/include", 247 | "${env:IDF_PATH}/components/wpa_supplicant/include", 248 | "${env:IDF_PATH}/components/wpa_supplicant/port/include", 249 | "${env:IDF_PATH}/components/wpa_supplicant/include/crypto", 250 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa", 251 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/eap_peer", 252 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/tls", 253 | "${env:IDF_PATH}/components/wpa_supplicant/include/wpa2/utils", 254 | "${env:IDF_PATH}/components/xtensa-debug-module/include", 255 | "C:/Program Files/Espressif/ESP-IDF Tools/toolchain/lib/gcc/xtensa-esp32-elf/5.2.0/include" 256 | 257 | ], 258 | "limitSymbolsToIncludedHeaders": true, 259 | "databaseFilename": "${workspaceRoot}/.vscode/browse.vc.db" 260 | }, 261 | "cStandard": "c11", 262 | "cppStandard": "c++17" 263 | } 264 | ], 265 | "version": 4 266 | } --------------------------------------------------------------------------------