Code for the motor controller

This is basically what we used in Detroit.

Change-Id: If2820d7ec5fcbc5f33b4082025027a6e969ad0e1
diff --git a/motors/util.h b/motors/util.h
index e4a0271..d1eaf53 100644
--- a/motors/util.h
+++ b/motors/util.h
@@ -1,6 +1,11 @@
 #ifndef MOTORS_UTIL_H_
 #define MOTORS_UTIL_H_
 
+#include <stdint.h>
+#include <stddef.h>
+
+#include "motors/core/kinetis.h"
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -97,6 +102,7 @@
 #define CAN_MB_CONTROL_IDE ((uint32_t)(1 << 21))
 #define CAN_MB_CONTROL_SRR ((uint32_t)(1 << 22))
 #define CAN_MB_CONTROL_INSERT_CODE(n) ((uint32_t)(((n) & 0xF) << 24))
+#define CAN_MB_CONTROL_EXTRACT_CODE(n) ((uint32_t)(((n) >> 24) & 0xF))
 #define CAN_MB_CONTROL_CODE_BUSY_MASK CAN_MB_CONTROL_INSERT_CODE(1)
 #define CAN_MB_PRIO_ID_PRIORITY_MASK ((uint32_t)((1 << 29) - 1))
 #define CAN_MB_CODE_RX_INACTIVE 0
@@ -161,6 +167,116 @@
 };
 #endif  // __cplusplus
 
