-
-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NTCAN hardware layer #198
Draft
Y-Less
wants to merge
3
commits into
Open-Agriculture:main
Choose a base branch
from
Y-Less:ntcan
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
NTCAN hardware layer #198
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
64 changes: 64 additions & 0 deletions
64
hardware_integration/include/isobus/hardware_integration/ntcan_fifo_plugin.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
//================================================================================================ | ||
/// @file ntcan_fifo_plugin.hpp | ||
/// | ||
/// @brief An interface for using a ESD NTCAN FIFO driver. | ||
/// @attention Use of the NTCAN driver is governed in part by their license, and requires you | ||
/// to install their driver first, which in-turn requires you to agree to their terms and conditions. | ||
/// @author Alex "Y_Less" Cole | ||
/// | ||
/// @copyright 2023 Alex "Y_Less" Cole | ||
//================================================================================================ | ||
#ifndef NTCAN_FIFO_PLUGIN_HPP | ||
#define NTCAN_FIFO_PLUGIN_HPP | ||
|
||
#include <string> | ||
|
||
#include <NTCAN.h> | ||
#include "isobus/hardware_integration/can_hardware_plugin.hpp" | ||
#include "isobus/isobus/can_frame.hpp" | ||
#include "isobus/isobus/can_hardware_abstraction.hpp" | ||
|
||
//================================================================================================ | ||
/// @class NTCANPlugin | ||
/// | ||
/// @brief A CAN Driver for ESD NTCAN FIFO Devices | ||
//================================================================================================ | ||
class NTCANFIFOPlugin : public CANHardwarePlugin | ||
{ | ||
public: | ||
/// @brief Constructor for the ESD NTCAN FIFO CAN driver | ||
/// @param[in] channel The logical net number assigned to the physical CAN port to use. | ||
explicit NTCANFIFOPlugin(int channel); | ||
|
||
/// @brief The destructor for NTCANFIFOPlugin | ||
virtual ~NTCANFIFOPlugin() = default; | ||
|
||
/// @brief Returns if the connection with the hardware is valid | ||
/// @returns `true` if connected, `false` if not connected | ||
bool get_is_valid() const override; | ||
|
||
/// @brief Closes the connection to the hardware | ||
void close() override; | ||
|
||
/// @brief Connects to the hardware you specified in the constructor's channel argument | ||
void open() override; | ||
|
||
/// @brief Returns a frame from the hardware (synchronous), or `false` if no frame can be read. | ||
/// @param[in, out] canFrame The CAN frame that was read | ||
/// @returns `true` if a CAN frame was read, otherwise `false` | ||
bool read_frame(isobus::HardwareInterfaceCANFrame &canFrame) override; | ||
|
||
/// @brief Writes a frame to the bus (synchronous) | ||
/// @param[in] canFrame The frame to write to the bus | ||
/// @returns `true` if the frame was written, otherwise `false` | ||
bool write_frame(const isobus::HardwareInterfaceCANFrame &canFrame) override; | ||
|
||
private: | ||
int net; | ||
std::uint64_t timestampFreq; | ||
std::uint64_t timestampOff; | ||
NTCAN_HANDLE handle; ///< The handle as defined in the NTCAN FIFO driver API | ||
NTCAN_RESULT openResult; ///< Stores the result of the call to begin CAN communication. Used for is_valid check later. | ||
}; | ||
|
||
#endif // NTCAN_FIFO_PLUGIN_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
//================================================================================================ | ||
/// @file ntcan_fifo_plugin.cpp | ||
/// | ||
/// @brief An interface for using a ESD NTCAN FIFO driver. | ||
/// @attention Use of the NTCAN driver is governed in part by their license, and requires you | ||
/// to install their driver first, which in-turn requires you to agree to their terms and conditions. | ||
/// @author Alex "Y_Less" Cole | ||
/// | ||
/// @copyright 2023 Alex "Y_Less" Cole | ||
//================================================================================================ | ||
|
||
#include "isobus/hardware_integration/ntcan_fifo_plugin.hpp" | ||
#include "isobus/isobus/can_stack_logger.hpp" | ||
|
||
#include <thread> | ||
#include <chrono> | ||
|
||
NTCANFIFOPlugin::NTCANFIFOPlugin(int channel) : | ||
net(channel), | ||
timestampFreq(1), | ||
timestampOff(0), | ||
handle(0), | ||
openResult(NTCAN_SUCCESS) | ||
{ | ||
} | ||
|
||
bool NTCANFIFOPlugin::get_is_valid() const | ||
{ | ||
return (NTCAN_SUCCESS == openResult); | ||
} | ||
|
||
void NTCANFIFOPlugin::close() | ||
{ | ||
canClose(handle); | ||
} | ||
|
||
void NTCANFIFOPlugin::open() | ||
{ | ||
{ | ||
std::uint32_t mode = 0; | ||
std::int32_t txQueueSize = 8; | ||
std::int32_t rxQueueSize = 8; | ||
std::int32_t txTimeOut = 100; | ||
std::int32_t rxTimeOut = 1000; | ||
|
||
openResult = canOpen(net, mode, txQueueSize, rxQueueSize, txTimeOut, rxTimeOut, &handle); | ||
} | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
CAN_IF_STATUS status {0}; | ||
|
||
openResult = canSetBaudrate(handle, NTCAN_BAUD_250); | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
openResult = canStatus(handle, &status); | ||
} | ||
|
||
if (NTCAN_FEATURE_TIMESTAMP == (status.features & NTCAN_FEATURE_TIMESTAMP)) | ||
{ | ||
std::uint64_t timestamp = 0; | ||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
openResult = canIoctl(handle, NTCAN_IOCTL_GET_TIMESTAMP_FREQ, ×tampFreq); | ||
} | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
openResult = canIoctl(handle, NTCAN_IOCTL_GET_TIMESTAMP, ×tamp); | ||
} | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
auto now = std::chrono::system_clock::now(); | ||
auto unix = now.time_since_epoch(); | ||
long long millis = std::chrono::duration_cast<std::chrono::microseconds>(unix).count(); | ||
timestampOff = millis - timestamp; | ||
} | ||
} | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
std::int32_t ids = (1 << 11); | ||
openResult = canIdRegionAdd(handle, 0, &ids); | ||
if (NTCAN_SUCCESS == openResult && ids != (1 << 11)) | ||
{ | ||
openResult = NTCAN_INSUFFICIENT_RESOURCES; | ||
} | ||
} | ||
|
||
if (NTCAN_SUCCESS == openResult) | ||
{ | ||
std::int32_t ids = (1 << 29); | ||
// Address 0, with the wide address flag. | ||
openResult = canIdRegionAdd(handle, 0 | NTCAN_20B_BASE, &ids); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 0 | something is always something. Do you need the 0? |
||
if (NTCAN_SUCCESS == openResult && ids != (1 << 29)) | ||
{ | ||
openResult = NTCAN_INSUFFICIENT_RESOURCES; | ||
} | ||
} | ||
|
||
if (NTCAN_SUCCESS != openResult) | ||
{ | ||
isobus::CANStackLogger::CAN_stack_log(isobus::CANStackLogger::LoggingLevel::Critical, "[NTCAN]: Error trying to connect to NTCAN driver"); | ||
canClose(handle); | ||
} | ||
} | ||
else | ||
{ | ||
isobus::CANStackLogger::CAN_stack_log(isobus::CANStackLogger::LoggingLevel::Critical, "[NTCAN]: Error trying to connect to NTCAN driver"); | ||
} | ||
} | ||
|
||
bool NTCANFIFOPlugin::read_frame(isobus::HardwareInterfaceCANFrame &canFrame) | ||
{ | ||
NTCAN_RESULT result; | ||
CMSG_T msgCanMessage {0}; | ||
bool retVal = false; | ||
std::int32_t count = 1; | ||
|
||
result = canReadT(handle, &msgCanMessage, &count, nullptr); | ||
|
||
if (NTCAN_SUCCESS == result && 1 == count) | ||
{ | ||
canFrame.dataLength = msgCanMessage.len; | ||
memcpy(canFrame.data, msgCanMessage.data, msgCanMessage.len); | ||
canFrame.identifier = (msgCanMessage.id & ((1 << 29) - 1)); | ||
canFrame.isExtendedFrame = (NTCAN_20B_BASE == (msgCanMessage.id & NTCAN_20B_BASE)); | ||
canFrame.timestamp_us = msgCanMessage.timestamp * 1000000 / timestampFreq + timestampOff; | ||
retVal = true; | ||
} | ||
else | ||
{ | ||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||
} | ||
return retVal; | ||
} | ||
|
||
bool NTCANFIFOPlugin::write_frame(const isobus::HardwareInterfaceCANFrame &canFrame) | ||
{ | ||
NTCAN_RESULT result; | ||
CMSG_T msgCanMessage {0}; | ||
std::int32_t count = 1; | ||
|
||
msgCanMessage.id = canFrame.isExtendedFrame ? (canFrame.identifier | NTCAN_20B_BASE) : canFrame.identifier; | ||
msgCanMessage.len = canFrame.dataLength; | ||
memcpy(msgCanMessage.data, canFrame.data, canFrame.dataLength); | ||
|
||
result = canWriteT(handle, &msgCanMessage, &count, nullptr); | ||
|
||
return (NTCAN_SUCCESS == result && 1 == count); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going forward the best practice is to put initializers in the class header instead of here, so like:
std::uint64_t timestampOff = 0;
in the header file instead of in the class initializer list.