21template <SPI_HandleTypeDef *Handle>
class Amt22 {
24 : cs_port_{cs_port}, cs_pin_{cs_pin}, resolution_{resolution} {
25 HAL_GPIO_WritePin(cs_port_, cs_pin_, GPIO_PIN_SET);
26 stm32cubemx_helper::set_context<Handle, Amt22>(
this);
27 HAL_SPI_RegisterCallback(
28 Handle, HAL_SPI_TX_RX_COMPLETE_CB_ID, [](SPI_HandleTypeDef *hspi) {
29 auto amt22 = stm32cubemx_helper::get_context<Handle, Amt22>();
30 amt22->tx_rx_sem_.release();
35 HAL_SPI_Abort_IT(Handle);
36 HAL_SPI_UnRegisterCallback(Handle, HAL_SPI_TX_RX_COMPLETE_CB_ID);
37 stm32cubemx_helper::set_context<Handle, Amt22>(
nullptr);
38 HAL_GPIO_WritePin(cs_port_, cs_pin_, GPIO_PIN_RESET);
42 std::array<uint8_t, 2> command{0x00, 0x00};
43 auto res = send_command(command);
47 return ((*res)[0] << 8 | (*res)[1]) &
48 ((1 << std::to_underlying(resolution_)) - 1);
52 std::array<uint8_t, 4> command{0x00, 0xA0, 0x00, 0x00};
53 auto res = send_command(command);
57 int16_t turns = ((*res)[2] << 8 | (*res)[3]) & 0x3FFF;
65 std::array<uint8_t, 2> command{0x00, 0x70};
66 return send_command(command).has_value();
70 std::array<uint8_t, 2> command{0x00, 0x60};
71 return send_command(command).has_value();
75 GPIO_TypeDef *cs_port_;
77 rtos::Semaphore tx_rx_sem_{1, 1};
81 std::optional<std::array<uint8_t, N>>
82 send_command(
const std::array<uint8_t, N> &command) {
83 std::array<uint8_t, N> buf;
84 HAL_GPIO_WritePin(cs_port_, cs_pin_, GPIO_PIN_RESET);
85 for (
size_t i = 0; i < N; ++i) {
86 tx_rx_sem_.acquire(0);
87 if (HAL_SPI_TransmitReceive_IT(Handle, &command[i], &buf[i],
89 HAL_SPI_Abort_IT(Handle);
92 if (!tx_rx_sem_.acquire(1)) {
93 HAL_SPI_Abort_IT(Handle);
97 HAL_GPIO_WritePin(cs_port_, cs_pin_, GPIO_PIN_SET);
98 for (
size_t i = 0; i < N; i += 2) {
99 if (!test_checksum(buf[i], buf[i + 1])) {
106 static inline bool test_checksum(uint8_t l, uint8_t h) {
107 bool k1 = !(bit(h, 5) ^ bit(h, 3) ^ bit(h, 1) ^ bit(l, 7) ^ bit(l, 5) ^
108 bit(l, 3) ^ bit(l, 1));
109 bool k0 = !(bit(h, 4) ^ bit(h, 2) ^ bit(h, 0) ^ bit(l, 6) ^ bit(l, 4) ^
110 bit(l, 2) ^ bit(l, 0));
111 return (k1 == bit(h, 7)) && (k0 == bit(h, 6));
114 static inline bool bit(uint8_t x, uint8_t i) {
return ((x >> i) & 1) == 1; }