This commit is contained in:
Matthew Kennedy 2020-09-19 16:50:55 -07:00
parent 746bcefef7
commit 72c2c271fb
4 changed files with 147 additions and 0 deletions

32
firmware/can.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "can.h"
#include "hal.h"
#include "can_helper.h"
static const CANConfig canConfig500 =
{
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
CAN_BTR_SJW(0) | CAN_BTR_BRP(5) | CAN_BTR_TS1(12) | CAN_BTR_TS2(1),
};
void InitCan()
{
canStart(&CAND1, &canConfig500);
CanTxMessage::setDevice(CAND1);
}
struct StandardDataFrame
{
uint16_t lambda;
uint16_t measuredResistance;
uint8_t pad[4];
};
void SendCanData(float lambda, uint16_t measuredResistance)
{
CanTxTyped<StandardDataFrame> frame(0x130);
frame.get().lambda = lambda / 1000.0f;
frame.get().measuredResistance = measuredResistance;
}

6
firmware/can.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <cstdint>
void InitCan();
void SendCanData(float lambda, uint16_t measuredResistance);

28
firmware/can_helper.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "can_helper.h"
#include <cstring>
/*static*/ CANDriver* CanTxMessage::s_device = nullptr;
/*static*/ void CanTxMessage::setDevice(CANDriver& device) {
s_device = &device;
}
CanTxMessage::CanTxMessage(uint32_t eid, uint8_t dlc) {
m_frame.IDE = CAN_IDE_STD;
m_frame.EID = eid;
m_frame.RTR = CAN_RTR_DATA;
m_frame.DLC = dlc;
memset(m_frame.data8, 0, sizeof(m_frame.data8));
}
CanTxMessage::~CanTxMessage() {
auto device = s_device;
// 100 ms timeout
canTransmit(device, CAN_ANY_MAILBOX, &m_frame, TIME_MS2I(100));
}
uint8_t& CanTxMessage::operator[](size_t index) {
return m_frame.data8[index];
}

81
firmware/can_helper.h Normal file
View File

@ -0,0 +1,81 @@
#pragma once
#include <cstdint>
#include <cstddef>
#include "hal.h"
/**
* Represent a message to be transmitted over CAN.
*
* Usage:
* * Create an instance of CanTxMessage
* * Set any data you'd like to transmit either using the subscript operator to directly access bytes, or any of the helper functions.
* * Upon destruction, the message is transmitted.
*/
class CanTxMessage
{
public:
/**
* Create a new CAN message, with the specified extended ID.
*/
explicit CanTxMessage(uint32_t eid, uint8_t dlc = 8);
/**
* Destruction of an instance of CanTxMessage will transmit the message over the wire.
*/
~CanTxMessage();
/**
* Configures the device for all messages to transmit from.
*/
static void setDevice(CANDriver& device);
/**
* @brief Read & write the raw underlying 8-byte buffer.
*/
uint8_t& operator[](size_t);
protected:
CANTxFrame m_frame;
private:
static CANDriver* s_device;
};
/**
* A CAN message based on a type, removing the need for manually flipping bits/bytes.
*/
template <typename TData>
class CanTxTyped final : public CanTxMessage
{
static_assert(sizeof(TData) == sizeof(CANTxFrame::data8));
public:
explicit CanTxTyped(uint32_t eid) : CanTxMessage(eid) { }
/**
* Access members of the templated type.
*
* So you can do:
* CanTxTyped<MyType> d;
* d->memberOfMyType = 23;
*/
TData* operator->()
{
return reinterpret_cast<TData*>(&m_frame.data8);
}
TData& get()
{
return *reinterpret_cast<TData*>(&m_frame.data8);
}
};
template <typename TData>
void transmitStruct(uint32_t eid)
{
CanTxTyped<TData> frame(eid);
// Destruction of an instance of CanTxMessage will transmit the message over the wire.
// see CanTxMessage::~CanTxMessage()
populateFrame(frame.get());
}