audio_pwm.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. #include "system/includes.h"
  2. #include "app_config.h"
  3. #include "app_action.h"
  4. #include "app_main.h"
  5. #include "gpio.h"
  6. #include "asm/power/p11.h"
  7. // 可配参数
  8. #define AUDIO_PWM_SOURCE (1) // 0:timer 1:mcpwm
  9. #define AUDIO_PWM_MODE (3) // 0:single mode 1:diff mode 0 2:diff mode 1 3:diff mode 2
  10. #define FADE_STEP (100) // PWM开始和结尾的淡入淡出步进,每 FADE_STEP 个点更新一次占空比单位
  11. #if (AUDIO_PWM_SOURCE == 0)
  12. #define PWM_DEAD_AREA (50) // PWM死区时钟数 因为占空比在中断更新,这个时间要大于中断的整个处理时间,但要小于PWM周期
  13. #elif (AUDIO_PWM_SOURCE == 1)
  14. #define PWM_DEAD_AREA (0) // PWM死区时钟数 MCPWM 模块有占空比更新时机控制机制,不需要死区
  15. #endif
  16. #define BUF_SIZE (1024 * 4) // AUDIO PWM 缓冲buf大小
  17. u32 pwm_io_P = IO_PORTB_08; // PWM 输出 P 端 IO 选择,单端只关注 P 端即可
  18. u32 pwm_io_N = IO_PORTB_09; // PWM 输出 N 端 IO 选择,差分需要配置 N 端
  19. // PWM cbuf 缓冲区相关参数
  20. volatile s16 audio_pwm_cbuf[BUF_SIZE] = {0};
  21. volatile u32 rptr = 0;
  22. volatile u32 wptr = 0;
  23. static u8 pwm_is_closed = 1;
  24. // PWM 状态及占空比控制参数
  25. #define STATE_STOP (0)
  26. #define STATE_FADE_IN (1)
  27. #define STATE_START (2)
  28. #define STATE_FADE_OUT (3)
  29. volatile u8 audio_pwm_state = 0;
  30. volatile u32 audio_pwm_target = 0;
  31. volatile u32 audio_pwm_cur = 0;
  32. volatile u32 audio_pwm_prd = 0; // 周期时钟数,也是占空比的分辨率
  33. u16 pcm_to_pwm_scale = 0; // 16bit pcm数据 转成 占空比分辨率范围 的比例值
  34. u32 audio_pwm_zero = 0; // PCM 数据 0 的时候对应的 PWM 值
  35. u32 half_wave_limit = 0;
  36. volatile u8 pwm_need_resume = 0;
  37. static OS_SEM pwm_need_resume_sem ;
  38. static void (*pwm_resume_handler)(void *) = NULL;
  39. static u8 drop_flag = 0;
  40. void state_printf(void)
  41. {
  42. printf("state :%d, pwm_h:%d, pwm_l:%d", audio_pwm_state, JL_MCPWM->CH3_CMPH, JL_MCPWM->CH3_CMPL);
  43. }
  44. void set_state(u8 state)
  45. {
  46. if (state == STATE_STOP) { //要设置pwm 停止需要等cbuffer 里面的数据播完
  47. u8 err_cnt = 0;
  48. while (abs(wptr - rptr) > 1) {
  49. delay(3000);
  50. err_cnt++;
  51. if (err_cnt > 500) {
  52. printf("wptr:%x,rptr:%x!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", wptr, rptr);
  53. break;
  54. }
  55. }
  56. audio_pwm_state = state;
  57. pwm_is_closed = 1;
  58. } else {
  59. audio_pwm_state = state;
  60. pwm_is_closed = 0;
  61. }
  62. }
  63. #if (AUDIO_PWM_SOURCE == 0) // timer
  64. ___interrupt
  65. void usr_pwm_timer_isr(void) __attribute__((section(".audio_pwm_code")))
  66. {
  67. s32 pcm = 0;
  68. s32 pcm1 = 0;
  69. JL_TIMER3->CON |= BIT(14);
  70. /* JL_PORTA->DIR &= ~BIT(5); */
  71. /* JL_PORTA->OUT &= ~BIT(5); */
  72. if (drop_flag == 0) {
  73. drop_flag = 1;
  74. return;
  75. } else {
  76. drop_flag = 0;
  77. }
  78. if (audio_pwm_state == STATE_START) {
  79. if (rptr != wptr) {
  80. pcm = (s32)(audio_pwm_cbuf[rptr]);
  81. #if (AUDIO_PWM_MODE == 0)
  82. if (pcm >= 0) {
  83. pcm += pcm_to_pwm_scale / 2;
  84. } else {
  85. pcm -= pcm_to_pwm_scale / 2;
  86. }
  87. pcm /= pcm_to_pwm_scale;
  88. if (pcm > half_wave_limit) {
  89. pcm = half_wave_limit;
  90. } else if (pcm < -half_wave_limit) {
  91. pcm = -half_wave_limit;
  92. }
  93. JL_TIMER3->PWM = (u32)(pcm + audio_pwm_zero); // P
  94. #elif (AUDIO_PWM_MODE == 1)
  95. if (pcm >= 0) {
  96. pcm += pcm_to_pwm_scale / 2;
  97. } else {
  98. pcm -= pcm_to_pwm_scale / 2;
  99. }
  100. pcm /= pcm_to_pwm_scale;
  101. if (pcm > half_wave_limit) {
  102. pcm = half_wave_limit;
  103. } else if (pcm < -half_wave_limit) {
  104. pcm = -half_wave_limit;
  105. }
  106. JL_TIMER3->PWM = (u32)(pcm + audio_pwm_zero); // P
  107. JL_TIMER2->PWM = (u32)(pcm + audio_pwm_zero); // N
  108. #elif (AUDIO_PWM_MODE == 2)
  109. if (pcm >= 0) {
  110. pcm += pcm_to_pwm_scale / 2;
  111. } else {
  112. pcm -= pcm_to_pwm_scale / 2;
  113. }
  114. pcm /= pcm_to_pwm_scale;
  115. if (pcm > half_wave_limit) {
  116. pcm = half_wave_limit;
  117. } else if (pcm < -half_wave_limit) {
  118. pcm = -half_wave_limit;
  119. }
  120. JL_TIMER3->PWM = (u32)(pcm + audio_pwm_zero); // P
  121. JL_TIMER2->PWM = (u32)(-pcm + audio_pwm_zero); // N
  122. #elif (AUDIO_PWM_MODE == 3)
  123. if (pcm >= 0) {
  124. pcm += pcm_to_pwm_scale / 2;
  125. pcm /= pcm_to_pwm_scale;
  126. if (pcm > half_wave_limit) {
  127. pcm = half_wave_limit;
  128. }
  129. JL_TIMER3->PWM = (u32)(PWM_DEAD_AREA + pcm); // P
  130. JL_TIMER2->PWM = (u32)(PWM_DEAD_AREA); // N
  131. } else {
  132. pcm = -pcm;
  133. pcm -= pcm_to_pwm_scale / 2;
  134. pcm /= pcm_to_pwm_scale;
  135. if (pcm > half_wave_limit) {
  136. pcm = half_wave_limit;
  137. }
  138. JL_TIMER3->PWM = (u32)(PWM_DEAD_AREA); // P
  139. JL_TIMER2->PWM = (u32)(PWM_DEAD_AREA + pcm); // N
  140. }
  141. #endif
  142. rptr++;
  143. if (rptr >= BUF_SIZE) {
  144. rptr = 0;
  145. }
  146. } else {
  147. /* putchar('e'); */
  148. }
  149. } else if ((audio_pwm_state == STATE_FADE_IN) || (audio_pwm_state == STATE_FADE_OUT)) {
  150. if (audio_pwm_cur > audio_pwm_target) {
  151. audio_pwm_cur--;
  152. /* printf("{%d", audio_pwm_cur); */
  153. } else if (audio_pwm_cur < audio_pwm_target) {
  154. audio_pwm_cur++;
  155. /* printf("}%d", audio_pwm_cur); */
  156. } else {
  157. if (audio_pwm_state == STATE_FADE_IN) {
  158. audio_pwm_state = STATE_START;
  159. } else {
  160. audio_pwm_state = STATE_STOP;
  161. }
  162. }
  163. #if (AUDIO_PWM_MODE == 0)
  164. JL_TIMER3->PWM = audio_pwm_cur / FADE_STEP;
  165. #elif ((AUDIO_PWM_MODE == 1) || (AUDIO_PWM_MODE == 2))
  166. JL_TIMER3->PWM = audio_pwm_cur / FADE_STEP;
  167. JL_TIMER2->PWM = audio_pwm_cur / FADE_STEP;
  168. #elif (AUDIO_PWM_MODE == 3) // 这种调制方式不需要淡入淡出
  169. if (audio_pwm_state == STATE_FADE_IN) {
  170. audio_pwm_state = STATE_START;
  171. } else {
  172. audio_pwm_state = STATE_STOP;
  173. }
  174. #endif
  175. } else {
  176. // do no thing
  177. }
  178. /* JL_PORTA->DIR &= ~BIT(5); */
  179. /* JL_PORTA->OUT |= BIT(5); */
  180. }
  181. void usr_pwm_timer_init(void)
  182. {
  183. printf("############ usr_pwm_timer_init ########## \n");
  184. bit_clr_ie(IRQ_TIME3_IDX);
  185. request_irq(IRQ_TIME3_IDX, 3, usr_pwm_timer_isr, 0);
  186. irq_unmask_set(IRQ_TIME3_IDX, 0);
  187. JL_TIMER3->CON = BIT(14);
  188. JL_TIMER3->CON |= (6 << 10); //时钟源选择稳定的STD_24M
  189. JL_TIMER3->CON |= (0b0000 << 4); //时钟源再1分频
  190. JL_TIMER3->CON &= ~BIT(9); // PWM_INV 信号反相
  191. JL_TIMER3->CON |= BIT(8); // PWM IO OUT
  192. JL_TIMER3->CNT = 0;
  193. JL_TIMER3->PRD = 750; // 频率 32kHz
  194. JL_TIMER3->PWM = 0;
  195. JL_TIMER3->CON |= BIT(14) | BIT(0);
  196. audio_pwm_prd = JL_TIMER3->PRD;
  197. #if (AUDIO_PWM_MODE == 3)
  198. pcm_to_pwm_scale = 32767 / audio_pwm_prd;
  199. audio_pwm_zero = 0;
  200. half_wave_limit = audio_pwm_prd;
  201. #else
  202. pcm_to_pwm_scale = 65536 / (audio_pwm_prd - PWM_DEAD_AREA);
  203. audio_pwm_zero = PWM_DEAD_AREA + (audio_pwm_prd - PWM_DEAD_AREA) / 2;
  204. half_wave_limit = (audio_pwm_prd - PWM_DEAD_AREA) / 2;
  205. #endif
  206. gpio_set_fun_output_port(pwm_io_P, FO_TMR3_PWM, 0, 1);
  207. //设置引脚状态
  208. gpio_set_die(pwm_io_P, 1);
  209. gpio_set_pull_up(pwm_io_P, 0);
  210. gpio_set_pull_down(pwm_io_P, 0);
  211. gpio_set_direction(pwm_io_P, 0);
  212. #if ((AUDIO_PWM_MODE == 1) || (AUDIO_PWM_MODE == 2) || (AUDIO_PWM_MODE == 3))
  213. JL_TIMER2->CON = 0;
  214. JL_TIMER2->CON |= (6 << 10); //时钟源选择稳定的STD_24M
  215. JL_TIMER2->CON |= (0b0000 << 4); //时钟源再1分频
  216. #if (AUDIO_PWM_MODE == 1)
  217. JL_TIMER2->CON |= BIT(9); // PWM_INV 信号反相
  218. #elif ((AUDIO_PWM_MODE == 2) || (AUDIO_PWM_MODE == 3))
  219. JL_TIMER2->CON &= ~BIT(9); // PWM_INV 信号反相
  220. #endif
  221. JL_TIMER2->CON |= BIT(8); // PWM IO OUT
  222. JL_TIMER2->PRD = 750; // 频率 32kHz
  223. JL_TIMER2->PWM = 0;
  224. JL_TIMER2->CON |= BIT(0);
  225. JL_TIMER2->CNT = 0;
  226. JL_TIMER3->CNT = 0; // sync
  227. gpio_set_fun_output_port(pwm_io_N, FO_TMR2_PWM, 0, 1);
  228. //设置引脚状态
  229. gpio_set_die(pwm_io_N, 1);
  230. gpio_set_pull_up(pwm_io_N, 0);
  231. gpio_set_pull_down(pwm_io_N, 0);
  232. gpio_set_direction(pwm_io_N, 0);
  233. /* gpio_set_hd(pwm_io_N, 1); */
  234. /* gpio_set_hd0(pwm_io_N, 1); */
  235. #endif
  236. audio_pwm_state = STATE_START;
  237. }
  238. void usr_pwm_timer_uninit(void)
  239. {
  240. JL_TIMER3->CON = 0;
  241. #if ((AUDIO_PWM_MODE == 1) || (AUDIO_PWM_MODE == 2) || (AUDIO_PWM_MODE == 3))
  242. JL_TIMER2->CON = 0;
  243. #endif
  244. }
  245. #elif (AUDIO_PWM_SOURCE == 1) // mcpwm
  246. ___interrupt
  247. void usr_mcpwm_isr(void) __attribute__((section(".audio_pwm_code")))
  248. {
  249. s32 pcm = 0;
  250. s32 pcm1 = 0;
  251. if (JL_MCPWM->TMR3_CON & BIT(12)) {
  252. JL_MCPWM->TMR3_CON |= BIT(10);//清中断标志
  253. }
  254. if (drop_flag == 0) {
  255. drop_flag = 1;
  256. return;
  257. } else {
  258. drop_flag = 0;
  259. }
  260. /* JL_PORTA->DIR &= ~BIT(5); */
  261. /* JL_PORTA->OUT &= ~BIT(5); */
  262. if (audio_pwm_state == STATE_START) {
  263. if (rptr != wptr) {
  264. pcm = (s32)(audio_pwm_cbuf[rptr]);
  265. #if (AUDIO_PWM_MODE == 0)
  266. if (pcm >= 0) {
  267. pcm += pcm_to_pwm_scale / 2;
  268. } else {
  269. pcm -= pcm_to_pwm_scale / 2;
  270. }
  271. pcm /= pcm_to_pwm_scale;
  272. if (pcm > half_wave_limit) {
  273. pcm = half_wave_limit;
  274. } else if (pcm < -half_wave_limit) {
  275. pcm = -half_wave_limit;
  276. }
  277. JL_MCPWM->CH3_CMPH = (u32)(pcm + audio_pwm_zero); // P
  278. #elif (AUDIO_PWM_MODE == 1)
  279. if (pcm >= 0) {
  280. pcm += pcm_to_pwm_scale / 2;
  281. } else {
  282. pcm -= pcm_to_pwm_scale / 2;
  283. }
  284. pcm /= pcm_to_pwm_scale;
  285. if (pcm > half_wave_limit) {
  286. pcm = half_wave_limit;
  287. } else if (pcm < -half_wave_limit) {
  288. pcm = -half_wave_limit;
  289. }
  290. JL_MCPWM->CH3_CMPH = (u32)(pcm + audio_pwm_zero); // P
  291. JL_MCPWM->CH3_CMPL = (u32)(pcm + audio_pwm_zero); // N
  292. #elif (AUDIO_PWM_MODE == 2)
  293. if (pcm >= 0) {
  294. pcm += pcm_to_pwm_scale / 2;
  295. } else {
  296. pcm -= pcm_to_pwm_scale / 2;
  297. }
  298. pcm /= pcm_to_pwm_scale;
  299. if (pcm > half_wave_limit) {
  300. pcm = half_wave_limit;
  301. } else if (pcm < -half_wave_limit) {
  302. pcm = -half_wave_limit;
  303. }
  304. JL_MCPWM->CH3_CMPH = (u32)(pcm + audio_pwm_zero); // P
  305. pcm1 = pcm;
  306. JL_MCPWM->CH3_CMPL = (u32)(-pcm + audio_pwm_zero); // N
  307. #elif (AUDIO_PWM_MODE == 3)
  308. if (pcm >= 0) {
  309. pcm += pcm_to_pwm_scale / 2;
  310. pcm /= pcm_to_pwm_scale;
  311. if (pcm > half_wave_limit) {
  312. pcm = half_wave_limit;
  313. }
  314. JL_MCPWM->CH3_CMPH = (u32)(PWM_DEAD_AREA + pcm); // P
  315. JL_MCPWM->CH3_CMPL = PWM_DEAD_AREA; // N
  316. } else {
  317. pcm = -pcm;
  318. pcm -= pcm_to_pwm_scale / 2;
  319. pcm /= pcm_to_pwm_scale;
  320. if (pcm > half_wave_limit) {
  321. pcm = half_wave_limit;
  322. }
  323. JL_MCPWM->CH3_CMPH = PWM_DEAD_AREA; // P
  324. JL_MCPWM->CH3_CMPL = (u32)(PWM_DEAD_AREA + pcm); // N
  325. }
  326. #endif
  327. rptr++;
  328. if (rptr >= BUF_SIZE) {
  329. rptr = 0;
  330. }
  331. } else {
  332. /* putchar('e'); */
  333. }
  334. } else if ((audio_pwm_state == STATE_FADE_IN) || (audio_pwm_state == STATE_FADE_OUT)) {
  335. if (audio_pwm_cur > audio_pwm_target) {
  336. audio_pwm_cur--;
  337. /* printf("{%d", audio_pwm_cur); */
  338. } else if (audio_pwm_cur < audio_pwm_target) {
  339. audio_pwm_cur++;
  340. /* printf("}%d", audio_pwm_cur); */
  341. } else {
  342. if (audio_pwm_state == STATE_FADE_IN) {
  343. audio_pwm_state = STATE_START;
  344. /* putchar('s'); */
  345. } else {
  346. audio_pwm_state = STATE_STOP;
  347. /* putchar('p'); */
  348. }
  349. }
  350. JL_MCPWM->CH3_CMPH = audio_pwm_cur / FADE_STEP;
  351. #if ((AUDIO_PWM_MODE == 1) || (AUDIO_PWM_MODE == 2))
  352. JL_MCPWM->CH3_CMPL = audio_pwm_cur / FADE_STEP;
  353. #elif (AUDIO_PWM_MODE == 3) // 这种调制方式不需要淡入淡出
  354. if (audio_pwm_state == STATE_FADE_IN) {
  355. audio_pwm_state = STATE_START;
  356. } else if (audio_pwm_state == STATE_FADE_OUT) {
  357. audio_pwm_state = STATE_STOP;
  358. }
  359. #endif
  360. } else {
  361. JL_MCPWM->CH3_CMPH = PWM_DEAD_AREA; // P
  362. JL_MCPWM->CH3_CMPL = PWM_DEAD_AREA; // N
  363. // do no thing
  364. }
  365. /* JL_PORTA->DIR &= ~BIT(5); */
  366. /* JL_PORTA->OUT |= BIT(5); */
  367. }
  368. void usr_mcpwm_init(void)
  369. {
  370. printf("############ usr_mcpwm_init ########## \n");
  371. request_irq(IRQ_MCPWM_TIMER, 3, usr_mcpwm_isr, 0);
  372. irq_unmask_set(IRQ_MCPWM_TIMER, 0);
  373. JL_MCPWM->MCPWM_CON0 &= ~BIT(8 + 3);
  374. JL_MCPWM->TMR3_CNT = 0;
  375. JL_MCPWM->TMR3_PR = clk_get("lsb") / 32000;
  376. audio_pwm_prd = JL_MCPWM->TMR3_PR;
  377. #if (AUDIO_PWM_MODE == 3)
  378. pcm_to_pwm_scale = 32767 / audio_pwm_prd;
  379. audio_pwm_zero = 0;
  380. half_wave_limit = audio_pwm_prd;
  381. #else
  382. pcm_to_pwm_scale = 65536 / (audio_pwm_prd - PWM_DEAD_AREA);
  383. audio_pwm_zero = PWM_DEAD_AREA + (audio_pwm_prd - PWM_DEAD_AREA) / 2;
  384. half_wave_limit = (audio_pwm_prd - PWM_DEAD_AREA) / 2;
  385. #endif
  386. JL_MCPWM->TMR3_CON |= BIT(8); // IE
  387. JL_MCPWM->TMR3_CON |= BIT(10) | BIT(0);
  388. JL_MCPWM->MCPWM_CON0 |= BIT(8 + 3); // MCTIMER3 enable
  389. gpio_set_fun_output_port(pwm_io_P, FO_MCPWM_CH3H, 0, 1);
  390. gpio_set_die(pwm_io_P, 1);
  391. gpio_set_direction(pwm_io_P, 0);
  392. gpio_set_pull_up(pwm_io_P, 0);
  393. gpio_set_pull_down(pwm_io_P, 0);
  394. #if ((AUDIO_PWM_MODE == 1) || (AUDIO_PWM_MODE == 2) || (AUDIO_PWM_MODE == 3))
  395. gpio_set_fun_output_port(pwm_io_N, FO_MCPWM_CH3L, 0, 1);
  396. gpio_set_die(pwm_io_N, 1);
  397. gpio_set_direction(pwm_io_N, 0);
  398. gpio_set_pull_up(pwm_io_N, 0);
  399. gpio_set_pull_down(pwm_io_N, 0);
  400. #endif
  401. JL_MCPWM->CH3_CON0 = 0;
  402. JL_MCPWM->CH3_CON0 |= BIT(2); // PWM H enable
  403. JL_MCPWM->CH3_CON0 |= BIT(3); // PWM L enable
  404. JL_MCPWM->CH3_CON0 &= ~BIT(4); // PWM H 信号反相使能
  405. #if (AUDIO_PWM_MODE == 1)
  406. JL_MCPWM->CH3_CON0 |= BIT(5); // PWM L 信号反相使能
  407. #elif ((AUDIO_PWM_MODE == 2) || (AUDIO_PWM_MODE == 3))
  408. JL_MCPWM->CH3_CON0 &= ~BIT(5); // PWM L 信号反相使能
  409. #endif
  410. SFR(JL_MCPWM->CH3_CON0, 0, 2, 2); // duty update type select
  411. SFR(JL_MCPWM->CH3_CON1, 8, 3, 3); // MCPWM CH3 select MCTIMER3
  412. JL_MCPWM->MCPWM_CON0 |= BIT(0 + 3); // MCPWM CH3 enable
  413. audio_pwm_state = STATE_START;
  414. }
  415. void usr_mcpwm_uninit(void)
  416. {
  417. pwm_is_closed = 1;
  418. }
  419. #endif
  420. static void audio_pwm_task(void *param)
  421. {
  422. printf(">>>> audio_pwm_task\n");
  423. u32 buf_points = 0;
  424. while (1) {
  425. if (pwm_need_resume) {
  426. if (rptr < wptr) {
  427. buf_points = wptr - rptr;
  428. } else if (rptr == wptr) {
  429. buf_points = 0;
  430. } else {
  431. buf_points = BUF_SIZE - rptr + wptr;
  432. }
  433. if (buf_points < 1024) { //32 ms
  434. if (pwm_resume_handler != NULL) {
  435. pwm_resume_handler(NULL);
  436. }
  437. /* putchar('R'); */
  438. } else {
  439. /* putchar('N'); */
  440. }
  441. } else {
  442. /* printf("enter audio_pwm.c %d\n",__LINE__); */
  443. os_sem_pend(&pwm_need_resume_sem, 0); //在不需要跑任务的时候pend住,避免任务频繁起来
  444. /* printf("enter audio_pwm.c %d\n",__LINE__); */
  445. }
  446. os_time_dly(1);
  447. }
  448. }
  449. void audio_pwm_set_resume(void (*resume)(void *))
  450. {
  451. pwm_resume_handler = resume;
  452. }
  453. void audio_pwm_open(void)
  454. {
  455. printf("audio_pwm_open\n");
  456. clk_set("sys", 96 * 1000000L);
  457. os_sem_create(&pwm_need_resume_sem, 0);
  458. os_task_create(audio_pwm_task, NULL, 2, 1024, 128, "audio_pwm_task");
  459. #if (AUDIO_PWM_SOURCE == 0) // timer
  460. usr_pwm_timer_init();
  461. #elif (AUDIO_PWM_SOURCE == 1) // mcpwm
  462. usr_mcpwm_init();
  463. #endif // timer of mcpwm
  464. //开机进低功耗要把输出清0,不然有杂声
  465. JL_MCPWM->CH3_CMPH = PWM_DEAD_AREA; // P
  466. JL_MCPWM->CH3_CMPL = PWM_DEAD_AREA; // N
  467. /* pwm_is_closed = 0; */
  468. }
  469. void audio_pwm_close(void)
  470. {
  471. #if (AUDIO_PWM_SOURCE == 0) // timer
  472. usr_pwm_timer_uninit();
  473. #elif (AUDIO_PWM_SOURCE == 1) // mcpwm
  474. usr_mcpwm_uninit();
  475. #endif // timer of mcpwm
  476. }
  477. void audio_pwm_start(void)
  478. {
  479. audio_pwm_state = STATE_FADE_IN;
  480. #if (AUDIO_PWM_SOURCE == 0) // timer
  481. audio_pwm_cur = JL_TIMER3->PWM * FADE_STEP;
  482. #elif (AUDIO_PWM_SOURCE == 1) // mcpwm
  483. audio_pwm_cur = JL_MCPWM->CH3_CMPH;
  484. #endif // timer of mcpwm
  485. audio_pwm_target = audio_pwm_zero * FADE_STEP;
  486. }
  487. void audio_pwm_stop(void)
  488. {
  489. audio_pwm_state = STATE_FADE_OUT;
  490. #if (AUDIO_PWM_SOURCE == 0) // timer
  491. audio_pwm_cur = JL_TIMER3->PWM * FADE_STEP;
  492. #elif (AUDIO_PWM_SOURCE == 1) // mcpwm
  493. audio_pwm_cur = JL_MCPWM->CH3_CMPH;
  494. #endif // timer of mcpwm
  495. audio_pwm_target = 0;
  496. }
  497. static int __audio_pwm_write(s16 *data, u32 len)
  498. {
  499. u32 free_points = 0;
  500. u32 wpoints = len / 2;
  501. local_irq_disable();
  502. if (rptr <= wptr) {
  503. if (rptr == 0) { // 不能让 wptr 和 rptr 碰到一起
  504. free_points = BUF_SIZE - wptr - 1;
  505. } else {
  506. free_points = BUF_SIZE - wptr;
  507. }
  508. } else {
  509. free_points = rptr - wptr - 1;
  510. }
  511. if (free_points == 0) {
  512. local_irq_enable();
  513. return 0;
  514. }
  515. if (wpoints > free_points) {
  516. wpoints = free_points;
  517. }
  518. memcpy(&(audio_pwm_cbuf[wptr]), data, wpoints * 2);
  519. wptr += wpoints;
  520. if (wptr >= BUF_SIZE) {
  521. wptr = 0;
  522. }
  523. local_irq_enable();
  524. return wpoints * 2;
  525. }
  526. int audio_pwm_write(s16 *data, u32 len)
  527. {
  528. u32 wlen = 0;
  529. wlen = __audio_pwm_write(data, len);
  530. if (len != wlen) {
  531. data += wlen / 2;
  532. wlen += __audio_pwm_write(data, len - wlen);
  533. }
  534. if (wlen != len) {
  535. /* putchar('S'); */
  536. pwm_need_resume = 1;
  537. os_sem_post(&pwm_need_resume_sem);
  538. } else {
  539. /* putchar('W'); */
  540. pwm_need_resume = 0;
  541. os_sem_set(&pwm_need_resume_sem, 0);
  542. }
  543. return wlen;
  544. }
  545. static u8 pwm_demo_idle_query()
  546. {
  547. return pwm_is_closed;
  548. }
  549. REGISTER_LP_TARGET(pwm_demo_lp_target) = {
  550. .name = "pwm_demo",
  551. .is_idle = pwm_demo_idle_query,
  552. };