基质喷涂
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

404 lines
13 KiB

  1. //
  2. // Created by iflyt on 2025/3/2.
  3. //
  4. #include "button_manager.h"
  5. #include <stm32f4xx_hal.h>
  6. #include <base/apphardware.hpp>
  7. #include <base/zbasic.h>
  8. #include <status/motor_manager.h>
  9. #include "led.h"
  10. #include "can_control/can_protocol_factory.h"
  11. #define TAG "EXTI_KEY"
  12. const B_PinInfo ButtonManager::pinInfos[8] = {
  13. {SYSTEM_POWER_PORT, SYSTEM_POWER_PIN, GPIO_PIN_SET, 100}, // PAUSE_PIN 高电平有效
  14. {E_STOP_PORT, E_STOP_PIN, GPIO_PIN_RESET, 100},
  15. {X_PORT, X_ORIGIN_PIN, GPIO_PIN_RESET, 0},
  16. {X_PORT, X_LIMIT_PIN, GPIO_PIN_RESET, 0},
  17. {Y_PORT, Y_ORIGIN_PIN, GPIO_PIN_RESET, 0},
  18. {Y_PORT, Y_LIMIT_PIN, GPIO_PIN_RESET, 0},
  19. {Z_PORT, Z_ORIGIN_PIN, GPIO_PIN_RESET, 0},
  20. {Z_PORT, Z_LIMIT_PIN, GPIO_PIN_RESET, 0}
  21. };
  22. const uint16_t ButtonManager::pins[] = {SYSTEM_POWER_PIN, E_STOP_PIN, X_ORIGIN_PIN, X_LIMIT_PIN,
  23. Y_ORIGIN_PIN, Y_LIMIT_PIN, Z_ORIGIN_PIN, Z_LIMIT_PIN};
  24. ButtonManager* ButtonManager::instance = nullptr;
  25. ButtonManager* ButtonManager::ins() {
  26. if (instance == nullptr) {
  27. instance = new ButtonManager();
  28. }
  29. return instance;
  30. }
  31. ButtonManager::ButtonManager() {
  32. for (int i = 0; i < PIN_COUNT; ++i) {
  33. uint32_t pin_t = pins[i];
  34. pinStates[i] = readPin(getPortByPin(pin_t), pin_t);
  35. }
  36. keyQueue = osMessageQueueNew(10, sizeof(uint16_t), nullptr);
  37. if (keyQueue == nullptr) {
  38. // 处理队列创建失败
  39. }
  40. osThreadNew(ButtonManager::handleKeyInterrupts, this, nullptr);
  41. }
  42. ButtonManager::~ButtonManager() {
  43. osMessageQueueDelete(keyQueue);
  44. }
  45. bool ButtonManager::isPinStateTriggered(uint16_t targetPin, bool state) {
  46. for (int i = 0; i < sizeof(pinInfos) / sizeof(pinInfos[0]); i++) {
  47. if (pinInfos[i].pin == targetPin) {
  48. GPIO_PinState currentLevel = state ? GPIO_PIN_SET : GPIO_PIN_RESET;
  49. // 检查当前电平是否等于有效电平,并且输入的电平也等于有效电平
  50. return (currentLevel == pinInfos[i].activeLevel);
  51. }
  52. }
  53. return false; // 如果未找到对应的引脚,返回 false
  54. }
  55. void ButtonManager::handleInterrupt(uint16_t pin) {
  56. if (instance && instance->keyQueue) {
  57. osMessageQueuePut(instance->keyQueue, &pin, 0, 0);
  58. }
  59. }
  60. bool ButtonManager::readPin(GPIO_TypeDef* port, uint16_t pin) {
  61. return HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET;
  62. }
  63. int ButtonManager::getPinDebounceTime(uint16_t targetPin) {
  64. for (int i = 0; i < sizeof(pinInfos) / sizeof(pinInfos[0]); i++) {
  65. if (pinInfos[i].pin == targetPin) {
  66. return pinInfos[i].debounceTime;
  67. }
  68. }
  69. return 0; // 如果未找到对应的引脚,返回 false
  70. }
  71. bool ButtonManager::isPinTriggered(uint16_t targetPin) {
  72. for (int i = 0; i < sizeof(pinInfos) / sizeof(pinInfos[0]); i++) {
  73. if (pinInfos[i].pin == targetPin) {
  74. GPIO_PinState currentLevel = HAL_GPIO_ReadPin(pinInfos[i].port, pinInfos[i].pin);
  75. // 检查当前电平是否等于有效电平,并且输入的电平也等于有效电平
  76. return (currentLevel == pinInfos[i].activeLevel);
  77. }
  78. }
  79. return false; // 如果未找到对应的引脚,返回 false
  80. }
  81. void ButtonManager::handleKeyInterrupts(void* arg) {
  82. ButtonManager* manager = static_cast<ButtonManager*>(arg);
  83. uint16_t pin;
  84. while (1) {
  85. if (osMessageQueueGet(manager->keyQueue, &pin, nullptr, osWaitForever) == osOK) {
  86. GPIO_TypeDef* port = getPortByPin(pin);
  87. GPIO_PinState pin_state = HAL_GPIO_ReadPin(port, pin);
  88. ZLOGI(TAG, "GPIO PIN %d pin_state %d", pin, pin_state);
  89. int debounceTime = getPinDebounceTime(pin);
  90. if(debounceTime != 0) {
  91. bool b_pin_state = pin_state == GPIO_PIN_SET;
  92. manager->processKeyEvent(pin, b_pin_state);
  93. }else {
  94. bool b_pin_state = pin_state == GPIO_PIN_SET;
  95. osDelay(manager->debounceTime);
  96. bool b_cur_pin_state = HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET;
  97. if (port != nullptr && b_pin_state == b_cur_pin_state) {
  98. manager->processKeyEvent(pin, b_cur_pin_state);
  99. }
  100. else {
  101. ZLOGI(TAG, "[SOFT DEBOUNCE] GPIO PIN %d pin_state %02x ", pin, pin_state);
  102. }
  103. }
  104. }
  105. }
  106. }
  107. void ButtonManager::processKeyEvent(uint16_t pin, bool state) {
  108. const int temp_i = getPinIndex(pin);
  109. if(temp_i < 0)
  110. return;
  111. const uint32_t index = temp_i;
  112. switch (pin) {
  113. case E_STOP_PIN: {
  114. // 处理急停按键事件
  115. if (isPinStateTriggered(E_STOP_PIN, state)) {
  116. ZLOGI(TAG, "E_STOP_PIN Pressed");
  117. {
  118. CanMessage msg = CanProtocolFactory::createUploadEvent(0xFF, SYSTEM_E_STOP_Pressed);
  119. iflytop::AppHardware::ins()->can0Controller.sendMessage(msg);
  120. }
  121. iflytop::AppHardware::ins()->setE_Stop(true);
  122. iflytop::AppHardware::ins()->SystemPowerOff();
  123. } else {
  124. ZLOGI(TAG, "E_STOP_PIN Released");
  125. {
  126. CanMessage msg = CanProtocolFactory::createUploadEvent(0xFF, SYSTEM_E_STOP_Released);
  127. iflytop::AppHardware::ins()->can0Controller.sendMessage(msg);
  128. }
  129. iflytop::AppHardware::ins()->setE_Stop(false);
  130. bool isLaunched = iflytop::AppHardware::ins()->isLaunched();
  131. if(isLaunched) {
  132. iflytop::AppHardware::ins()->SystemPowerOn();
  133. }
  134. }
  135. if (pinStates[index] != state) {
  136. pinStates[index] = state;
  137. }
  138. break;
  139. }
  140. case SYSTEM_POWER_PIN: {
  141. // 处理暂停按键事件
  142. if(isPinStateTriggered(SYSTEM_POWER_PIN, state)) {
  143. ZLOGI(TAG, "SYSTEM_POWER_PIN Pressed");
  144. {
  145. CanMessage msg = CanProtocolFactory::createUploadEvent(0xFF, SYSTEM_Pause_Pressed);
  146. iflytop::AppHardware::ins()->can0Controller.sendMessage(msg);
  147. }
  148. RK3588_POWER_TOGGLE;
  149. LED_KEY_TOGGLE;
  150. // bool
  151. const bool isLaunched = iflytop::AppHardware::ins()->isLaunched();
  152. if(!isLaunched) {
  153. iflytop::AppHardware::ins()->SystemPowerOn();
  154. }
  155. else {
  156. iflytop::AppHardware::ins()->SystemPowerOff();
  157. }
  158. iflytop::AppHardware::ins()->toggleLaunched();
  159. }
  160. else {
  161. {
  162. CanMessage msg = CanProtocolFactory::createUploadEvent(0xFF, SYSTEM_Pause_Released);
  163. iflytop::AppHardware::ins()->can0Controller.sendMessage(msg);
  164. }
  165. ZLOGI(TAG, "SYSTEM POWER PIN Released");
  166. }
  167. if (pinStates[index] != state) {
  168. pinStates[index] = state;
  169. }
  170. break;
  171. }
  172. case X_ORIGIN_PIN: {
  173. // 处理X轴原点传感器事件
  174. const bool isEnter = isPinStateTriggered(X_ORIGIN_PIN, state);
  175. if (isEnter) {
  176. ZLOGI(TAG, "X_ORIGIN_PIN ENTER");
  177. } else {
  178. ZLOGI(TAG, "X_ORIGIN_PIN LEAVE");
  179. }
  180. MotorManager::ins()->motors[0].runZeroLimit(isEnter);
  181. if (pinStates[index] != state) {
  182. pinStates[index] = state;
  183. }
  184. break;
  185. }
  186. case X_LIMIT_PIN: {
  187. // 处理X轴限位传感器事件
  188. const bool isEnter = isPinStateTriggered(X_LIMIT_PIN, state);
  189. if (isPinStateTriggered(X_LIMIT_PIN, state)) {
  190. ZLOGI(TAG, "X_LIMIT_PIN ENTER");
  191. } else {
  192. ZLOGI(TAG, "X_LIMIT_PIN LEAVE");
  193. }
  194. MotorManager::ins()->motors[0].runEndLimit(isEnter);
  195. if (pinStates[index] != state) {
  196. pinStates[index] = state;
  197. }
  198. break;
  199. }
  200. case Y_ORIGIN_PIN: {
  201. // 处理Y轴原点传感器事件
  202. const bool isEnter = isPinStateTriggered(Y_ORIGIN_PIN, state);
  203. if (isEnter) {
  204. ZLOGI(TAG, "Y_ORIGIN_PIN ENTER");
  205. } else {
  206. ZLOGI(TAG, "Y_ORIGIN_PIN LEAVE");
  207. }
  208. MotorManager::ins()->motors[1].runZeroLimit(isEnter);
  209. if (pinStates[index] != state) {
  210. pinStates[index] = state;
  211. }
  212. break;
  213. }
  214. case Y_LIMIT_PIN: {
  215. // 处理Y轴限位传感器事件
  216. const bool isEnter = isPinStateTriggered(Y_LIMIT_PIN, state);
  217. if (isEnter) {
  218. ZLOGI(TAG, "Y_LIMIT_PIN ENTER");
  219. } else {
  220. ZLOGI(TAG, "Y_LIMIT_PIN LEAVE");
  221. }
  222. MotorManager::ins()->motors[1].runEndLimit(isEnter);
  223. if (pinStates[index] != state) {
  224. pinStates[index] = state;
  225. }
  226. break;
  227. }
  228. case Z_ORIGIN_PIN: {
  229. // 处理Z轴原点传感器事件
  230. const bool isEnter = isPinStateTriggered(Z_ORIGIN_PIN, state);
  231. if (isEnter) {
  232. ZLOGI(TAG, "Z_ORIGIN_PIN ENTER");
  233. } else {
  234. ZLOGI(TAG, "Z_ORIGIN_PIN LEAVE");
  235. }
  236. MotorManager::ins()->motors[2].runZeroLimit(isEnter);
  237. if (pinStates[index] != state) {
  238. pinStates[index] = state;
  239. }
  240. break;
  241. }
  242. case Z_LIMIT_PIN: {
  243. // 处理Z轴限位传感器事件
  244. const bool isEnter = isPinStateTriggered(Z_LIMIT_PIN, state);
  245. if (isEnter) {
  246. ZLOGI(TAG, "Z_LIMIT_PIN ENTER");
  247. } else {
  248. ZLOGI(TAG, "Z_LIMIT_PIN LEAVE");
  249. }
  250. MotorManager::ins()->motors[2].runEndLimit(isEnter);
  251. if (pinStates[index] != state) {
  252. pinStates[index] = state;
  253. }
  254. break;
  255. }
  256. default:
  257. break;
  258. }
  259. }
  260. GPIO_TypeDef* ButtonManager::getPortByPin(uint16_t pin) {
  261. if (pin == SYSTEM_POWER_PIN) return SYSTEM_POWER_PORT;
  262. if (pin == E_STOP_PIN) return E_STOP_PORT;
  263. if (pin >= X_ORIGIN_PIN && pin <= X_LIMIT_PIN) return X_PORT;
  264. if (pin >= Y_ORIGIN_PIN && pin <= Y_LIMIT_PIN) return Y_PORT;
  265. if (pin >= Z_ORIGIN_PIN && pin <= Z_LIMIT_PIN) return Z_PORT;
  266. return nullptr;
  267. }
  268. int ButtonManager::getPinIndex(uint16_t pin) {
  269. for (int i = 0; i < PIN_COUNT; ++i) {
  270. if (pins[i] == pin) {
  271. return i;
  272. }
  273. }
  274. return -1;
  275. }
  276. // 初始化 GPIO 引脚
  277. void EX_GPIO_Init(void) {
  278. GPIO_InitTypeDef GPIO_InitStruct = {0};
  279. // 使能 GPIO 时钟
  280. __HAL_RCC_GPIOA_CLK_ENABLE();
  281. __HAL_RCC_GPIOB_CLK_ENABLE();
  282. __HAL_RCC_GPIOF_CLK_ENABLE();
  283. // 配置 KEY1 引脚
  284. GPIO_InitStruct.Pin = SYSTEM_POWER_PIN;
  285. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; // 上升沿触发中断
  286. GPIO_InitStruct.Pull = GPIO_NOPULL;
  287. HAL_GPIO_Init(SYSTEM_POWER_PORT, &GPIO_InitStruct);
  288. // 配置 JT 引脚
  289. GPIO_InitStruct.Pin = E_STOP_PIN;
  290. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  291. GPIO_InitStruct.Pull = GPIO_NOPULL;
  292. HAL_GPIO_Init(E_STOP_PORT, &GPIO_InitStruct);
  293. // 配置 X 轴传感器引脚
  294. GPIO_InitStruct.Pin = X_ORIGIN_PIN | X_LIMIT_PIN;
  295. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  296. GPIO_InitStruct.Pull = GPIO_NOPULL;
  297. HAL_GPIO_Init(X_PORT, &GPIO_InitStruct);
  298. // 配置 Y 轴传感器引脚
  299. GPIO_InitStruct.Pin = Y_ORIGIN_PIN | Y_LIMIT_PIN;
  300. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  301. GPIO_InitStruct.Pull = GPIO_NOPULL;
  302. HAL_GPIO_Init(Y_PORT, &GPIO_InitStruct);
  303. // 配置 Z 轴传感器引脚
  304. GPIO_InitStruct.Pin = Z_ORIGIN_PIN | Z_LIMIT_PIN;
  305. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  306. GPIO_InitStruct.Pull = GPIO_NOPULL;
  307. HAL_GPIO_Init(Z_PORT, &GPIO_InitStruct);
  308. // 配置中断优先级
  309. HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0);
  310. HAL_NVIC_EnableIRQ(EXTI0_IRQn);
  311. HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0);
  312. HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  313. HAL_NVIC_SetPriority(EXTI9_5_IRQn, 5, 0);
  314. HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
  315. }
  316. extern "C" void EXTI0_IRQHandler(void) {
  317. HAL_GPIO_EXTI_IRQHandler(SYSTEM_POWER_PIN);
  318. }
  319. extern "C" void EXTI9_5_IRQHandler(void) {
  320. HAL_GPIO_EXTI_IRQHandler(X_ORIGIN_PIN);
  321. HAL_GPIO_EXTI_IRQHandler(X_LIMIT_PIN);
  322. HAL_GPIO_EXTI_IRQHandler(Y_ORIGIN_PIN);
  323. }
  324. extern "C" void EXTI15_10_IRQHandler(void) {
  325. HAL_GPIO_EXTI_IRQHandler(Y_LIMIT_PIN);
  326. HAL_GPIO_EXTI_IRQHandler(Z_ORIGIN_PIN);
  327. HAL_GPIO_EXTI_IRQHandler(Z_LIMIT_PIN);
  328. HAL_GPIO_EXTI_IRQHandler(E_STOP_PIN);
  329. }
  330. extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
  331. ButtonManager::handleInterrupt(GPIO_Pin);
  332. }
  333. extern "C" uint16_t getORIGINPin(uint32_t motor_index) {
  334. switch (motor_index) {
  335. case 0:
  336. return X_ORIGIN_PIN;
  337. case 1:
  338. return Y_ORIGIN_PIN;
  339. case 2:
  340. return Z_ORIGIN_PIN;
  341. default:
  342. return 0xFFFF;
  343. }
  344. }
  345. #include "button_manager.h"
  346. uint16_t getAxisLimitPin(uint32_t motor_index) {
  347. switch (motor_index) {
  348. case 0:
  349. return X_LIMIT_PIN;
  350. case 1:
  351. return Y_LIMIT_PIN;
  352. case 2:
  353. return Z_LIMIT_PIN;
  354. default:
  355. return 0xFFFF;
  356. }
  357. }