ReduxLib C++ 2025.0.0-beta2
Loading...
Searching...
No Matches
CanandAddress.h
1// Copyright (c) Redux Robotics and other contributors.
2// This is open source and can be modified and shared under the 3-clause BSD license.
3
4#pragma once
5#include "CANBus.h"
6#include "CanandUtils.h"
7#include "CanandMessage.h"
8namespace redux::canand {
9/**
10 * Class representing the exact combination of CAN bus, product IDs, and device IDs that uniquely correspond to a Redux CAN device on a robot.
11 *
12 * <p>
13 * The full 29-bit CAN ID that actually gets put on the bus can be broken down into four components:
14 * </p>
15 * <ol>
16 * <li> A 5 bit device type (devType) that is product specific (the Canandmag is 7 for "gear tooth sensor")</li>
17 * <li> an 8-bit manufacturer code unique to each vendor (the Redux code is 14) </li>
18 * <li> 10 bits of API identifier</li>
19 * <li> a 6-bit device number (devId) that is user-configurable so you can have multiple of a device on a bus
20 * (this is what the "CAN Id" in robot code and vendor tuners usually refer to)</li>
21 * </ol>
22 *
23 * <a href="https://docs.wpilib.org/en/stable/docs/software/can-devices/can-addressing.html"> The WPILib docs</a> elaborate on this in a bit more detail.
24 *
25 * Of note is that it breaks down the 10-bit API identifier into a 6-bit API class and 4-bit API
26 * index. Redux products, however, break it down into a 2 bit API page (page) and an 8 bit API index
27 * (apiIndex), which actually gets used for a device's message API.
28 *
29 * <p>
30 * The breakdown can be seen in the diagram provided below:
31 * </p>
32 * <pre class="not-code">
33 * +-------------------+-------------------------------+-------+-------------------------------+-----------------------+
34 * | Device Type | Manufacturer ID (redux=0xE) | Page | API Index | Device ID (devID) |
35 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
36 * | 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
37 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
38 * </pre>
39 * Documentation on what each apiIndex value does as well as DBCs for Redux devices is available at
40 * <a href="https://docs.reduxrobotics.com/">https://docs.reduxrobotics.com/</a>
41 *
42 * <p>
43 * In summary, to check if an incoming CAN message is from the device the CanandAddress represents, it needs to check:
44 * </p>
45 * <ul>
46 * <li> the devType </li>
47 * <li> the devId </li>
48 * <li> and the CAN bus the message was sent from, as different devices on different buses can share identical IDs</li>
49 * </ul>
50 * to ensure they all match, leaving the apiIndex to be parsed by device class code. (The manufacturer ID is filtered for in the native driver portion of ReduxLib.)
51 *
52 * <p>
53 * Subclasses of CanandDevice will use this class for CAN i/o to a device, as this class provides a method to send CAN packets to the device it describes, and
54 * the internal event loop uses it to determine which messages to give to CanandDevice::HandleMessage by checking them against MsgMatches, yielding
55 * an asynchronous method of receiving packets.
56 * </p>
57 *
58 *
59 *
60 *
61 */
63 public:
64 /**
65 * Constructor with explicit CAN bus.
66 * @param bus the CANBus the address is associated with.
67 * @param devType the device type
68 * @param devId the device CAN id
69 */
70 CanandAddress(CANBus& bus, uint8_t devType, uint8_t devId) : bus{bus}, devType{devType}, devId{devId} {};
71
72 /**
73 * Constructor with implicit Rio CAN bus.
74 * @param devType the device type
75 * @param devId the device CAN id
76 */
77 CanandAddress(uint8_t devType, uint8_t devId) : bus{0}, devType{devType}, devId{devId} {};
78
79 /**
80 * Checks if a CAN message matches against the device type, product id, and device can id
81 *
82 * @param msg a CanandMessage matching
83 * @return if there is a match
84 */
85 inline bool MsgMatches(CanandMessage& msg) { return utils::idMatches(msg.GetId(), devType, devId) && bus.Equals(msg.GetBus()); }
86
87 /**
88 * Sends a CAN message to the CanandAddress.
89 *
90 * @param apiIndex the API index the message should have (between 0-1023 inclusive, optionally ORed with 512 or 256)
91 * @param data 1-8 bytes of payload, as an array or pointer
92 * @param length the length of the the payload buffer
93 * @return if the operation was successful
94 */
95 bool SendCANMessage(uint16_t apiIndex, uint8_t* data, uint8_t length);
96 virtual ~CanandAddress() = default;
97
98
99 /**
100 * Returns the 5-bit device type.
101 *
102 * @return the device type
103 */
104 inline uint8_t GetDeviceType() { return devType; }
105
106 /**
107 * Returns the user-settable device ID.
108 *
109 * @return the device ID
110 */
111 inline uint8_t GetDeviceId() { return devId; }
112
113 private:
114 CANBus bus;
115 uint8_t devType;
116 uint8_t devId;
117 uint8_t baseMsgId;
118};
119}
Definition: CANBus.h:14
bool Equals(CANBus other)
Definition: CANBus.h:36
Definition: CanandAddress.h:62
CanandAddress(uint8_t devType, uint8_t devId)
Definition: CanandAddress.h:77
bool MsgMatches(CanandMessage &msg)
Definition: CanandAddress.h:85
CanandAddress(CANBus &bus, uint8_t devType, uint8_t devId)
Definition: CanandAddress.h:70
uint8_t GetDeviceId()
Definition: CanandAddress.h:111
bool SendCANMessage(uint16_t apiIndex, uint8_t *data, uint8_t length)
uint8_t GetDeviceType()
Definition: CanandAddress.h:104
Definition: CanandMessage.h:26
CANBus GetBus()
Definition: CanandMessage.h:110
uint32_t GetId()
Definition: CanandMessage.h:51
constexpr bool idMatches(uint32_t idToCompare, uint8_t deviceType, uint8_t devId)
Definition: CanandUtils.h:70
Definition: CanandMessage.h:10