hw_config.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * hw_config.c
  3. *
  4. * 可变化的硬件相关逻辑。
  5. * 换 PCB / 改引脚 / 调启动流程 — 只改这个文件, ukey.c 状态机不动。
  6. *
  7. * 函数清单:
  8. * GPIOA_IRQHandler — 按键 GPIO 中断
  9. * checkbleOnOrOff — 按键短按次数 → 操作分发
  10. * sw_hal_sleep — 进入低功耗睡眠 / 关机
  11. * sys_startup — 上电开机硬件初始化
  12. */
  13. #include "hw_config.h"
  14. #include "ledx.h"
  15. #include "RF_PHY.h"
  16. #include "pindef.h"
  17. #include "peripheral.h"
  18. #include "sir24drv.h"
  19. #include "hop_config.h" /* sys_startup: HOP_POOL */
  20. #include "rx_hop.h" /* sys_startup: rx_hop_init */
  21. #include "ukey.h" /* setOPMode, __OP_MODE__, OPMODE_* */
  22. /* ==================== GPIO 中断 ==================== */
  23. __INTERRUPT
  24. __HIGH_CODE
  25. void GPIOA_IRQHandler(void)
  26. {
  27. GPIO_PIN_ClearITFlagBit(SW_KEY_PORT, SW_KEY);
  28. }
  29. /* ==================== 按键短按处理 ==================== */
  30. void checkbleOnOrOff(uint32_t key_up_time)
  31. {
  32. if (key_down_counter > 0) {
  33. if (RTC_GetCycle32k() - key_down_time > KEY_SEQUENCE_TIMEOUT) {
  34. if (key_down_counter == 2) {
  35. /* 双击: 预留(原为配对/BLE) */
  36. } else if (key_down_counter == 1 && CAN_ENTERN_NORMAL_OPMODE()) {
  37. /* 单按: 进入普通模式 */
  38. setOPMode(OPMODE_NORMAL);
  39. } else if (key_down_counter == 1 && __OP_MODE__ == OPMODE_NORMAL) {
  40. /* 普通模式下单按: 切换闪烁模式 */
  41. if (isRFOn) {
  42. key_down_counter = 0;
  43. return;
  44. }
  45. resetEco();
  46. setColorModeNext();
  47. }
  48. key_down_counter = 0;
  49. }
  50. }
  51. }
  52. /* ==================== 进入睡眠 / 关机 ==================== */
  53. void sw_hal_sleep(void)
  54. {
  55. RF2401_Shutdown();
  56. sys_idle_count = 0;
  57. setBrightness(0);
  58. /* 按键唤醒配置 */
  59. GPIO_PIN_ModeCfg(SW_KEY_PORT, SW_KEY, GPIO_ModeIN_PU);
  60. GPIO_PIN_ITModeCfg(SW_KEY_PORT, SW_KEY, GPIO_ITMode_FallEdge);
  61. /* 声音开关: 上拉关断 */
  62. GPIO_PIN_ModeCfg(SOUND_SW_PORT, SOUND_SW, GPIO_ModeOut_PP_5mA);
  63. GPIO_PIN_SetBits(SOUND_SW_PORT, SOUND_SW);
  64. /* 关掉声音检测引脚的唤醒使能 */
  65. R16_PB_INT_EN &= ~SOUND_PIN;
  66. R16_PB_INT_MODE &= ~SOUND_PIN;
  67. R16_PB_INT_IF = SOUND_PIN;
  68. /* LED 引脚设为输出低 */
  69. GPIO_PIN_ModeCfg(LED_PORT, LED_PIN, GPIO_ModeOut_PP_5mA);
  70. GPIO_PIN_ResetBits(LED_PORT, LED_PIN);
  71. /* 使能 GPIO 中断唤醒 */
  72. PFIC_EnableIRQ(GPIO_A_IRQn);
  73. PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay);
  74. DelayMs(50);
  75. /* 标记: 本次由中断唤醒 (若 RTC 唤醒则此标志未被设置, 说明中断失效, 人工唤醒) */
  76. is_iqr_weekup = TRUE;
  77. DelayMs(100);
  78. LowPower_Shutdown(0);
  79. HSECFG_Current(HSE_RCur_100);
  80. need_pwup = TRUE;
  81. }
  82. /* ==================== 开机初始化 ==================== */
  83. void sys_startup(void)
  84. {
  85. /* LED 引脚 */
  86. GPIO_PIN_ModeCfg(LED_PORT, LED_PIN, GPIO_ModeOut_PP_5mA);
  87. GPIO_PIN_ResetBits(LED_PORT, LED_PIN);
  88. ledPwmInit();
  89. /* 进入普通模式 */
  90. setOPMode(OPMODE_NORMAL);
  91. /* 声音引脚: 浮空输入 */
  92. GPIO_PIN_ModeCfg(SOUND_PORT, SOUND_PIN, GPIO_ModeIN_Floating);
  93. /* 声音开关: 输出低 */
  94. GPIO_PIN_ModeCfg(SOUND_SW_PORT, SOUND_SW, GPIO_ModeOut_PP_5mA);
  95. GPIO_PIN_ResetBits(SOUND_SW_PORT, SOUND_SW);
  96. /* SI24R1 重映射 + SPI 初始化 */
  97. SI24R1_SPI_REMAP_INIT();
  98. drv_spi_init();
  99. NRF24L01_Gpio_Init();
  100. if (NRF24L01_check() == SUCCESS) {
  101. RF24L01_Init();
  102. NRF24L01_Set_Speed(SPEED_250K);
  103. DelayMs(10);
  104. RF24L01_Set_Mode(MODE_RX);
  105. /* HOP_POOL 首信道开机驻留 */
  106. {
  107. static const uint8_t pool[HOP_POOL_SIZE] = HOP_POOL;
  108. uint8_t boot_freq = pool[0];
  109. RF24LL01_Write_Hopping_Point(boot_freq);
  110. DelayUs(100);
  111. rx_hop_init(boot_freq);
  112. }
  113. IS_RF_INITED = TRUE;
  114. }
  115. /* 按键 / 空闲状态复位 */
  116. key_down_counter = 0;
  117. is_key_down = FALSE;
  118. skip_this_btn_down = TRUE;
  119. sys_idle_count = 0;
  120. count_5 = 0;
  121. /* 开机防抖计时 */
  122. is_powup_first = TRUE;
  123. sys_open_time = RTC_GetCycle32k();
  124. resetEco();
  125. }
  126. /* ==================== 节能亮度曲线 ==================== */
  127. /* 每阶段从 pwm_start 线性过渡到 pwm_end, 持续 sec 秒。
  128. * is_loop=1 的阶段构成循环体; loop_max_sec 限制循环总时长。
  129. * 修改此表即可调整节能策略, 无需改动 ledx.c 逻辑。 */
  130. /* 修改此表后需同步更新 hw_config.h 中的 ECO_PLAN_LEN */
  131. struct eco_s eco_plan[] = {
  132. { 9500, 60, 9500, 0, 0 }, /* 95% 保持 60 秒 */
  133. };
  134. /* ---- 节能状态机 ---- */
  135. volatile uint8_t eco_idx = 0;
  136. volatile uint16_t eco_sec = 0;
  137. volatile uint16_t eco_loop_sec = 0;
  138. uint8_t resetEco(void)
  139. {
  140. eco_idx = 0;
  141. eco_sec = 0;
  142. eco_loop_sec = 0;
  143. _led_pwm_echo = eco_plan[0].pwm_start;
  144. }
  145. uint8_t changeEco(void)
  146. {
  147. ledPwmApplyBrightness(_led_brightness);
  148. struct eco_s *cur = &eco_plan[eco_idx];
  149. eco_sec++;
  150. _led_pwm_echo = cur->pwm_start
  151. + (int32_t)(cur->pwm_end - cur->pwm_start) * eco_sec / cur->sec;
  152. if (cur->is_loop) {
  153. eco_loop_sec++;
  154. uint8_t ls = eco_idx;
  155. while (ls > 0 && eco_plan[ls - 1].is_loop) ls--;
  156. uint16_t maxs = eco_plan[ls].loop_max_sec;
  157. if (maxs > 0 && eco_loop_sec >= maxs) {
  158. eco_sec = 0;
  159. eco_loop_sec = 0;
  160. uint8_t n = ls;
  161. while (n < ECO_PLAN_LEN && eco_plan[n].is_loop) n++;
  162. if (n < ECO_PLAN_LEN) {
  163. eco_idx = n;
  164. _led_pwm_echo = eco_plan[eco_idx].pwm_start;
  165. }
  166. return 2;
  167. }
  168. }
  169. if (eco_sec >= cur->sec) {
  170. eco_sec = 0;
  171. uint8_t is_last_loop = cur->is_loop
  172. && (eco_idx + 1 >= ECO_PLAN_LEN || !eco_plan[eco_idx + 1].is_loop);
  173. if (is_last_loop) {
  174. uint8_t s = eco_idx;
  175. while (s > 0 && eco_plan[s - 1].is_loop) s--;
  176. eco_idx = s;
  177. } else if (eco_idx + 1 < ECO_PLAN_LEN) {
  178. eco_idx++;
  179. }
  180. _led_pwm_echo = eco_plan[eco_idx].pwm_start;
  181. }
  182. return 2;
  183. }
  184. /* ==================== 声音检测 ==================== */
  185. static uint32_t ms10sys32tick = MS_TO_RTC(2); /* 2ms 检测间隔 */
  186. uint8_t catchSound(void)
  187. {
  188. uint32_t current_time = RTC_GetCycle32k();
  189. uint32_t time_diff;
  190. /* 安全时间差 (处理 32-bit 溢出) */
  191. if (current_time >= _led_current_sound_systick) {
  192. time_diff = current_time - _led_current_sound_systick;
  193. } else {
  194. time_diff = 0xFFFFFFFF - _led_current_sound_systick + current_time + 1;
  195. }
  196. if (time_diff > ms10sys32tick) {
  197. _led_current_sound_systick = current_time;
  198. /* 读取 GPIO 并去抖动 */
  199. uint8_t current_gpio_state = (GPIO_PIN_ReadPortPin(SOUND_PORT, SOUND_PIN) == 0) ? 0 : 1;
  200. if (current_gpio_state != last_gpio_state) {
  201. sound_debounce_count = 0;
  202. } else {
  203. if (sound_debounce_count < SOUND_DEBOUNCE_COUNT) {
  204. sound_debounce_count++;
  205. }
  206. }
  207. last_gpio_state = current_gpio_state;
  208. /* 去抖动稳定后判定声音 */
  209. if (sound_debounce_count >= SOUND_DEBOUNCE_COUNT) {
  210. if (current_gpio_state == 0) {
  211. inSound = SOUND_ACTIVE_DURATION;
  212. setBrightness(255);
  213. return 1;
  214. }
  215. }
  216. /* 声音后保持亮度倒计时 */
  217. if (inSound > 0) {
  218. inSound--;
  219. if (inSound > 0) {
  220. setBrightness(255);
  221. return 1;
  222. }
  223. }
  224. setBrightness(0);
  225. return 2;
  226. }
  227. return 0;
  228. }