Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 1 | #ifndef AOS_COMMON_SENSORS_SENSORS_H_ |
| 2 | #define AOS_COMMON_SENSORS_SENSORS_H_ |
| 3 | |
| 4 | #include "aos/common/time.h" |
Brian Silverman | ffe3d71 | 2013-03-15 21:35:59 -0700 | [diff] [blame] | 5 | #include "aos/common/byteorder.h" |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 6 | #include "aos/common/control_loop/ControlLoop.h" |
Brian Silverman | 50df23f | 2013-03-20 21:38:07 -0700 | [diff] [blame] | 7 | #include "aos/common/inttypes.h" |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 8 | |
| 9 | namespace aos { |
| 10 | // This namespace contains all of the stuff for dealing with reading sensors and |
| 11 | // communicating it to everything that needs it. There are 4 main classes whose |
| 12 | // instances actually process the data. They must all be registered in the |
| 13 | // appropriate ::aos::crio::ControlsManager hooks. |
| 14 | // |
| 15 | // SensorPackers get run on the cRIO to read inputs (from WPILib or elsewhere) |
| 16 | // and put the values into the Values struct (which is templated for all of the |
| 17 | // classes that use it). |
| 18 | // SensorUnpackers get run on both the atom and the cRIO to take the data from |
| 19 | // the Values struct and put them into queues for control loops etc. |
| 20 | // SensorBroadcasters (on the cRIO) send the data to a SensorReceiver (on the |
| 21 | // atom) to pass to its SensorUnpacker there. |
| 22 | // CRIOControlLoopRunners register with a SensorBroadcaster to get called right |
| 23 | // after reading the sensor data so that they can immediately pass it so a |
| 24 | // SensorUnpacker and then run their control loops. |
| 25 | // The actual SensorPacker and SensorUnpacker classes have the Interface suffix |
| 26 | // on them. |
| 27 | namespace sensors { |
| 28 | |
| 29 | // How many times per ::aos::control_loops::kLoopFrequency sensor |
| 30 | // values get sent out by the cRIO. |
| 31 | // This must evenly divide that frequency into multiples of sysClockRateGet(). |
| 32 | const int kSendsPerCycle = 10; |
| 33 | // ::aos::control_loops::kLoopFrequency / kSendsPerCycle for |
| 34 | // convenience. |
| 35 | extern const time::Time kSensorSendFrequency; |
| 36 | using ::aos::control_loops::kLoopFrequency; |
Brian Silverman | 15ca985 | 2013-03-17 18:24:15 -0700 | [diff] [blame] | 37 | using ::aos::control_loops::NextLoopTime; |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 38 | |
Brian Silverman | 50df23f | 2013-03-20 21:38:07 -0700 | [diff] [blame] | 39 | uint32_t CalculateChecksum(char *buf, size_t size); |
| 40 | |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 41 | // This is the struct that actually gets sent over the UDP socket. |
| 42 | template<class Values> |
| 43 | struct SensorData { |
Brian Silverman | 50df23f | 2013-03-20 21:38:07 -0700 | [diff] [blame] | 44 | // All of the other 4-byte chunks in the message bitwise-exclusive-ORed |
| 45 | // together. Needed because it seems like nobody else checks... (vxworks not |
| 46 | // sending the UDP checksum or (not very likely) linux not checking it). |
Brian Silverman | d3f92f1 | 2013-03-20 23:01:33 -0700 | [diff] [blame] | 47 | // TODO(brians): static_assert that this is at the front |
Brian Silverman | 50df23f | 2013-03-20 21:38:07 -0700 | [diff] [blame] | 48 | uint32_t checksum; |
| 49 | |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 50 | Values values; |
| 51 | // Starts at 0 and goes up. |
| 52 | int32_t count; |
Brian Silverman | ffe3d71 | 2013-03-15 21:35:59 -0700 | [diff] [blame] | 53 | |
| 54 | void NetworkToHost() { |
| 55 | count = ntoh(count); |
| 56 | } |
Brian Silverman | 15ca985 | 2013-03-17 18:24:15 -0700 | [diff] [blame] | 57 | void HostToNetwork() { |
| 58 | count = hton(count); |
| 59 | } |
Brian Silverman | 50df23f | 2013-03-20 21:38:07 -0700 | [diff] [blame] | 60 | |
| 61 | void FillinChecksum() { |
| 62 | checksum = CalculateChecksum(reinterpret_cast<char *>(this) + |
| 63 | sizeof(checksum), |
| 64 | sizeof(*this) - sizeof(checksum)); |
| 65 | } |
| 66 | // Returns whether or not checksum is correct. |
| 67 | bool CheckChecksum() { |
| 68 | uint32_t expected = CalculateChecksum(reinterpret_cast<char *>(this) + |
| 69 | sizeof(checksum), |
| 70 | sizeof(*this) - sizeof(checksum)); |
| 71 | if (checksum != expected) { |
| 72 | LOG(INFO, "expected %"PRIx32" but got %"PRIx32"\n", |
| 73 | expected, checksum); |
| 74 | return false; |
| 75 | } |
| 76 | return true; |
| 77 | } |
Brian Silverman | 3204dd8 | 2013-03-12 18:42:01 -0700 | [diff] [blame] | 78 | } __attribute__((packed)); |
| 79 | |
| 80 | } // namespace sensors |
| 81 | } // namespace aos |
| 82 | |
| 83 | #endif // AOS_COMMON_SENSORS_SENSORS_H_ |