drv_adc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /**************************************************************************//**
  2. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-12-12 Wayne First version
  9. *
  10. ******************************************************************************/
  11. #include <rtconfig.h>
  12. #if defined(BSP_USING_ADC)
  13. #include <rtdevice.h>
  14. #include "NuMicro.h"
  15. #include "drv_sys.h"
  16. #include "nu_bitutil.h"
  17. #include "drv_adc.h"
  18. /* Private define ---------------------------------------------------------------*/
  19. #define DEF_ADC_TOUCH_SMPL_TICK 40
  20. #define TOUCH_MQ_LENGTH 64
  21. /* Private Typedef --------------------------------------------------------------*/
  22. struct nu_adc
  23. {
  24. struct rt_adc_device dev;
  25. char *name;
  26. uint32_t OpFreqKHz;
  27. IRQn_Type irqn;
  28. E_SYS_IPRST rstidx;
  29. E_SYS_IPCLK clkidx;
  30. int chn_num;
  31. uint32_t chn_mask;
  32. rt_sem_t m_psSem;
  33. #if defined(BSP_USING_ADC_TOUCH)
  34. rt_touch_t psRtTouch;
  35. rt_timer_t psRtTouchMenuTimer;
  36. rt_mq_t m_pmqTouchXYZ;
  37. #endif
  38. nu_adc_cb m_isr[eAdc_ISR_CNT];
  39. nu_adc_cb m_wkisr[eAdc_WKISR_CNT];
  40. };
  41. typedef struct nu_adc *nu_adc_t;
  42. #if defined(BSP_USING_ADC_TOUCH)
  43. struct nu_adc_touch_data
  44. {
  45. uint32_t u32X;
  46. uint32_t u32Y;
  47. uint32_t u32Z0;
  48. uint32_t u32Z1;
  49. };
  50. typedef struct nu_adc_touch_data *nu_adc_touch_data_t;
  51. #endif
  52. /* Private functions ------------------------------------------------------------*/
  53. static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled);
  54. static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
  55. static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args);
  56. /* Public functions ------------------------------------------------------------*/
  57. int rt_hw_adc_init(void);
  58. /* Private variables ------------------------------------------------------------*/
  59. static struct nu_adc g_sNuADC =
  60. {
  61. .name = "adc",
  62. .OpFreqKHz = 4000, /* 1000 <= OpFreqKHz <= 4000 */
  63. .chn_num = 8,
  64. .irqn = IRQ_ADC,
  65. .rstidx = ADCRST,
  66. .clkidx = ADCCKEN,
  67. .chn_mask = 0
  68. };
  69. static void nu_adc_isr(int vector, void *param)
  70. {
  71. rt_int32_t isr, wkisr;
  72. nu_adc_t psNuAdc = (nu_adc_t)param;
  73. rt_int32_t irqidx;
  74. isr = inpw(REG_ADC_ISR);
  75. wkisr = inpw(REG_ADC_WKISR);
  76. while ((irqidx = nu_ctz(isr)) < eAdc_ISR_CNT)
  77. {
  78. uint32_t u32IsrBitMask = 1 << irqidx ;
  79. if (psNuAdc->m_isr[irqidx].cbfunc != RT_NULL)
  80. {
  81. //rt_kprintf("[%s] %d %x\n", __func__, irqidx, psNuAdc->m_isr[irqidx].cbfunc);
  82. psNuAdc->m_isr[irqidx].cbfunc(isr, psNuAdc->m_isr[irqidx].private_data);
  83. }
  84. /* Clear sent bit */
  85. outpw(REG_ADC_ISR, u32IsrBitMask);
  86. isr &= ~(u32IsrBitMask);
  87. } //while
  88. while ((irqidx = nu_ctz(wkisr)) < eAdc_WKISR_CNT)
  89. {
  90. uint32_t u32IsrBitMask = 1 << irqidx ;
  91. if (psNuAdc->m_wkisr[irqidx].cbfunc != RT_NULL)
  92. {
  93. psNuAdc->m_wkisr[irqidx].cbfunc(wkisr, psNuAdc->m_wkisr[irqidx].private_data);
  94. }
  95. /* Clear sent bit */
  96. outpw(REG_ADC_WKISR, u32IsrBitMask);
  97. wkisr &= ~(u32IsrBitMask);
  98. } //while
  99. }
  100. static rt_err_t _nu_adc_init(rt_device_t dev)
  101. {
  102. uint32_t div;
  103. nu_adc_t psNuAdc = (nu_adc_t)dev;
  104. /* ADC Engine Clock is set to freq Khz */
  105. if (psNuAdc->OpFreqKHz > 4000) psNuAdc->OpFreqKHz = 4000;
  106. if (psNuAdc->OpFreqKHz < 1000) psNuAdc->OpFreqKHz = 1000;
  107. div = 12000 / psNuAdc->OpFreqKHz;
  108. outpw(REG_CLK_DIVCTL7, inpw(REG_CLK_DIVCTL7) & ~((0x3 << 19) | (0x7 << 16) | (0xFFul << 24)));
  109. outpw(REG_CLK_DIVCTL7, (0 << 19) | (0 << 16) | ((div - 1) << 24));
  110. /* Install interrupt service routine */
  111. rt_hw_interrupt_install(psNuAdc->irqn, nu_adc_isr, (void *)psNuAdc, psNuAdc->name);
  112. return RT_EOK;
  113. }
  114. static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData)
  115. {
  116. nu_adc_t psNuAdc = (nu_adc_t)userData;
  117. #if defined(BSP_USING_ADC_TOUCH)
  118. static struct nu_adc_touch_data point;
  119. static rt_bool_t bDrop = RT_FALSE;
  120. static uint32_t u32LastZ0 = 0xffffu;
  121. if (psNuAdc->psRtTouch != RT_NULL)
  122. {
  123. uint32_t value;
  124. value = inpw(REG_ADC_XYDATA);
  125. point.u32X = (value & 0x0ffful);
  126. point.u32Y = ((value >> 16) & 0x0ffful);
  127. value = inpw(REG_ADC_ZDATA);
  128. point.u32Z0 = (value & 0x0ffful);
  129. point.u32Z1 = ((value >> 16) & 0x0ffful);
  130. /* Trigger next or not. */
  131. if (point.u32Z0 == 0)
  132. {
  133. /* Stop sampling procedure. */
  134. rt_timer_stop(g_sNuADC.psRtTouchMenuTimer);
  135. /* Re-start pendown detection */
  136. nu_adc_touch_detect(RT_TRUE);
  137. bDrop = RT_TRUE;
  138. }
  139. else
  140. {
  141. bDrop = RT_FALSE;
  142. }
  143. /* Notify upper layer. */
  144. if ((!bDrop || (u32LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK)
  145. {
  146. rt_hw_touch_isr(psNuAdc->psRtTouch);
  147. }
  148. u32LastZ0 = point.u32Z0;
  149. }
  150. else
  151. #endif
  152. {
  153. rt_err_t result = rt_sem_release(psNuAdc->m_psSem);
  154. RT_ASSERT(result == RT_EOK);
  155. }
  156. return 0;
  157. }
  158. #if defined(BSP_USING_ADC_TOUCH)
  159. void nu_adc_touch_detect(rt_bool_t bStartDetect)
  160. {
  161. nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC;
  162. if (bStartDetect)
  163. {
  164. /* Start detect PenDown */
  165. _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_ON, RT_NULL);
  166. }
  167. else
  168. {
  169. /* Stop detect PenDown */
  170. _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_OFF, RT_NULL);
  171. }
  172. }
  173. static int32_t PenDownCallback(uint32_t status, uint32_t userData)
  174. {
  175. nu_adc_touch_detect(RT_FALSE);
  176. rt_timer_start(g_sNuADC.psRtTouchMenuTimer);
  177. return 0;
  178. }
  179. int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt)
  180. {
  181. int i;
  182. struct nu_adc_touch_data value;
  183. for (i = 0 ; i < dataCnt; i++)
  184. {
  185. if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT)
  186. break;
  187. bufX[i] = value.u32X;
  188. bufY[i] = value.u32Y;
  189. bufZ0[i] = value.u32Z0;
  190. bufZ1[i] = value.u32Z1;
  191. }
  192. return i;
  193. }
  194. void nu_adc_touch_start_conv(void)
  195. {
  196. nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC;
  197. _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL);
  198. }
  199. rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch)
  200. {
  201. nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC;
  202. nu_adc_cb sNuAdcCb;
  203. rt_adc_enable((rt_adc_device_t)psNuAdc, 4);
  204. rt_adc_enable((rt_adc_device_t)psNuAdc, 5);
  205. rt_adc_enable((rt_adc_device_t)psNuAdc, 6);
  206. rt_adc_enable((rt_adc_device_t)psNuAdc, 7);
  207. outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24);
  208. /* Register touch device. */
  209. psNuAdc->psRtTouch = psRtTouch;
  210. /* Enable TouchXY. */
  211. _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL);
  212. /* Enable TouchZZ. */
  213. _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL);
  214. /* Register PenDown callback. */
  215. sNuAdcCb.cbfunc = PenDownCallback;
  216. sNuAdcCb.private_data = (rt_uint32_t)psRtTouch;
  217. _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb);
  218. nu_adc_touch_detect(RT_TRUE);
  219. return RT_EOK;
  220. }
  221. rt_err_t nu_adc_touch_disable(void)
  222. {
  223. nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC;
  224. nu_adc_touch_detect(RT_FALSE);
  225. _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL);
  226. _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL);
  227. _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL);
  228. rt_adc_disable((rt_adc_device_t)psNuAdc, 4);
  229. rt_adc_disable((rt_adc_device_t)psNuAdc, 5);
  230. rt_adc_disable((rt_adc_device_t)psNuAdc, 6);
  231. rt_adc_disable((rt_adc_device_t)psNuAdc, 7);
  232. return RT_EOK;
  233. }
  234. #endif
  235. static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args)
  236. {
  237. rt_err_t ret = RT_EINVAL ;
  238. nu_adc_t psNuAdc = (nu_adc_t)dev;
  239. nu_adc_cb_t psAdcCb = (nu_adc_cb_t)args;
  240. switch (cmd)
  241. {
  242. case START_MST: /* Menu Start Conversion */
  243. {
  244. /* Enable interrupt */
  245. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN);
  246. /* Start conversion */
  247. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST);
  248. /* Wait it done */
  249. ret = rt_sem_take(psNuAdc->m_psSem, RT_WAITING_FOREVER);
  250. RT_ASSERT(ret == RT_EOK);
  251. /* Get data: valid data is 12-bit */
  252. if (args != RT_NULL)
  253. *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF;
  254. }
  255. break;
  256. /* case START_MST_POLLING: Not supported. */
  257. case VBPOWER_ON: /* Enable ADC Internal Bandgap Power */
  258. {
  259. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_VBGEN);
  260. }
  261. break;
  262. case VBPOWER_OFF: /* Disable ADC Internal Bandgap Power */
  263. {
  264. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_VBGEN);
  265. }
  266. break;
  267. case KPPOWER_ON: /* Enable ADC Keypad Power */
  268. {
  269. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PWKPEN);
  270. }
  271. break;
  272. case KPPOWER_OFF: /* Disable ADC Keypad Power */
  273. {
  274. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PWKPEN);
  275. }
  276. break;
  277. case PEPOWER_ON: /* Enable Pen Power */
  278. {
  279. int retry = 100;
  280. uint32_t treg = inpw(REG_ADC_IER);
  281. outpw(REG_ADC_IER, treg & ~(ADC_IER_PEDEIEN | ADC_IER_PEUEIEN));
  282. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PEDEEN);
  283. do
  284. {
  285. outpw(REG_ADC_ISR, ADC_ISR_PEDEF | ADC_ISR_PEUEF);
  286. rt_thread_mdelay(1);
  287. if (retry-- == 0)
  288. break;
  289. }
  290. while (inpw(REG_ADC_ISR) & (ADC_ISR_PEDEF | ADC_ISR_PEUEF));
  291. outpw(REG_ADC_IER, treg);
  292. }
  293. break;
  294. case PEPOWER_OFF: /* Disable Pen Power */
  295. {
  296. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PEDEEN);
  297. }
  298. break;
  299. case KPPRESS_ON: /* Enable Keypad press event */
  300. {
  301. if (psAdcCb)
  302. {
  303. rt_memcpy(&psNuAdc->m_isr[eAdc_KPEF], psAdcCb, sizeof(nu_adc_cb));
  304. }
  305. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN);
  306. }
  307. break;
  308. case KPPRESS_OFF: /* Disable Keypad press event */
  309. {
  310. outpw(REG_ADC_IER, inpw(REG_ADC_IER & ~ADC_IER_KPEIEN));
  311. }
  312. break;
  313. case KPUP_ON: /* Enable Keypad up event */
  314. {
  315. if (psAdcCb)
  316. {
  317. rt_memcpy(&psNuAdc->m_isr[eAdc_KPUEF], psAdcCb, sizeof(nu_adc_cb));
  318. }
  319. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPUEIEN);
  320. }
  321. break;
  322. case KPUP_OFF: /* Disable Keypad up event */
  323. {
  324. outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_KPUEIEN);
  325. }
  326. break;
  327. case PEDEF_ON: /* Enable Pen Down Event */
  328. {
  329. if (psAdcCb)
  330. {
  331. rt_memcpy(&psNuAdc->m_isr[eAdc_PEDEF], psAdcCb, sizeof(nu_adc_cb));
  332. }
  333. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_PEDEIEN);
  334. }
  335. break;
  336. case PEDEF_OFF: /* Disable Pen Down Event */
  337. {
  338. outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_PEDEIEN);
  339. }
  340. break;
  341. case WKP_ON: /* Enable Keypad Press Wake Up */
  342. {
  343. if (psAdcCb)
  344. {
  345. rt_memcpy(&psNuAdc->m_wkisr[eAdc_WKPEF], psAdcCb, sizeof(nu_adc_cb));
  346. }
  347. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKPEN);
  348. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKPIEN);
  349. outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26));
  350. }
  351. break;
  352. case WKP_OFF: /* Disable Keypad Press Wake Up */
  353. {
  354. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKPEN);
  355. outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKPIEN);
  356. outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26));
  357. }
  358. break;
  359. case WKT_ON: /* Enable Touch Wake Up */
  360. {
  361. if (psAdcCb)
  362. {
  363. rt_memcpy(&psNuAdc->m_wkisr[eAdc_WPEDEF], psAdcCb, sizeof(nu_adc_cb));
  364. }
  365. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKTEN);
  366. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKTIEN);
  367. outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26));
  368. }
  369. break;
  370. case WKT_OFF: /* Disable Touch Wake Up */
  371. {
  372. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKTEN);
  373. outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKTIEN);
  374. outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26));
  375. }
  376. break;
  377. case SWITCH_5WIRE_ON: /* Wire Mode Switch to 5-Wire */
  378. {
  379. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WMSWCH);
  380. }
  381. break;
  382. case SWITCH_5WIRE_OFF: /* Wire Mode Switch to 4-Wire */
  383. {
  384. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WMSWCH);
  385. }
  386. break;
  387. case T_ON: /* Enable Touch detection function */
  388. {
  389. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_TEN);
  390. }
  391. break;
  392. case T_OFF: /* Disable Touch detection function */
  393. {
  394. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_TEN);
  395. }
  396. break;
  397. case TAVG_ON: /* Enable Touch Mean average for X and Y function */
  398. {
  399. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISTMAVEN);
  400. }
  401. break;
  402. case TAVG_OFF: /* Disable Touch Mean average for X and Y function */
  403. {
  404. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISTMAVEN);
  405. }
  406. break;
  407. case Z_ON: /* Enable Press measure function */
  408. {
  409. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_ZEN);
  410. }
  411. break;
  412. case Z_OFF: /* Disable Press measure function */
  413. {
  414. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN);
  415. #if defined(BSP_USING_ADC_TOUCH)
  416. rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL);
  417. #endif
  418. }
  419. break;
  420. case TZAVG_ON: /* Enable Pressure Mean average for Z1 and Z2 function */
  421. {
  422. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISZMAVEN);
  423. }
  424. break;
  425. case TZAVG_OFF: /* Disable Pressure Mean average for Z1 and Z2 function */
  426. {
  427. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISZMAVEN);
  428. }
  429. break;
  430. case NAC_ON: /* Enable Normal AD Conversion */
  431. {
  432. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_NACEN | ADC_CONF_REFSEL_AVDD33);
  433. }
  434. break;
  435. case NAC_OFF: /* Disable Normal AD Conversion */
  436. {
  437. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_NACEN);
  438. }
  439. break;
  440. case VBAT_ON: /* Enable Voltage Battery Conversion */
  441. {
  442. if (psAdcCb)
  443. {
  444. rt_memcpy(&psNuAdc->m_isr[eAdc_VBF], psAdcCb, sizeof(nu_adc_cb));
  445. }
  446. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_VBATEN);
  447. }
  448. break;
  449. case VBAT_OFF: /* Disable Voltage Battery */
  450. {
  451. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_VBATEN);
  452. }
  453. break;
  454. case KPCONV_ON: /* Enable Keypad conversion function */
  455. {
  456. if (psAdcCb)
  457. {
  458. rt_memcpy(&psNuAdc->m_isr[eAdc_KPCF], psAdcCb, sizeof(nu_adc_cb));
  459. }
  460. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_KPCEN);
  461. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN);
  462. }
  463. break;
  464. case KPCONV_OFF: /* Disable Keypad conversion function */
  465. {
  466. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_KPCEN);
  467. }
  468. break;
  469. case SWITCH_CH:
  470. {
  471. int chn = (int)args;
  472. if (chn >= psNuAdc->chn_num)
  473. {
  474. return -ret;
  475. }
  476. outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~ADC_CONF_CHSEL_Msk) | (chn << ADC_CONF_CHSEL_Pos));
  477. }
  478. break;
  479. default:
  480. return -(ret);
  481. }
  482. return RT_EOK;
  483. }
  484. static rt_err_t _nu_adc_open(rt_device_t dev, rt_uint16_t oflag)
  485. {
  486. nu_adc_t psNuAdc = (nu_adc_t)dev;
  487. /* Enable ADC engine clock */
  488. nu_sys_ipclk_enable(psNuAdc->clkidx);
  489. /* Reset the ADC IP */
  490. nu_sys_ip_reset(psNuAdc->rstidx);
  491. /* Enable ADC Power */
  492. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_ADEN);
  493. /* Enable ADC to high speed mode */
  494. outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_HSPEED);
  495. /* Enable interrupt */
  496. rt_hw_interrupt_umask(psNuAdc->irqn);
  497. /* Enable Normal AD Conversion */
  498. _nu_adc_control(dev, NAC_ON, RT_NULL);
  499. return RT_EOK;
  500. }
  501. static rt_err_t _nu_adc_close(rt_device_t dev)
  502. {
  503. nu_adc_t psNuAdc = (nu_adc_t)dev;
  504. /* Disable Normal AD Conversion */
  505. _nu_adc_control(dev, NAC_OFF, RT_NULL);
  506. /* Disable interrupt */
  507. rt_hw_interrupt_mask(psNuAdc->irqn);
  508. /* Disable ADC Power */
  509. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_ADEN);
  510. /* Disable ADC engine clock */
  511. nu_sys_ipclk_disable(psNuAdc->clkidx);
  512. return RT_EOK;
  513. }
  514. static const struct rt_adc_ops nu_adc_ops =
  515. {
  516. nu_adc_enabled,
  517. nu_adc_convert,
  518. };
  519. /* nu_adc_enabled - Enable ADC clock and wait for ready */
  520. static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  521. {
  522. nu_adc_t psNuADC = (nu_adc_t)device;
  523. RT_ASSERT(device != RT_NULL);
  524. if (channel >= psNuADC->chn_num)
  525. return -(RT_EINVAL);
  526. if (enabled)
  527. {
  528. psNuADC->chn_mask |= (1 << channel);
  529. }
  530. else
  531. {
  532. psNuADC->chn_mask &= ~(1 << channel);
  533. }
  534. if (psNuADC->chn_mask > 0 && ((rt_device_t)device)->ref_count == 0)
  535. {
  536. _nu_adc_open((rt_device_t)device, 0);
  537. ((rt_device_t)device)->ref_count = 1;
  538. }
  539. else if ((psNuADC->chn_mask == 0) && ((rt_device_t)device)->ref_count == 1)
  540. {
  541. _nu_adc_close((rt_device_t)device);
  542. ((rt_device_t)device)->ref_count = 0;
  543. }
  544. return RT_EOK;
  545. }
  546. static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  547. {
  548. rt_err_t ret = RT_EOK;
  549. nu_adc_t psNuAdc = (nu_adc_t)device;
  550. RT_ASSERT(device != RT_NULL);
  551. RT_ASSERT(value != RT_NULL);
  552. if (channel >= psNuAdc->chn_num)
  553. {
  554. ret = RT_EINVAL;
  555. goto exit_nu_adc_convert;
  556. }
  557. else if ((ret = _nu_adc_control((rt_device_t)device, SWITCH_CH, (void *)channel)) != RT_EOK)
  558. {
  559. goto exit_nu_adc_convert;
  560. }
  561. else if ((ret = _nu_adc_control((rt_device_t)device, START_MST, (void *)value)) != RT_EOK)
  562. {
  563. goto exit_nu_adc_convert;
  564. }
  565. exit_nu_adc_convert:
  566. return (-ret) ;
  567. }
  568. #if defined(BSP_USING_ADC_TOUCH)
  569. static void nu_adc_touch_smpl(void *p)
  570. {
  571. /* Enable interrupt */
  572. outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN);
  573. /* Start conversion */
  574. outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST);
  575. }
  576. #endif
  577. int rt_hw_adc_init(void)
  578. {
  579. rt_err_t result = RT_ERROR;
  580. rt_device_t psDev = &g_sNuADC.dev.parent;
  581. result = rt_hw_adc_register(&g_sNuADC.dev, g_sNuADC.name, &nu_adc_ops, &g_sNuADC);
  582. RT_ASSERT(result == RT_EOK);
  583. result = _nu_adc_init(psDev);
  584. RT_ASSERT(result == RT_EOK);
  585. g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO);
  586. RT_ASSERT(g_sNuADC.m_psSem != RT_NULL);
  587. #if defined(BSP_USING_ADC_TOUCH)
  588. g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO);
  589. RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL);
  590. g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC);
  591. RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL);
  592. #endif
  593. rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr));
  594. rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr));
  595. g_sNuADC.m_isr[eAdc_MF].cbfunc = AdcMenuStartCallback;
  596. g_sNuADC.m_isr[eAdc_MF].private_data = (UINT32)&g_sNuADC;
  597. return (int)result;
  598. }
  599. INIT_BOARD_EXPORT(rt_hw_adc_init);
  600. #endif //#if defined(BSP_USING_ADC)