-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ba55be6
Showing
7 changed files
with
1,519 additions
and
0 deletions.
There are no files selected for viewing
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,34 @@ | ||
{ | ||
"configurations": [ | ||
{ | ||
"name": "Win32", | ||
"includePath": [ | ||
"${workspaceFolder}/**", | ||
"C:/arduino-1.8.10/hardware/arduino/avr/cores/arduino", | ||
"C:/arduino-1.8.10/hardware/arduino/avr/variants/standard", | ||
"Z:/Documents/Arduino/libraries/MCP_CAN_lib", | ||
"C:/arduino-1.8.10/libraries/Servo/src", | ||
"C:/arduino-1.8.10/hardware/arduino/avr/libraries/SPI/src", | ||
"C:/arduino-1.8.10/hardware/arduino/avr/libraries/EEPROM/src" | ||
], | ||
"defines": [ | ||
"F_CPU=16000000L", | ||
"ARDUINO=10810", | ||
"ARDUINO_AVR_UNO", | ||
"ARDUINO_ARCH_AVR" | ||
], | ||
"windowsSdkVersion": "10.0.18362.0", | ||
"compilerPath": "C:/arduino-1.8.10/hardware/tools/avr/bin/avr-gcc.exe", | ||
"cStandard": "c11", | ||
"cppStandard": "c++11", | ||
"intelliSenseMode": "gcc-x86", | ||
"compilerArgs": [ | ||
"-mmcu=atmega328p" | ||
], | ||
"forcedInclude": [ | ||
"C:/arduino-1.8.10/hardware/arduino/avr/cores/arduino/Arduino.h" | ||
] | ||
} | ||
], | ||
"version": 4 | ||
} |
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,42 @@ | ||
|
||
#include "mcp2515.h" | ||
|
||
#include "frc/CAN.h" | ||
|
||
#define CAN_CS 10 | ||
#define CAN_INTERRUPT 2 | ||
|
||
MCP2515 mcp2515{CAN_CS}; | ||
frc::CAN frcCANDevice{1}; | ||
|
||
void CANCallback(frc::CAN* can, int apiId) { | ||
|
||
} | ||
|
||
|
||
void setup() { | ||
mcp2515.reset(); | ||
mcp2515.setBitrate(CAN_1000KBPS); | ||
mcp2515.setNormalMode(); | ||
pinMode(CAN_INTERRUPT, OUTPUT); | ||
frc::CAN::SetCANImpl(&mcp2515, CAN_INTERRUPT, CANCallback); | ||
} | ||
|
||
unsigned long long lastSend20Ms = 0; | ||
int count = 0; | ||
|
||
void loop() { | ||
frc::CAN::Update(); | ||
|
||
uint8_t data[8]; | ||
|
||
auto now = millis(); | ||
if (now - lastSend20Ms > 20) { | ||
// 20 ms periodic | ||
memset(data, 0, 8); | ||
data[0] = count; | ||
count++; | ||
|
||
frcCANDevice.WritePacket(data, 1, 1); | ||
} | ||
} |
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,45 @@ | ||
#ifndef CAN_H_ | ||
#define CAN_H_ | ||
|
||
#include <stdint.h> | ||
|
||
|
||
typedef unsigned char __u8; | ||
typedef unsigned short __u16; | ||
typedef unsigned long __u32; | ||
|
||
|
||
/* special address description flags for the CAN_ID */ | ||
#define CAN_EFF_FLAG 0x80000000UL /* EFF/SFF is set in the MSB */ | ||
#define CAN_RTR_FLAG 0x40000000UL /* remote transmission request */ | ||
#define CAN_ERR_FLAG 0x20000000UL /* error message frame */ | ||
|
||
/* valid bits in CAN ID for frame formats */ | ||
#define CAN_SFF_MASK 0x000007FFUL /* standard frame format (SFF) */ | ||
#define CAN_EFF_MASK 0x1FFFFFFFUL /* extended frame format (EFF) */ | ||
#define CAN_ERR_MASK 0x1FFFFFFFUL /* omit EFF, RTR, ERR flags */ | ||
|
||
/* | ||
* Controller Area Network Identifier structure | ||
* | ||
* bit 0-28 : CAN identifier (11/29 bit) | ||
* bit 29 : error message frame flag (0 = data frame, 1 = error message) | ||
* bit 30 : remote transmission request flag (1 = rtr frame) | ||
* bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) | ||
*/ | ||
typedef __u32 canid_t; | ||
|
||
#define CAN_SFF_ID_BITS 11 | ||
#define CAN_EFF_ID_BITS 29 | ||
|
||
/* CAN payload length and DLC definitions according to ISO 11898-1 */ | ||
#define CAN_MAX_DLC 8 | ||
#define CAN_MAX_DLEN 8 | ||
|
||
struct can_frame { | ||
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ | ||
__u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */ | ||
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); | ||
}; | ||
|
||
#endif /* CAN_H_ */ |
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,73 @@ | ||
#include "frc/CAN.h" | ||
#include "mcp2515.h" | ||
|
||
using namespace frc; | ||
|
||
MCP2515* CAN::m_mcp2515 = nullptr; | ||
uint8_t CAN::m_interruptPin = 0; | ||
CAN::MessageCallback CAN::m_messageCb = nullptr; | ||
CAN* CAN::m_canClasses[16]; | ||
uint8_t CAN::m_canCount = 0; | ||
|
||
|
||
void CAN::SetCANImpl(MCP2515* mcp, uint8_t iPin, CAN::MessageCallback cb) { | ||
m_mcp2515 = mcp; | ||
m_interruptPin = iPin; | ||
m_messageCb = cb; | ||
} | ||
|
||
void CAN::Update() { | ||
can_frame frame; | ||
if (!digitalRead(m_interruptPin)) { | ||
auto err = m_mcp2515->readMessage(&frame); | ||
if (err == MCP2515::ERROR::ERROR_OK) { | ||
for(uint8_t i = 0; i < m_canCount; i++) { | ||
auto canClass = m_canClasses[i]; | ||
if (canClass == nullptr) return; | ||
auto masked = frame.can_id & CAN_EFF_MASK; | ||
auto matchesId = canClass->matchesId(masked); | ||
if (matchesId >= 0) { | ||
m_messageCb(canClass, matchesId); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
void CAN::AddToReadList() { | ||
m_canClasses[m_canCount] = this; | ||
m_canCount++; | ||
} | ||
|
||
void CAN::RemoveFromReadList() { | ||
for (int i = 0; i < m_canCount; i++) { | ||
if (m_canClasses[i] == this) { | ||
m_canClasses[i] == nullptr; | ||
} | ||
} | ||
} | ||
|
||
bool CAN::WritePacket(const uint8_t *data, uint8_t length, int apiId) { | ||
can_frame frame; | ||
memcpy(frame.data, data, length); | ||
frame.can_dlc = length; | ||
frame.can_id = m_messageMask; | ||
frame.can_id |= apiId << 6; | ||
frame.can_id |= CAN_EFF_FLAG; | ||
|
||
return m_mcp2515->sendMessage(&frame) == MCP2515::ERROR::ERROR_OK; | ||
|
||
} | ||
|
||
bool CAN::WriteRTRFrame(uint8_t length, int apiId) { | ||
can_frame frame; | ||
memset(frame.data, 0, 8); | ||
frame.can_dlc = length; | ||
frame.can_id = m_messageMask; | ||
frame.can_id |= apiId << 6; | ||
frame.can_id |= CAN_EFF_FLAG; | ||
frame.can_id |= CAN_RTR_FLAG; | ||
|
||
return m_mcp2515->sendMessage(&frame) == MCP2515::ERROR::ERROR_OK; | ||
} |
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,94 @@ | ||
#pragma once | ||
|
||
class MCP2515; | ||
|
||
namespace frc | ||
{ | ||
struct CANData | ||
{ | ||
uint8_t data[8]; | ||
uint8_t length; | ||
uint32_t timestamp; | ||
}; | ||
|
||
enum class CANDeviceType | ||
{ | ||
kBroadcast = 0, | ||
kRobotController = 1, | ||
kMotorController = 2, | ||
kRelayController = 3, | ||
kGyroSensor = 4, | ||
kAccelerometer = 5, | ||
kUltrasonicSensor = 6, | ||
kGearToothSensor = 7, | ||
kPowerDistribution = 8, | ||
kPneumatics = 9, | ||
kMiscellaneous = 10, | ||
kFirmwareUpdate = 31 | ||
}; | ||
|
||
enum class CANManufacturer | ||
{ | ||
kBroadcast = 0, | ||
kNI = 1, | ||
kLM = 2, | ||
kDEKA = 3, | ||
kCTRE = 4, | ||
kREV = 5, | ||
kGrapple = 6, | ||
kMS = 7, | ||
kTeamUse = 8, | ||
kKauaiLabs = 9, | ||
kCopperforge = 10, | ||
kPWF = 11, | ||
kStudica = 12 | ||
}; | ||
|
||
constexpr uint32_t createCANId(uint16_t apiId, uint8_t deviceId, uint8_t manufacturer, uint8_t deviceType) | ||
{ | ||
return (static_cast<uint32_t>(deviceType) & 0x1F) << 24 | (static_cast<uint32_t>(manufacturer) & 0xFF) << 16 | (apiId & 0x3FF) << 6 | (deviceId & 0x3F); | ||
} | ||
|
||
class CAN | ||
{ | ||
public: | ||
typedef void (*MessageCallback)(CAN *can, int apiId); | ||
static void SetCANImpl(MCP2515 *mcp2515, uint8_t interruptPin, MessageCallback messageCallback); | ||
|
||
static void Update(); | ||
|
||
constexpr CAN(int deviceId, CANManufacturer deviceManufacturer, CANDeviceType deviceType) | ||
: m_messageMask{createCANId(0, deviceId, static_cast<uint8_t>(deviceManufacturer), static_cast<uint8_t>(deviceType))} | ||
{ | ||
} | ||
|
||
constexpr explicit CAN(int deviceId) : CAN{deviceId, CANManufacturer::kTeamUse, CANDeviceType::kMiscellaneous} | ||
{ | ||
} | ||
|
||
void AddToReadList(); | ||
|
||
void RemoveFromReadList(); | ||
|
||
bool WritePacket(const uint8_t *data, uint8_t length, int apiId); | ||
|
||
bool WriteRTRFrame(uint8_t length, int apiId); | ||
|
||
private: | ||
static MCP2515* m_mcp2515; | ||
static uint8_t m_interruptPin; | ||
static CAN::MessageCallback m_messageCb; | ||
static CAN* m_canClasses[16]; | ||
static uint8_t m_canCount; | ||
|
||
int16_t matchesId(int32_t id) { | ||
constexpr int32_t mask = 0x1FFF003F; | ||
constexpr int32_t filter = 0x0000FFC0; | ||
if ((id & mask) == m_messageMask) { | ||
return (id & filter) >> 6; | ||
} | ||
return -1; | ||
} | ||
uint32_t m_messageMask = 0; | ||
}; | ||
} // namespace frc |
Oops, something went wrong.