drv_adc.c 19 KB

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