Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Nov 23, 2019
0 parents commit ba55be6
Show file tree
Hide file tree
Showing 7 changed files with 1,519 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .vscode/c_cpp_properties.json
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
}
42 changes: 42 additions & 0 deletions FRCCAN.ino
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);
}
}
45 changes: 45 additions & 0 deletions can.h
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_ */
73 changes: 73 additions & 0 deletions frc/CAN.cpp
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;
}
94 changes: 94 additions & 0 deletions frc/CAN.h
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
Loading

0 comments on commit ba55be6

Please sign in to comment.