OpenDTU-old/src/BatteryCanReceiver.cpp
Andreas Böhm 6a3f90ff95
Feature: add support for Pytes batteries using CAN (#1088)
Co-authored-by: Bernhard Kirchen <schlimmchen@posteo.net>
2024-07-10 21:01:49 +02:00

176 lines
5.3 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
#include "BatteryCanReceiver.h"
#include "MessageOutput.h"
#include "PinMapping.h"
#include <driver/twai.h>
bool BatteryCanReceiver::init(bool verboseLogging, char const* providerName)
{
_verboseLogging = verboseLogging;
_providerName = providerName;
MessageOutput.printf("[%s] Initialize interface...\r\n",
_providerName);
const PinMapping_t& pin = PinMapping.get();
MessageOutput.printf("[%s] Interface rx = %d, tx = %d\r\n",
_providerName, pin.battery_rx, pin.battery_tx);
if (pin.battery_rx < 0 || pin.battery_tx < 0) {
MessageOutput.printf("[%s] Invalid pin config\r\n",
_providerName);
return false;
}
auto tx = static_cast<gpio_num_t>(pin.battery_tx);
auto rx = static_cast<gpio_num_t>(pin.battery_rx);
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(tx, rx, TWAI_MODE_NORMAL);
// Initialize configuration structures using macro initializers
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// Install TWAI driver
esp_err_t twaiLastResult = twai_driver_install(&g_config, &t_config, &f_config);
switch (twaiLastResult) {
case ESP_OK:
MessageOutput.printf("[%s] Twai driver installed\r\n",
_providerName);
break;
case ESP_ERR_INVALID_ARG:
MessageOutput.printf("[%s] Twai driver install - invalid arg\r\n",
_providerName);
return false;
break;
case ESP_ERR_NO_MEM:
MessageOutput.printf("[%s] Twai driver install - no memory\r\n",
_providerName);
return false;
break;
case ESP_ERR_INVALID_STATE:
MessageOutput.printf("[%s] Twai driver install - invalid state\r\n",
_providerName);
return false;
break;
}
// Start TWAI driver
twaiLastResult = twai_start();
switch (twaiLastResult) {
case ESP_OK:
MessageOutput.printf("[%s] Twai driver started\r\n",
_providerName);
break;
case ESP_ERR_INVALID_STATE:
MessageOutput.printf("[%s] Twai driver start - invalid state\r\n",
_providerName);
return false;
break;
}
return true;
}
void BatteryCanReceiver::deinit()
{
// Stop TWAI driver
esp_err_t twaiLastResult = twai_stop();
switch (twaiLastResult) {
case ESP_OK:
MessageOutput.printf("[%s] Twai driver stopped\r\n",
_providerName);
break;
case ESP_ERR_INVALID_STATE:
MessageOutput.printf("[%s] Twai driver stop - invalid state\r\n",
_providerName);
break;
}
// Uninstall TWAI driver
twaiLastResult = twai_driver_uninstall();
switch (twaiLastResult) {
case ESP_OK:
MessageOutput.printf("[%s] Twai driver uninstalled\r\n",
_providerName);
break;
case ESP_ERR_INVALID_STATE:
MessageOutput.printf("[%s] Twai driver uninstall - invalid state\r\n",
_providerName);
break;
}
}
void BatteryCanReceiver::loop()
{
// Check for messages. twai_receive is blocking when there is no data so we return if there are no frames in the buffer
twai_status_info_t status_info;
esp_err_t twaiLastResult = twai_get_status_info(&status_info);
if (twaiLastResult != ESP_OK) {
switch (twaiLastResult) {
case ESP_ERR_INVALID_ARG:
MessageOutput.printf("[%s] Twai driver get status - invalid arg\r\n",
_providerName);
break;
case ESP_ERR_INVALID_STATE:
MessageOutput.printf("[%s] Twai driver get status - invalid state\r\n",
_providerName);
break;
}
return;
}
if (status_info.msgs_to_rx == 0) {
return;
}
// Wait for message to be received, function is blocking
twai_message_t rx_message;
if (twai_receive(&rx_message, pdMS_TO_TICKS(100)) != ESP_OK) {
MessageOutput.printf("[%s] Failed to receive message",
_providerName);
return;
}
if (_verboseLogging) {
MessageOutput.printf("[%s] Received CAN message: 0x%04X -",
_providerName, rx_message.identifier);
for (int i = 0; i < rx_message.data_length_code; i++) {
MessageOutput.printf(" %02X", rx_message.data[i]);
}
MessageOutput.printf("\r\n");
}
onMessage(rx_message);
}
uint8_t BatteryCanReceiver::readUnsignedInt8(uint8_t *data)
{
return data[0];
}
uint16_t BatteryCanReceiver::readUnsignedInt16(uint8_t *data)
{
return (data[1] << 8) | data[0];
}
int16_t BatteryCanReceiver::readSignedInt16(uint8_t *data)
{
return this->readUnsignedInt16(data);
}
uint32_t BatteryCanReceiver::readUnsignedInt32(uint8_t *data)
{
return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0];
}
float BatteryCanReceiver::scaleValue(int16_t value, float factor)
{
return value * factor;
}
bool BatteryCanReceiver::getBit(uint8_t value, uint8_t bit)
{
return (value & (1 << bit)) >> bit;
}