Cheetah Software  1.0
rt_spi.cpp
Go to the documentation of this file.
1 #include <byteswap.h>
2 #include <math.h>
3 #include <pthread.h>
4 #include <stdio.h>
5 #include <string.h>
6 
7 #include <linux/spi/spidev.h>
8 #include <rt/rt_spi.h>
9 #include <rt/rt_spi_lcm.h>
10 #include <lcm/lcm-cpp.hpp>
11 
12 lcm::LCM *lcm_spi;
13 
14 unsigned char spi_mode = SPI_MODE_0;
15 unsigned char spi_bits_per_word = 8;
16 unsigned int spi_speed = 6000000;
17 uint8_t lsb = 0x01;
18 
19 int spi_1_fd = -1;
20 int spi_2_fd = -1;
21 
22 int spi_open();
23 
26 
27 spi_command_t spi_command_drv;
28 spi_data_t spi_data_drv;
29 spi_torque_t spi_torque;
30 
31 pthread_mutex_t spi_mutex;
32 
33 const float max_torque[3] = {17.f, 17.f, 26.f}; // TODO CHECK WITH BEN
34 const float wimp_torque[3] = {6.f, 6.f, 6.f}; // TODO CHECK WITH BEN
35 const float disabled_torque[3] = {0.f, 0.f, 0.f};
36 
37 // only used for actual robot
38 const float abad_side_sign[4] = {-1.f, -1.f, 1.f, 1.f};
39 const float hip_side_sign[4] = {-1.f, 1.f, -1.f, 1.f};
40 const float knee_side_sign[4] = {-.6429f, .6429f, -.6429f, .6429f};
41 
42 // only used for actual robot
43 const float abad_offset[4] = {0.f, 0.f, 0.f, 0.f};
44 const float hip_offset[4] = {M_PI / 2.f, -M_PI / 2.f, -M_PI / 2.f, M_PI / 2.f};
46  -K_KNEE_OFFSET_POS, K_KNEE_OFFSET_POS};
47 
48 uint32_t xor_checksum(uint32_t *data, size_t len) {
49  uint32_t t = 0;
50  for (size_t i = 0; i < len; i++) t = t ^ data[i];
51  // t = t ^ ((data[i]>>8) + ((data[i] & 0xff) << 8));
52  // t = t ^ __bswap_16(data[i]);
53  return t;
54 }
55 
56 // static void *read_lcm_spi(void *arg) {
57 // printf("[RT SPI] Simulator SPI LCM read thread started!\n");
58 // while (1)
59 // lcm_handle(lcm_spi);
60 //}
61 
62 void fake_spine_control(spi_command_t *cmd, spi_data_t *data,
63  spi_torque_t *torque_out, int board_num) {
64  torque_out->tau_abad[board_num] =
65  cmd->kp_abad[board_num] *
66  (cmd->q_des_abad[board_num] - data->q_abad[board_num]) +
67  cmd->kd_abad[board_num] *
68  (cmd->qd_des_abad[board_num] - data->qd_abad[board_num]) +
69  cmd->tau_abad_ff[board_num];
70 
71  torque_out->tau_hip[board_num] =
72  cmd->kp_hip[board_num] *
73  (cmd->q_des_hip[board_num] - data->q_hip[board_num]) +
74  cmd->kd_hip[board_num] *
75  (cmd->qd_des_hip[board_num] - data->qd_hip[board_num]) +
76  cmd->tau_hip_ff[board_num];
77 
78  torque_out->tau_knee[board_num] =
79  cmd->kp_knee[board_num] *
80  (cmd->q_des_knee[board_num] - data->q_knee[board_num]) +
81  cmd->kd_knee[board_num] *
82  (cmd->qd_des_knee[board_num] - data->qd_knee[board_num]) +
83  cmd->tau_knee_ff[board_num];
84 
85  const float *torque_limits = disabled_torque;
86 
87  if (cmd->flags[board_num] & 0b1) {
88  if (cmd->flags[board_num] & 0b10)
89  torque_limits = wimp_torque;
90  else
91  torque_limits = max_torque;
92  }
93 
94  if (torque_out->tau_abad[board_num] > torque_limits[0])
95  torque_out->tau_abad[board_num] = torque_limits[0];
96  if (torque_out->tau_abad[board_num] < -torque_limits[0])
97  torque_out->tau_abad[board_num] = -torque_limits[0];
98 
99  if (torque_out->tau_hip[board_num] > torque_limits[1])
100  torque_out->tau_hip[board_num] = torque_limits[1];
101  if (torque_out->tau_hip[board_num] < -torque_limits[1])
102  torque_out->tau_hip[board_num] = -torque_limits[1];
103 
104  if (torque_out->tau_knee[board_num] > torque_limits[2])
105  torque_out->tau_knee[board_num] = torque_limits[2];
106  if (torque_out->tau_knee[board_num] < -torque_limits[2])
107  torque_out->tau_knee[board_num] = -torque_limits[2];
108 }
109 
110 void init_spi() {
111  // check sizes:
112  size_t command_size = sizeof(spi_command_t);
113  size_t data_size = sizeof(spi_data_t);
114 
115  memset(&spi_command_drv, 0, sizeof(spi_command_drv));
116  memset(&spi_data_drv, 0, sizeof(spi_data_drv));
117 
118  if (pthread_mutex_init(&spi_mutex, NULL) != 0)
119  printf("[ERROR: RT SPI] Failed to create spi data mutex\n");
120 
121  if (command_size != K_EXPECTED_COMMAND_SIZE) {
122  printf("[RT SPI] Error command size is %ld, expected %d\n", command_size,
124  } else
125  printf("[RT SPI] command size good\n");
126 
127  if (data_size != K_EXPECTED_DATA_SIZE) {
128  printf("[RT SPI] Error data size is %ld, expected %d\n", data_size,
130  } else
131  printf("[RT SPI] data size good\n");
132 
133  printf("[RT SPI] Open\n");
134  spi_open();
135 }
136 
137 int spi_open() {
138  int rv = 0;
139  spi_1_fd = open("/dev/spidev2.0", O_RDWR);
140  if (spi_1_fd < 0) perror("[ERROR] Couldn't open spidev 2.0");
141  spi_2_fd = open("/dev/spidev2.1", O_RDWR);
142  if (spi_2_fd < 0) perror("[ERROR] Couldn't open spidev 2.1");
143 
144  rv = ioctl(spi_1_fd, SPI_IOC_WR_MODE, &spi_mode);
145  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_mode (1)");
146 
147  rv = ioctl(spi_2_fd, SPI_IOC_WR_MODE, &spi_mode);
148  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_mode (2)");
149 
150  rv = ioctl(spi_1_fd, SPI_IOC_RD_MODE, &spi_mode);
151  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_mode (1)");
152 
153  rv = ioctl(spi_2_fd, SPI_IOC_RD_MODE, &spi_mode);
154  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_mode (2)");
155 
156  rv = ioctl(spi_1_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
157  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_bits_per_word (1)");
158 
159  rv = ioctl(spi_2_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
160  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_bits_per_word (2)");
161 
162  rv = ioctl(spi_1_fd, SPI_IOC_RD_BITS_PER_WORD, &spi_bits_per_word);
163  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_bits_per_word (1)");
164 
165  rv = ioctl(spi_2_fd, SPI_IOC_RD_BITS_PER_WORD, &spi_bits_per_word);
166  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_bits_per_word (2)");
167 
168  rv = ioctl(spi_1_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
169  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_max_speed_hz (1)");
170  rv = ioctl(spi_2_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
171  if (rv < 0) perror("[ERROR] ioctl spi_ioc_wr_max_speed_hz (2)");
172 
173  rv = ioctl(spi_1_fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_speed);
174  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_max_speed_hz (1)");
175  rv = ioctl(spi_2_fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_speed);
176  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_max_speed_hz (2)");
177 
178  rv = ioctl(spi_1_fd, SPI_IOC_RD_LSB_FIRST, &lsb);
179  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_lsb_first (1)");
180 
181  rv = ioctl(spi_2_fd, SPI_IOC_RD_LSB_FIRST, &lsb);
182  if (rv < 0) perror("[ERROR] ioctl spi_ioc_rd_lsb_first (2)");
183  return rv;
184 }
185 
187 
188 // convert spi command to spine_cmd_t
189 void spi_to_spine(spi_command_t *cmd, spine_cmd_t *spine_cmd, int leg_0) {
190  for (int i = 0; i < 2; i++) {
191  // spine_cmd->q_des_abad[i] = (cmd->q_des_abad[i+leg_0] +
192  // abad_offset[i+leg_0]) * abad_side_sign[i+leg_0]; spine_cmd->q_des_hip[i]
193  // = (cmd->q_des_hip[i+leg_0] + hip_offset[i+leg_0]) *
194  // hip_side_sign[i+leg_0]; spine_cmd->q_des_knee[i] =
195  // (cmd->q_des_knee[i+leg_0] + knee_offset[i+leg_0]) /
196  // knee_side_sign[i+leg_0];
197  spine_cmd->q_des_abad[i] =
198  (cmd->q_des_abad[i + leg_0] * abad_side_sign[i + leg_0]) +
199  abad_offset[i + leg_0];
200  spine_cmd->q_des_hip[i] =
201  (cmd->q_des_hip[i + leg_0] * hip_side_sign[i + leg_0]) +
202  hip_offset[i + leg_0];
203  spine_cmd->q_des_knee[i] =
204  (cmd->q_des_knee[i + leg_0] / knee_side_sign[i + leg_0]) +
205  knee_offset[i + leg_0];
206 
207  spine_cmd->qd_des_abad[i] =
208  cmd->qd_des_abad[i + leg_0] * abad_side_sign[i + leg_0];
209  spine_cmd->qd_des_hip[i] =
210  cmd->qd_des_hip[i + leg_0] * hip_side_sign[i + leg_0];
211  spine_cmd->qd_des_knee[i] =
212  cmd->qd_des_knee[i + leg_0] / knee_side_sign[i + leg_0];
213 
214  spine_cmd->kp_abad[i] = cmd->kp_abad[i + leg_0];
215  spine_cmd->kp_hip[i] = cmd->kp_hip[i + leg_0];
216  spine_cmd->kp_knee[i] = cmd->kp_knee[i + leg_0];
217 
218  spine_cmd->kd_abad[i] = cmd->kd_abad[i + leg_0];
219  spine_cmd->kd_hip[i] = cmd->kd_hip[i + leg_0];
220  spine_cmd->kd_knee[i] = cmd->kd_knee[i + leg_0];
221 
222  spine_cmd->tau_abad_ff[i] =
223  cmd->tau_abad_ff[i + leg_0] * abad_side_sign[i + leg_0];
224  spine_cmd->tau_hip_ff[i] =
225  cmd->tau_hip_ff[i + leg_0] * hip_side_sign[i + leg_0];
226  spine_cmd->tau_knee_ff[i] =
227  cmd->tau_knee_ff[i + leg_0] * knee_side_sign[i + leg_0];
228 
229  spine_cmd->flags[i] = cmd->flags[i + leg_0];
230  }
231  spine_cmd->checksum = xor_checksum((uint32_t *)spine_cmd, 32);
232 }
233 
234 // convert spine_data_t to spi data
235 void spine_to_spi(spi_data_t *data, spine_data_t *spine_data, int leg_0) {
236  for (int i = 0; i < 2; i++) {
237  data->q_abad[i + leg_0] = (spine_data->q_abad[i] - abad_offset[i + leg_0]) *
238  abad_side_sign[i + leg_0];
239  data->q_hip[i + leg_0] = (spine_data->q_hip[i] - hip_offset[i + leg_0]) *
240  hip_side_sign[i + leg_0];
241  data->q_knee[i + leg_0] = (spine_data->q_knee[i] - knee_offset[i + leg_0]) *
242  knee_side_sign[i + leg_0];
243 
244  data->qd_abad[i + leg_0] =
245  spine_data->qd_abad[i] * abad_side_sign[i + leg_0];
246  data->qd_hip[i + leg_0] = spine_data->qd_hip[i] * hip_side_sign[i + leg_0];
247  data->qd_knee[i + leg_0] =
248  spine_data->qd_knee[i] * knee_side_sign[i + leg_0];
249 
250  data->flags[i + leg_0] = spine_data->flags[i];
251  }
252 
253  uint32_t calc_checksum = xor_checksum((uint32_t *)spine_data, 14);
254  if (calc_checksum != (uint32_t)spine_data->checksum)
255  printf("SPI ERROR BAD CHECKSUM GOT 0x%hx EXPECTED 0x%hx\n", calc_checksum,
256  spine_data->checksum);
257 }
258 
259 // send receive from spine
260 void spi_send_receive(spi_command_t *command, spi_data_t *data) {
261  // update driver status flag
263  data->spi_driver_status = spi_driver_iterations << 16;
264 
265  // transmit and receive buffers
266  uint16_t tx_buf[K_WORDS_PER_MESSAGE];
267  uint16_t rx_buf[K_WORDS_PER_MESSAGE];
268 
269  for (int spi_board = 0; spi_board < 2; spi_board++) {
270  // copy command into spine type:
271  spi_to_spine(command, &g_spine_cmd, spi_board * 2);
272 
273  // pointers to command/data spine array
274  uint16_t *cmd_d = (uint16_t *)&g_spine_cmd;
275  uint16_t *data_d = (uint16_t *)&g_spine_data;
276 
277  // zero rx buffer
278  memset(rx_buf, 0, K_WORDS_PER_MESSAGE * sizeof(uint16_t));
279 
280  // copy into tx buffer flipping bytes
281  for (int i = 0; i < K_WORDS_PER_MESSAGE; i++)
282  tx_buf[i] = (cmd_d[i] >> 8) + ((cmd_d[i] & 0xff) << 8);
283  // tx_buf[i] = __bswap_16(cmd_d[i]);
284 
285  // each word is two bytes long
286  size_t word_len = 2; // 16 bit word
287 
288  // spi message struct
289  struct spi_ioc_transfer spi_message[1];
290 
291  // zero message struct.
292  memset(spi_message, 0, 1 * sizeof(struct spi_ioc_transfer));
293 
294  // set up message struct
295  for (int i = 0; i < 1; i++) {
296  spi_message[i].bits_per_word = spi_bits_per_word;
297  spi_message[i].cs_change = 1;
298  spi_message[i].delay_usecs = 0;
299  spi_message[i].len = word_len * 66;
300  spi_message[i].rx_buf = (uint64_t)rx_buf;
301  spi_message[i].tx_buf = (uint64_t)tx_buf;
302  }
303 
304  // do spi communication
305  int rv = ioctl(spi_board == 0 ? spi_1_fd : spi_2_fd, SPI_IOC_MESSAGE(1),
306  &spi_message);
307  (void)rv;
308 
309  // flip bytes the other way
310  for (int i = 0; i < 30; i++)
311  data_d[i] = (rx_buf[i] >> 8) + ((rx_buf[i] & 0xff) << 8);
312  // data_d[i] = __bswap_16(rx_buf[i]);
313 
314  // copy back to data
315  spine_to_spi(data, &g_spine_data, spi_board * 2);
316  }
317 }
318 
320  // do spi board calculations
321  for (int i = 0; i < 4; i++) {
323  }
325 
326  // in here, the driver is good
327  pthread_mutex_lock(&spi_mutex);
329  pthread_mutex_unlock(&spi_mutex);
330 }
331 
332 spi_command_t *get_spi_command() {
333  // printf("Get spi command\n");
334  return &spi_command_drv;
335 }
336 
337 spi_data_t *get_spi_data() { return &spi_data_drv; }
const float hip_offset[4]
Definition: rt_spi.cpp:44
static spine_data_t g_spine_data
Definition: rt_spi.cpp:25
float qd_des_hip[2]
Definition: rt_spi.h:52
int32_t flags[2]
Definition: rt_spi.h:75
int32_t flags[2]
Definition: rt_spi.h:63
float tau_hip_ff[2]
Definition: rt_spi.h:61
void spi_send_receive(spi_command_t *command, spi_data_t *data)
Definition: rt_spi.cpp:260
float q_abad[2]
Definition: rt_spi.h:69
#define K_EXPECTED_COMMAND_SIZE
Definition: rt_spi.h:27
float qd_hip[2]
Definition: rt_spi.h:73
#define K_EXPECTED_DATA_SIZE
Definition: rt_spi.h:29
float kd_hip[2]
Definition: rt_spi.h:58
const float abad_offset[4]
Definition: rt_spi.cpp:43
float kp_knee[2]
Definition: rt_spi.h:56
unsigned int spi_speed
Definition: rt_spi.cpp:16
const float max_torque[3]
Definition: rt_spi.cpp:33
lcm::LCM * lcm_spi
Definition: rt_spi.cpp:12
int32_t checksum
Definition: rt_spi.h:64
float qd_des_knee[2]
Definition: rt_spi.h:53
unsigned char spi_bits_per_word
Definition: rt_spi.cpp:15
float tau_abad_ff[2]
Definition: rt_spi.h:60
const float knee_side_sign[4]
Definition: rt_spi.cpp:40
float qd_knee[2]
Definition: rt_spi.h:74
float q_des_abad[2]
Definition: rt_spi.h:48
const float disabled_torque[3]
Definition: rt_spi.cpp:35
int spi_2_fd
Definition: rt_spi.cpp:20
float q_des_knee[2]
Definition: rt_spi.h:50
#define K_KNEE_OFFSET_POS
Definition: rt_spi.h:30
float kd_knee[2]
Definition: rt_spi.h:59
float q_hip[2]
Definition: rt_spi.h:70
void publish_spi_torque(spi_torque_t *data)
Definition: rt_spi_lcm.cpp:16
float kp_hip[2]
Definition: rt_spi.h:55
float q_knee[2]
Definition: rt_spi.h:71
pthread_mutex_t spi_mutex
Definition: rt_spi.cpp:31
const float hip_side_sign[4]
Definition: rt_spi.cpp:39
void spine_to_spi(spi_data_t *data, spine_data_t *spine_data, int leg_0)
Definition: rt_spi.cpp:235
float qd_des_abad[2]
Definition: rt_spi.h:51
int32_t checksum
Definition: rt_spi.h:76
#define K_WORDS_PER_MESSAGE
Definition: rt_spi.h:28
static spine_cmd_t g_spine_cmd
Definition: rt_spi.cpp:24
unsigned char spi_mode
Definition: rt_spi.cpp:14
void fake_spine_control(spi_command_t *cmd, spi_data_t *data, spi_torque_t *torque_out, int board_num)
Definition: rt_spi.cpp:62
float q_des_hip[2]
Definition: rt_spi.h:49
void init_spi()
Definition: rt_spi.cpp:110
int spi_driver_iterations
Definition: rt_spi.cpp:186
float qd_abad[2]
Definition: rt_spi.h:72
float tau_knee_ff[2]
Definition: rt_spi.h:62
spi_command_t * get_spi_command()
Definition: rt_spi.cpp:332
uint8_t lsb
Definition: rt_spi.cpp:17
spi_torque_t spi_torque
Definition: rt_spi.cpp:29
const float knee_offset[4]
Definition: rt_spi.cpp:45
const float wimp_torque[3]
Definition: rt_spi.cpp:34
spi_data_t spi_data_drv
Definition: rt_spi.cpp:28
void spi_to_spine(spi_command_t *cmd, spine_cmd_t *spine_cmd, int leg_0)
Definition: rt_spi.cpp:189
void spi_driver_run()
Definition: rt_spi.cpp:319
spi_data_t * get_spi_data()
Definition: rt_spi.cpp:337
int spi_1_fd
Definition: rt_spi.cpp:19
float kd_abad[2]
Definition: rt_spi.h:57
uint32_t xor_checksum(uint32_t *data, size_t len)
Definition: rt_spi.cpp:48
float kp_abad[2]
Definition: rt_spi.h:54
int spi_open()
Definition: rt_spi.cpp:137
const float abad_side_sign[4]
Definition: rt_spi.cpp:38
spi_command_t spi_command_drv
Definition: rt_spi.cpp:27