+typedef struct {
+	uint32_t saddr;
+	uint16_t soff;
+	uint16_t attr;
+	uint32_t nbytes_mlno;
+	uint32_t slast;
+	uint32_t daddr;
+	uint16_t doff;
+	uint16_t citer;
+	uint32_t dlastsga;
+	uint32_t _reserved;
+} DmaTcd __attribute__((aligned(0x20)));
+#ifdef __cplusplus
+static_assert(sizeof(DmaTcd) == 0x20, "DMA TCD is the wrong size");
+#endif
+
+#define ALL_FTM_REGISTERS         \
+  FOR_BOTH_FTM_REGISTER(SC)       \
+  FOR_BOTH_FTM_REGISTER(CNT)      \
+  FOR_BOTH_FTM_REGISTER(MOD)      \
+  FOR_BOTH_FTM_REGISTER(C0SC)     \
+  FOR_BOTH_FTM_REGISTER(C0V)      \
+  FOR_BOTH_FTM_REGISTER(C1SC)     \
+  FOR_BOTH_FTM_REGISTER(C1V)      \
+  FOR_BIG_FTM_REGISTER(C2SC)      \
+  FOR_BIG_FTM_REGISTER(C2V)       \
+  FOR_BIG_FTM_REGISTER(C3SC)      \
+  FOR_BIG_FTM_REGISTER(C3V)       \
+  FOR_BIG_FTM_REGISTER(C4SC)      \
+  FOR_BIG_FTM_REGISTER(C4V)       \
+  FOR_BIG_FTM_REGISTER(C5SC)      \
+  FOR_BIG_FTM_REGISTER(C5V)       \
+  FOR_BIG_FTM_REGISTER(C6SC)      \
+  FOR_BIG_FTM_REGISTER(C6V)       \
+  FOR_BIG_FTM_REGISTER(C7SC)      \
+  FOR_BIG_FTM_REGISTER(C7V)       \
+  FOR_BOTH_FTM_REGISTER(CNTIN)    \
+  FOR_BOTH_FTM_REGISTER(STATUS)   \
+  FOR_BOTH_FTM_REGISTER(MODE)     \
+  FOR_BOTH_FTM_REGISTER(SYNC)     \
+  FOR_BOTH_FTM_REGISTER(OUTINIT)  \
+  FOR_BOTH_FTM_REGISTER(OUTMASK)  \
+  FOR_BOTH_FTM_REGISTER(COMBINE)  \
+  FOR_BOTH_FTM_REGISTER(DEADTIME) \
+  FOR_BOTH_FTM_REGISTER(EXTTRIG)  \
+  FOR_BOTH_FTM_REGISTER(POL)      \
+  FOR_BOTH_FTM_REGISTER(FMS)      \
+  FOR_BOTH_FTM_REGISTER(FILTER)   \
+  FOR_BOTH_FTM_REGISTER(FLTCTRL)  \
+  FOR_LITTLE_FTM_REGISTER(QDCTRL) \
+  FOR_BOTH_FTM_REGISTER(CONF)     \
+  FOR_BOTH_FTM_REGISTER(FLTPOL)   \
+  FOR_BOTH_FTM_REGISTER(SYNCONF)  \
+  FOR_BOTH_FTM_REGISTER(INVCTRL)  \
+  FOR_BOTH_FTM_REGISTER(SWOCTRL)  \
+  FOR_BOTH_FTM_REGISTER(PWMLOAD)
+
+typedef struct {
+#define FOR_BIG_FTM_REGISTER(name) volatile uint32_t name;
+#define FOR_BOTH_FTM_REGISTER(name) volatile uint32_t name;
+#define FOR_LITTLE_FTM_REGISTER(name) const uint32_t _reserved_##name;
+  ALL_FTM_REGISTERS
+#undef FOR_BIG_FTM_REGISTER
+#undef FOR_LITTLE_FTM_REGISTER
+} BigFTM;
+
+typedef struct {
+#define FOR_BIG_FTM_REGISTER(name) const uint32_t _reserved_##name;
+#define FOR_LITTLE_FTM_REGISTER(name) volatile uint32_t name;
+        ALL_FTM_REGISTERS
+#undef FOR_BIG_FTM_REGISTER
+#undef FOR_LITTLE_FTM_REGISTER
+#undef FOR_BOTH_FTM_REGISTER
+} LittleFTM;
+
+#define FTM0 ((BigFTM *)0x40038000)
+#define FTM1 ((LittleFTM *)0x40039000)
+#define FTM2 ((LittleFTM *)0x400B8000)
+#define FTM3 ((BigFTM *)0x400B9000)
+
+#ifdef __cplusplus
+#define FOR_BIG_FTM_REGISTER(name)                                           \
+  static_assert(offsetof(BigFTM, name) ==                                    \
+                    (reinterpret_cast<const volatile char *>(&FTM0_##name) - \
+                     reinterpret_cast<volatile char *>(FTM0)),               \
+                #name " is at the wrong place");                             \
+  static_assert(offsetof(BigFTM, name) ==                                    \
+                    (reinterpret_cast<const volatile char *>(&FTM3_##name) - \
+                     reinterpret_cast<volatile char *>(FTM3)),               \
+                #name " is at the wrong place");
+#define FOR_LITTLE_FTM_REGISTER(name)                                        \
+  static_assert(offsetof(LittleFTM, name) ==                                 \
+                    (reinterpret_cast<const volatile char *>(&FTM1_##name) - \
+                     reinterpret_cast<volatile char *>(FTM1)),               \
+                #name " is at the wrong place");                             \
+  static_assert(offsetof(LittleFTM, name) ==                                 \
+                    (reinterpret_cast<const volatile char *>(&FTM2_##name) - \
+                     reinterpret_cast<volatile char *>(FTM2)),               \
+                #name " is at the wrong place");
+#define FOR_BOTH_FTM_REGISTER(name) \
+  FOR_BIG_FTM_REGISTER(name)        \
+  FOR_LITTLE_FTM_REGISTER(name)
+ALL_FTM_REGISTERS
+#undef FOR_BIG_FTM_REGISTER
+#undef FOR_LITTLE_FTM_REGISTER
+#undef FOR_BOTH_FTM_REGISTER
+#endif
+
+#undef ALL_FTM_REGISTERS
+
 #ifdef __cplusplus
 }
 #endif