diff --git a/bobbycar-can.h b/bobbycar-can.h new file mode 100644 index 0000000..9369b6f --- /dev/null +++ b/bobbycar-can.h @@ -0,0 +1,200 @@ +#pragma once + +#include + +namespace bobbycar { +namespace can { +template +class MotorController +{ +private: + enum { // vvv + DeviceTypeMotorController = 0b00000000000 + }; + + enum { // ...v + MotorControllerCommand = 0b00000000000, + MotorControllerFeedback = 0b00010000000, + }; + + enum { // .........v + MotorControllerFront = 0b00000000000, + MotorControllerBack = 0b00000000010, + }; + + enum { // ..........v + MotorControllerLeft = 0b00000000000, + MotorControllerRight = 0b00000000001, + }; + + enum { + MotorControllerMask = + DeviceTypeMotorController | + (isBack ? MotorControllerBack : MotorControllerFront) | + (isRight ? MotorControllerRight : MotorControllerLeft) + }; + +public: + MotorController() = delete; + ~MotorController() = delete; + + class Command { + private: + enum { + MotorControllerCommandMask = MotorControllerMask | MotorControllerCommand + }; + + public: + Command() = delete; + ~Command() = delete; + + enum { // ....vvvvv + Enable = 0b00000000000 | MotorControllerCommandMask, + InpTgt = 0b00000000100 | MotorControllerCommandMask, + CtrlTyp = 0b00000001000 | MotorControllerCommandMask, + CtrlMod = 0b00000001100 | MotorControllerCommandMask, + IMotMax = 0b00000010000 | MotorControllerCommandMask, + IDcMax = 0b00000010100 | MotorControllerCommandMask, + NMotMax = 0b00000011000 | MotorControllerCommandMask, + FieldWeakMax = 0b00000011100 | MotorControllerCommandMask, + PhaseAdvMax = 0b00000100000 | MotorControllerCommandMask, + CruiseCtrlEna = 0b00000100100 | MotorControllerCommandMask, + CruiseMotTgt = 0b00000101000 | MotorControllerCommandMask, + BuzzerFreq = 0b00000101100 | MotorControllerCommandMask, + BuzzerPattern = 0b00000110000 | MotorControllerCommandMask, + Led = 0b00000110100 | MotorControllerCommandMask, + Poweroff = 0b00000111000 | MotorControllerCommandMask + }; + }; + + class Feedback { + private: + enum { + MotorControllerFeedbackMask = MotorControllerMask | MotorControllerFeedback + }; + + public: + Feedback() = delete; + ~Feedback() = delete; + + enum { // ....vvvvv + DcLink = 0b00000000000 | MotorControllerFeedbackMask, + Speed = 0b00000000100 | MotorControllerFeedbackMask, + Error = 0b00000001000 | MotorControllerFeedbackMask, + Angle = 0b00000001100 | MotorControllerFeedbackMask, + DcPhaA = 0b00000010000 | MotorControllerFeedbackMask, + DcPhaB = 0b00000010100 | MotorControllerFeedbackMask, + DcPhaC = 0b00000011000 | MotorControllerFeedbackMask, + Chops = 0b00000011100 | MotorControllerFeedbackMask, + Hall = 0b00000100000 | MotorControllerFeedbackMask, + Voltage = 0b00000100100 | MotorControllerFeedbackMask, + Temp = 0b00000101000 | MotorControllerFeedbackMask + }; + }; +}; + +inline const char *bobbycarCanIdDesc(uint16_t id) +{ + switch (id) + { + case MotorController::Command::Enable: return "Enable (Command, Front, Left)"; + case MotorController::Command::Enable: return "Enable (Command, Front, Right)"; + case MotorController::Command::Enable: return "Enable (Command, Back, Left)"; + case MotorController::Command::Enable: return "Enable (Command, Back, Right)"; + case MotorController::Command::InpTgt: return "InpTgt (Command, Front, Left)"; + case MotorController::Command::InpTgt: return "InpTgt (Command, Front, Right)"; + case MotorController::Command::InpTgt: return "InpTgt (Command, Back, Left)"; + case MotorController::Command::InpTgt: return "InpTgt (Command, Back, Right)"; + case MotorController::Command::CtrlTyp: return "CtrlTyp (Command, Front, Left)"; + case MotorController::Command::CtrlTyp: return "CtrlTyp (Command, Front, Right)"; + case MotorController::Command::CtrlTyp: return "CtrlTyp (Command, Back, Left)"; + case MotorController::Command::CtrlTyp: return "CtrlTyp (Command, Back, Right)"; + case MotorController::Command::CtrlMod: return "CtrlMod (Command, Front, Left)"; + case MotorController::Command::CtrlMod: return "CtrlMod (Command, Front, Right)"; + case MotorController::Command::CtrlMod: return "CtrlMod (Command, Back, Left)"; + case MotorController::Command::CtrlMod: return "CtrlMod (Command, Back, Right)"; + case MotorController::Command::IMotMax: return "IMotMax (Command, Front, Left)"; + case MotorController::Command::IMotMax: return "IMotMax (Command, Front, Right)"; + case MotorController::Command::IMotMax: return "IMotMax (Command, Back, Left)"; + case MotorController::Command::IMotMax: return "IMotMax (Command, Back, Right)"; + case MotorController::Command::IDcMax: return "IDcMax (Command, Front, Left)"; + case MotorController::Command::IDcMax: return "IDcMax (Command, Front, Right)"; + case MotorController::Command::IDcMax: return "IDcMax (Command, Back, Left)"; + case MotorController::Command::IDcMax: return "IDcMax (Command, Back, Right)"; + case MotorController::Command::NMotMax: return "NMotMax (Command, Front, Left)"; + case MotorController::Command::NMotMax: return "NMotMax (Command, Front, Right)"; + case MotorController::Command::NMotMax: return "NMotMax (Command, Back, Left)"; + case MotorController::Command::NMotMax: return "NMotMax (Command, Back, Right)"; + case MotorController::Command::FieldWeakMax: return "FieldWeakMax (Command, Front, Left)"; + case MotorController::Command::FieldWeakMax: return "FieldWeakMax (Command, Front, Right)"; + case MotorController::Command::FieldWeakMax: return "FieldWeakMax (Command, Back, Left)"; + case MotorController::Command::FieldWeakMax: return "FieldWeakMax (Command, Back, Right)"; + case MotorController::Command::PhaseAdvMax: return "PhaseAdvMax (Command, Front, Left)"; + case MotorController::Command::PhaseAdvMax: return "PhaseAdvMax (Command, Front, Right)"; + case MotorController::Command::PhaseAdvMax: return "PhaseAdvMax (Command, Back, Left)"; + case MotorController::Command::PhaseAdvMax: return "PhaseAdvMax (Command, Back, Right)"; + case MotorController::Command::BuzzerFreq: return "BuzzerFreq (Command, Front, Left)"; + case MotorController::Command::BuzzerFreq: return "BuzzerFreq (Command, Front, Right)"; + case MotorController::Command::BuzzerFreq: return "BuzzerFreq (Command, Back, Left)"; + case MotorController::Command::BuzzerFreq: return "BuzzerFreq (Command, Back, Right)"; + case MotorController::Command::BuzzerPattern: return "BuzzerPattern (Command, Front, Left)"; + case MotorController::Command::BuzzerPattern: return "BuzzerPattern (Command, Front, Right)"; + case MotorController::Command::BuzzerPattern: return "BuzzerPattern (Command, Back, Left)"; + case MotorController::Command::BuzzerPattern: return "BuzzerPattern (Command, Back, Right)"; + case MotorController::Command::Led: return "Led (Command, Front, Left)"; + case MotorController::Command::Led: return "Led (Command, Front, Right)"; + case MotorController::Command::Led: return "Led (Command, Back, Left)"; + case MotorController::Command::Led: return "Led (Command, Back, Right)"; + case MotorController::Command::Poweroff: return "Poweroff (Command, Front, Left)"; + case MotorController::Command::Poweroff: return "Poweroff (Command, Front, Right)"; + case MotorController::Command::Poweroff: return "Poweroff (Command, Back, Left)"; + case MotorController::Command::Poweroff: return "Poweroff (Command, Back, Right)"; + case MotorController::Feedback::DcLink: return "DcLink (Feedback, Front, Left)"; + case MotorController::Feedback::DcLink: return "DcLink (Feedback, Front, Right)"; + case MotorController::Feedback::DcLink: return "DcLink (Feedback, Back, Left)"; + case MotorController::Feedback::DcLink: return "DcLink (Feedback, Back, Right)"; + case MotorController::Feedback::Speed: return "Speed (Feedback, Front, Left)"; + case MotorController::Feedback::Speed: return "Speed (Feedback, Front, Right)"; + case MotorController::Feedback::Speed: return "Speed (Feedback, Back, Left)"; + case MotorController::Feedback::Speed: return "Speed (Feedback, Back, Right)"; + case MotorController::Feedback::Error: return "Error (Feedback, Front, Left)"; + case MotorController::Feedback::Error: return "Error (Feedback, Front, Right)"; + case MotorController::Feedback::Error: return "Error (Feedback, Back, Left)"; + case MotorController::Feedback::Error: return "Error (Feedback, Back, Right)"; + case MotorController::Feedback::Angle: return "Angle (Feedback, Front, Left)"; + case MotorController::Feedback::Angle: return "Angle (Feedback, Front, Right)"; + case MotorController::Feedback::Angle: return "Angle (Feedback, Back, Left)"; + case MotorController::Feedback::Angle: return "Angle (Feedback, Back, Right)"; + case MotorController::Feedback::DcPhaA: return "DcPhaA (Feedback, Front, Left)"; + case MotorController::Feedback::DcPhaA: return "DcPhaA (Feedback, Front, Right)"; + case MotorController::Feedback::DcPhaA: return "DcPhaA (Feedback, Back, Left)"; + case MotorController::Feedback::DcPhaA: return "DcPhaA (Feedback, Back, Right)"; + case MotorController::Feedback::DcPhaB: return "DcPhaB (Feedback, Front, Left)"; + case MotorController::Feedback::DcPhaB: return "DcPhaB (Feedback, Front, Right)"; + case MotorController::Feedback::DcPhaB: return "DcPhaB (Feedback, Back, Left)"; + case MotorController::Feedback::DcPhaB: return "DcPhaB (Feedback, Back, Right)"; + case MotorController::Feedback::DcPhaC: return "DcPhaC (Feedback, Front, Left)"; + case MotorController::Feedback::DcPhaC: return "DcPhaC (Feedback, Front, Right)"; + case MotorController::Feedback::DcPhaC: return "DcPhaC (Feedback, Back, Left)"; + case MotorController::Feedback::DcPhaC: return "DcPhaC (Feedback, Back, Right)"; + case MotorController::Feedback::Chops: return "Chops (Feedback, Front, Left)"; + case MotorController::Feedback::Chops: return "Chops (Feedback, Front, Right)"; + case MotorController::Feedback::Chops: return "Chops (Feedback, Back, Left)"; + case MotorController::Feedback::Chops: return "Chops (Feedback, Back, Right)"; + case MotorController::Feedback::Hall: return "Hall (Feedback, Front, Left)"; + case MotorController::Feedback::Hall: return "Hall (Feedback, Front, Right)"; + case MotorController::Feedback::Hall: return "Hall (Feedback, Back, Left)"; + case MotorController::Feedback::Hall: return "Hall (Feedback, Back, Right)"; + case MotorController::Feedback::Voltage: return "Voltage (Feedback, Front, Left)"; + case MotorController::Feedback::Voltage: return "Voltage (Feedback, Front, Right)"; + case MotorController::Feedback::Voltage: return "Voltage (Feedback, Back, Left)"; + case MotorController::Feedback::Voltage: return "Voltage (Feedback, Back, Right)"; + case MotorController::Feedback::Temp: return "Temp (Feedback, Front, Left)"; + case MotorController::Feedback::Temp: return "Temp (Feedback, Front, Right)"; + case MotorController::Feedback::Temp: return "Temp (Feedback, Back, Left)"; + case MotorController::Feedback::Temp: return "Temp (Feedback, Back, Right)"; + } + return "Unknown"; +} +} +} diff --git a/bobbycar-common.h b/bobbycar-common.h new file mode 100644 index 0000000..b62bfd7 --- /dev/null +++ b/bobbycar-common.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +enum class ControlType : uint8_t { + Commutation, + Sinusoidal, + FieldOrientedControl +}; + +enum class ControlMode : uint8_t { + OpenMode, + Voltage, + Speed, // Only with FieldOrientedControl + Torque // Only with FieldOrientedControl +}; diff --git a/protocol.h b/bobbycar-serial.h similarity index 87% rename from protocol.h rename to bobbycar-serial.h index bd918a0..58a904a 100644 --- a/protocol.h +++ b/bobbycar-serial.h @@ -2,20 +2,7 @@ #include -namespace { - -enum class ControlType : uint8_t { - Commutation, - Sinusoidal, - FieldOrientedControl -}; - -enum class ControlMode : uint8_t { - OpenMode, - Voltage, - Speed, // Only with FieldOrientedControl - Torque // Only with FieldOrientedControl -}; +#include "bobbycar-common.h" struct MotorState { bool enable = false; @@ -29,7 +16,7 @@ struct MotorState { uint8_t phaseAdvMax = 40; // [deg] Maximum Phase Advance angle (only for SIN). Higher angle results in higher maximum speed. }; -uint16_t calculateChecksum(MotorState state) { +inline uint16_t calculateChecksum(MotorState state) { return uint16_t(state.enable) ^ state.pwm ^ @@ -47,7 +34,7 @@ struct BuzzerState { uint8_t pattern = 0; }; -uint16_t calculateChecksum(BuzzerState state) { +inline uint16_t calculateChecksum(BuzzerState state) { return state.freq ^ state.pattern; } @@ -67,7 +54,7 @@ struct Command { uint16_t checksum; }; -uint16_t calculateChecksum(Command command) { +inline uint16_t calculateChecksum(Command command) { return command.start ^ calculateChecksum(command.left) ^ calculateChecksum(command.right) ^ @@ -82,12 +69,12 @@ struct MotorFeedback { uint8_t error = 0; int16_t current = 0; uint16_t chops = 0; - bool hallA = false, - hallB = false, - hallC = false; + bool hallA = false; + bool hallB = false; + bool hallC = false; }; -uint16_t calculateChecksum(MotorFeedback feedback) { +inline uint16_t calculateChecksum(MotorFeedback feedback) { return feedback.angle ^ feedback.speed ^ feedback.error ^ feedback.current ^ feedback.chops ^ @@ -105,12 +92,12 @@ struct Feedback { int16_t batVoltage = 0; int16_t boardTemp = 0; - int16_t timeoutCntSerial = 0; + int16_t timeoutCntSerial = 0; uint16_t checksum; }; -uint16_t calculateChecksum(Feedback feedback) { +inline uint16_t calculateChecksum(Feedback feedback) { return feedback.start ^ calculateChecksum(feedback.left) ^ calculateChecksum(feedback.right) ^ @@ -121,7 +108,7 @@ uint16_t calculateChecksum(Feedback feedback) { #define ASSERT_LAYOUT(st, memb, off) \ - static_assert(offsetof(st, memb) == off, "struct layout wrong"); +static_assert(offsetof(st, memb) == off, "struct layout wrong"); ASSERT_LAYOUT(Feedback, start, 0); ASSERT_LAYOUT(Feedback, left, 2); @@ -181,5 +168,3 @@ ASSERT_LAYOUT(Command, buzzer.pattern, 27); ASSERT_LAYOUT(Command, poweroff, 28); ASSERT_LAYOUT(Command, led, 29); ASSERT_LAYOUT(Command, checksum, 30); - -}