/firmware/robot2011/cpu/radio_protocol.c

https://gitlab.com/balajimude.it/robocup-firmware · C · 206 lines · 153 code · 33 blank · 20 comment · 31 complexity · b73675cdf9d76bf4150472624f32ec2a MD5 · raw file

  1. #include "radio_protocol.h"
  2. #include "radio.h"
  3. #include "timer.h"
  4. #include "status.h"
  5. #include "fpga.h"
  6. #include "ball_sense.h"
  7. #include "power.h"
  8. #include "encoder_monitor.h"
  9. #include "stall.h"
  10. #include "imu.h"
  11. #include "invensense/imuFIFO.h"
  12. #include <string.h>
  13. #define Forward_Size 55
  14. // Last forward packet
  15. uint8_t forward_packet[Forward_Size];
  16. int cmd_body_x;
  17. int cmd_body_y;
  18. int cmd_body_w;
  19. int dribble_command;
  20. int kick_command;
  21. int kick_immediate;
  22. int accel_limit;
  23. int decel_limit;
  24. int sing;
  25. int anthem;
  26. int sequence;
  27. uint8_t reply_buf[64];
  28. uint8_t reply_len;
  29. uint32_t rx_lost_time;
  30. void reply_timer_init() {
  31. // TC0 is used for reply timing.
  32. // Start the timer with the appropriate value in RC when a forward packet is
  33. // received.
  34. // The timer reaches RC and stops when the reverse packet needs to be sent.
  35. //
  36. // The reply timer runs at MCK/32 => 1.5MHz
  37. AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0;
  38. AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
  39. AT91C_BASE_TC0->TC_CMR = AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
  40. AT91C_TC_CPCSTOP | AT91C_TC_CLKS_TIMER_DIV3_CLOCK;
  41. }
  42. void reply_timer_start(uint16_t time) {
  43. if (time < 2) {
  44. time = 2;
  45. }
  46. AT91C_BASE_TC0->TC_RC = time - 1;
  47. AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
  48. }
  49. void radio_reply() {
  50. if (reply_len && reply_timer_done()) {
  51. radio_transmit(reply_buf, reply_len);
  52. reply_len = 0;
  53. }
  54. }
  55. int motor_status(int i) {
  56. int bit = 1 << i;
  57. if (motor_faults & bit) {
  58. return 1;
  59. } else if (motor_stall & bit) {
  60. return 2;
  61. } else if (encoder_faults & bit) {
  62. return 3;
  63. } else {
  64. // Nothing is wrong
  65. return 0;
  66. }
  67. }
  68. int handle_forward_packet() {
  69. if (radio_rx_len != Forward_Size) {
  70. radio_command(SFRX);
  71. radio_command(SRX);
  72. return 0;
  73. }
  74. memcpy(forward_packet, radio_rx_buf, Forward_Size);
  75. rx_lost_time = current_time;
  76. LED_TOGGLE(LED_RG);
  77. LED_OFF(LED_RR);
  78. sequence = forward_packet[0] & 7;
  79. // Clear motor commands in case this robot's ID does not appear in the
  80. // packet
  81. cmd_body_x = 0;
  82. cmd_body_y = 0;
  83. cmd_body_w = 0;
  84. dribble_command = 0;
  85. // Get motor commands from the packet
  86. int offset = 1;
  87. int reply_slot = -1;
  88. for (int slot = 0; slot < 6; ++slot) {
  89. if ((forward_packet[offset + 4] & 0x0f) == robot_id) {
  90. uint8_t more = forward_packet[offset + 3];
  91. cmd_body_x = forward_packet[offset + 0] | ((more & 0x03) << 8);
  92. cmd_body_y = forward_packet[offset + 1] | ((more & 0x0c) << 6);
  93. cmd_body_w = forward_packet[offset + 2] | ((more & 0x30) << 4);
  94. // Sign extension
  95. if (cmd_body_x & 0x200) {
  96. cmd_body_x |= 0xfffffc00;
  97. }
  98. if (cmd_body_y & 0x200) {
  99. cmd_body_y |= 0xfffffc00;
  100. }
  101. if (cmd_body_w & 0x200) {
  102. cmd_body_w |= 0xfffffc00;
  103. }
  104. // Convert the dribbler speed from the top four bits in a byte to
  105. // nine bits
  106. uint8_t four_bits = forward_packet[offset + 4] & 0xf0;
  107. dribble_command =
  108. (four_bits << 1) | (four_bits >> 3) | (four_bits >> 7);
  109. kick_command = forward_packet[offset + 5];
  110. use_chipper = forward_packet[offset + 6] & 1;
  111. kick_immediate = forward_packet[offset + 6] & 2;
  112. accel_limit = forward_packet[offset + 7];
  113. decel_limit = forward_packet[offset + 7];
  114. sing = forward_packet[offset + 6] & 4;
  115. anthem = forward_packet[offset + 6] & 8;
  116. reply_slot = slot;
  117. break;
  118. }
  119. offset += 9;
  120. }
  121. if (accel_limit > 40) {
  122. accel_limit = 40;
  123. }
  124. if (decel_limit > 40) {
  125. decel_limit = 40;
  126. }
  127. if (reply_slot >= 0) {
  128. // Build and send a reverse packet
  129. reply_buf[0] = robot_id | (sequence << 4);
  130. reply_buf[1] = last_rssi;
  131. reply_buf[2] = supply_raw * VBATT_NUM / VBATT_DIV / 100;
  132. reply_buf[3] = kicker_status;
  133. if (failures & Fail_Kicker) {
  134. reply_buf[3] |= 0x80;
  135. }
  136. // Drive motor status
  137. reply_buf[4] = 0;
  138. for (int i = 0; i < 4; ++i) {
  139. reply_buf[4] |= motor_status(i) << (i * 2);
  140. }
  141. // Dribbler status
  142. reply_buf[5] = motor_status(4);
  143. // Ball sensor status
  144. if (failures &
  145. (Fail_Ball_LED_Open | Fail_Ball_Det_Open | Fail_Ball_Det_Short)) {
  146. reply_buf[5] |= 3 << 2;
  147. } else if (failures & Fail_Ball_Dazzled) {
  148. reply_buf[5] |= 2 << 2;
  149. } else if (have_ball) {
  150. reply_buf[5] |= 1 << 2;
  151. }
  152. // Mechanical version
  153. if (base2008) {
  154. reply_buf[5] |= 1 << 4;
  155. }
  156. if (imu_aligned) {
  157. reply_buf[5] |= 1 << 5;
  158. }
  159. reply_buf[6] = kicker_voltage;
  160. long quat[4] = {0};
  161. IMUgetQuaternion(quat);
  162. for (int i = 0; i < 4; ++i) {
  163. reply_buf[7 + i * 2] = quat[i] >> 16;
  164. reply_buf[8 + i * 2] = quat[i] >> 24;
  165. }
  166. reply_len = 7;
  167. reply_timer_start(3000 * reply_slot);
  168. } else {
  169. // Get ready to receive another forward packet
  170. radio_command(SRX);
  171. }
  172. return 1;
  173. }