em_lcd.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Liquid Crystal Display (LCD) Peripheral API
  4. * @author Energy Micro AS
  5. * @version 3.0.0
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * Permission is granted to anyone to use this software for any purpose,
  12. * including commercial applications, and to alter it and redistribute it
  13. * freely, subject to the following restrictions:
  14. *
  15. * 1. The origin of this software must not be misrepresented; you must not
  16. * claim that you wrote the original software.
  17. * 2. Altered source versions must be plainly marked as such, and must not be
  18. * misrepresented as being the original software.
  19. * 3. This notice may not be removed or altered from any source distribution.
  20. *
  21. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  22. * obligation to support this Software. Energy Micro AS is providing the
  23. * Software "AS IS", with no express or implied warranties of any kind,
  24. * including, but not limited to, any implied warranties of merchantability
  25. * or fitness for any particular purpose or warranties against infringement
  26. * of any proprietary rights of a third party.
  27. *
  28. * Energy Micro AS will not be liable for any consequential, incidental, or
  29. * special damages, or any other relief, or for any claim by any third party,
  30. * arising from your use of this Software.
  31. *
  32. ******************************************************************************/
  33. #include "em_lcd.h"
  34. #if defined(LCD_COUNT) && (LCD_COUNT > 0)
  35. #include "em_assert.h"
  36. #include "em_bitband.h"
  37. /***************************************************************************//**
  38. * @addtogroup EM_Library
  39. * @{
  40. ******************************************************************************/
  41. /***************************************************************************//**
  42. * @addtogroup LCD
  43. * @brief Liquid Crystal Display (LCD) Peripheral API
  44. * @{
  45. ******************************************************************************/
  46. /***************************************************************************//**
  47. * @brief
  48. * Initalize Liquid Crystal Display (LCD) controller
  49. *
  50. * @details
  51. * This function call will only configure the LCD controller. You must enable
  52. * it afterwards, potentially configuring Frame Control and interrupts first
  53. * according to requirements.
  54. *
  55. * @param[in] lcdInit
  56. * Pointer to initialization structure which configures LCD controller.
  57. *
  58. ******************************************************************************/
  59. void LCD_Init(const LCD_Init_TypeDef *lcdInit)
  60. {
  61. uint32_t dispCtrl = LCD->DISPCTRL;
  62. EFM_ASSERT(lcdInit != (void *) 0);
  63. /* Disable controller before reconfiguration */
  64. LCD_Enable(false);
  65. /* Make sure we don't touch other bit fields (i.e. voltage boost) */
  66. dispCtrl &= ~(
  67. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  68. _LCD_DISPCTRL_MUXE_MASK |
  69. #endif
  70. _LCD_DISPCTRL_MUX_MASK |
  71. _LCD_DISPCTRL_BIAS_MASK |
  72. _LCD_DISPCTRL_WAVE_MASK |
  73. _LCD_DISPCTRL_VLCDSEL_MASK |
  74. _LCD_DISPCTRL_CONCONF_MASK);
  75. /* Configure controller according to initialization structure */
  76. dispCtrl |= lcdInit->mux; /* also configures MUXE */
  77. dispCtrl |= lcdInit->bias;
  78. dispCtrl |= lcdInit->wave;
  79. dispCtrl |= lcdInit->vlcd;
  80. dispCtrl |= lcdInit->contrast;
  81. /* Update display controller */
  82. LCD->DISPCTRL = dispCtrl;
  83. /* Enable controller if wanted */
  84. if (lcdInit->enable)
  85. {
  86. LCD_Enable(true);
  87. }
  88. }
  89. /***************************************************************************//**
  90. * @brief
  91. * Select source for VLCD
  92. *
  93. * @param[in] vlcd
  94. * Select source for VLD voltage
  95. ******************************************************************************/
  96. void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd)
  97. {
  98. uint32_t dispctrl = LCD->DISPCTRL;
  99. /* Select VEXT or VDD */
  100. dispctrl &= ~(_LCD_DISPCTRL_VLCDSEL_MASK);
  101. switch (vlcd)
  102. {
  103. case lcdVLCDSelVExtBoost:
  104. dispctrl |= LCD_DISPCTRL_VLCDSEL_VEXTBOOST;
  105. break;
  106. case lcdVLCDSelVDD:
  107. dispctrl |= LCD_DISPCTRL_VLCDSEL_VDD;
  108. break;
  109. default:
  110. break;
  111. }
  112. LCD->DISPCTRL = dispctrl;
  113. }
  114. /***************************************************************************//**
  115. * @brief
  116. * Configure Update Control
  117. *
  118. * @param[in] ud
  119. * Configures LCD update method
  120. ******************************************************************************/
  121. void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud)
  122. {
  123. LCD->CTRL = (LCD->CTRL & ~_LCD_CTRL_UDCTRL_MASK) | ud;
  124. }
  125. /***************************************************************************//**
  126. * @brief
  127. * Initialize LCD Frame Counter
  128. *
  129. * @param[in] fcInit
  130. * Pointer to Frame Counter initialization structure
  131. ******************************************************************************/
  132. void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit)
  133. {
  134. uint32_t bactrl = LCD->BACTRL;
  135. EFM_ASSERT(fcInit != (void *) 0);
  136. /* Verify FC Top Counter to be within limits */
  137. EFM_ASSERT(fcInit->top < 64);
  138. /* Reconfigure frame count configuration */
  139. bactrl &= ~(_LCD_BACTRL_FCTOP_MASK |
  140. _LCD_BACTRL_FCPRESC_MASK);
  141. bactrl |= (fcInit->top << _LCD_BACTRL_FCTOP_SHIFT);
  142. bactrl |= fcInit->prescale;
  143. /* Set Blink and Animation Control Register */
  144. LCD->BACTRL = bactrl;
  145. LCD_FrameCountEnable(fcInit->enable);
  146. }
  147. /***************************************************************************//**
  148. * @brief
  149. * Configures LCD controller Animation feature
  150. *
  151. * @param[in] animInit
  152. * Pointer to LCD Animation initialization structure
  153. ******************************************************************************/
  154. void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)
  155. {
  156. uint32_t bactrl = LCD->BACTRL;
  157. EFM_ASSERT(animInit != (void *) 0);
  158. /* Set Animation Register Values */
  159. LCD->AREGA = animInit->AReg;
  160. LCD->AREGB = animInit->BReg;
  161. /* Configure Animation Shift and Logic */
  162. bactrl &= ~(_LCD_BACTRL_AREGASC_MASK |
  163. _LCD_BACTRL_AREGBSC_MASK |
  164. _LCD_BACTRL_ALOGSEL_MASK);
  165. bactrl |= (animInit->AShift << _LCD_BACTRL_AREGASC_SHIFT);
  166. bactrl |= (animInit->BShift << _LCD_BACTRL_AREGBSC_SHIFT);
  167. bactrl |= animInit->animLogic;
  168. #if defined(_EFM32_GIANT_FAMILY)
  169. if(animInit->startSeg == 0)
  170. {
  171. bactrl |= LCD_BACTRL_ALOC_SEG0TO7;
  172. }
  173. else if(animInit->startSeg == 8)
  174. {
  175. bactrl |= LCD_BACTRL_ALOC_SEG8TO15;
  176. }
  177. #endif
  178. /* Reconfigure */
  179. LCD->BACTRL = bactrl;
  180. /* Enable */
  181. LCD_AnimEnable(animInit->enable);
  182. }
  183. /***************************************************************************//**
  184. * @brief
  185. * Enables update of this range of LCD segment lines
  186. *
  187. * @param[in] segmentRange
  188. * Range of 4 LCD segments lines to enable or disable, for all enabled COM
  189. * lines
  190. *
  191. * @param[in] enable
  192. * Bool true to enable segment updates, false to disable updates
  193. ******************************************************************************/
  194. void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segmentRange, bool enable)
  195. {
  196. if (enable)
  197. {
  198. LCD->SEGEN |= segmentRange;
  199. }
  200. else
  201. {
  202. LCD->SEGEN &= ~((uint32_t)segmentRange);
  203. }
  204. }
  205. /***************************************************************************//**
  206. * @brief
  207. * Turn on or clear a segment
  208. *
  209. * @note
  210. * On Gecko Family, max configuration is (COM-lines x Segment-Lines) 4x40
  211. * On Tiny Family, max configuration is 8x20 or 4x24
  212. * On Giant Family, max configuration is 8x36 or 4x40
  213. *
  214. * @param[in] com
  215. * COM line to change
  216. *
  217. * @param[in] bit
  218. * Bit index of which field to change
  219. *
  220. * @param[in] enable
  221. * When true will set segment, when false will clear segment
  222. ******************************************************************************/
  223. void LCD_SegmentSet(int com, int bit, bool enable)
  224. {
  225. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  226. /* Tiny and Giant Family supports up to 8 COM lines */
  227. EFM_ASSERT(com < 8);
  228. #else
  229. /* Gecko Family supports up to 4 COM lines */
  230. EFM_ASSERT(com < 4);
  231. #endif
  232. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  233. EFM_ASSERT(bit < 40);
  234. #else
  235. /* Tiny Gecko Family supports only "low" segment registers */
  236. EFM_ASSERT(bit < 32);
  237. #endif
  238. /* Use bitband access for atomic bit set/clear of segment */
  239. switch (com)
  240. {
  241. case 0:
  242. if (bit < 32)
  243. {
  244. BITBAND_Peripheral(&(LCD->SEGD0L), bit, (unsigned int)enable);
  245. }
  246. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  247. else
  248. {
  249. bit -= 32;
  250. BITBAND_Peripheral(&(LCD->SEGD0H), bit, (unsigned int)enable);
  251. }
  252. #endif
  253. break;
  254. case 1:
  255. if (bit < 32)
  256. {
  257. BITBAND_Peripheral(&(LCD->SEGD1L), bit, (unsigned int)enable);
  258. }
  259. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  260. else
  261. {
  262. bit -= 32;
  263. BITBAND_Peripheral(&(LCD->SEGD1H), bit, (unsigned int)enable);
  264. }
  265. #endif
  266. break;
  267. case 2:
  268. if (bit < 32)
  269. {
  270. BITBAND_Peripheral(&(LCD->SEGD2L), bit, (unsigned int)enable);
  271. }
  272. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  273. else
  274. {
  275. bit -= 32;
  276. BITBAND_Peripheral(&(LCD->SEGD2H), bit, (unsigned int)enable);
  277. }
  278. #endif
  279. break;
  280. case 3:
  281. if (bit < 32)
  282. {
  283. BITBAND_Peripheral(&(LCD->SEGD3L), bit, (unsigned int)enable);
  284. }
  285. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  286. else
  287. {
  288. bit -= 32;
  289. BITBAND_Peripheral(&(LCD->SEGD3H), bit, (unsigned int)enable);
  290. }
  291. #endif
  292. break;
  293. case 4:
  294. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  295. if (bit < 32)
  296. {
  297. BITBAND_Peripheral(&(LCD->SEGD4L), bit, (unsigned int)enable);
  298. }
  299. #endif
  300. #if defined(_EFM32_GIANT_FAMILY)
  301. else
  302. {
  303. bit -= 32;
  304. BITBAND_Peripheral(&(LCD->SEGD4H), bit, (unsigned int)enable);
  305. }
  306. #endif
  307. break;
  308. case 5:
  309. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  310. if (bit < 32)
  311. {
  312. BITBAND_Peripheral(&(LCD->SEGD5L), bit, (unsigned int)enable);
  313. }
  314. #endif
  315. #if defined(_EFM32_GIANT_FAMILY)
  316. else
  317. {
  318. bit -= 32;
  319. BITBAND_Peripheral(&(LCD->SEGD5H), bit, (unsigned int)enable);
  320. }
  321. #endif
  322. break;
  323. case 6:
  324. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  325. if (bit < 32)
  326. {
  327. BITBAND_Peripheral(&(LCD->SEGD6L), bit, (unsigned int)enable);
  328. }
  329. #endif
  330. #if defined(_EFM32_GIANT_FAMILY)
  331. else
  332. {
  333. bit -= 32;
  334. BITBAND_Peripheral(&(LCD->SEGD6H), bit, (unsigned int)enable);
  335. }
  336. #endif
  337. break;
  338. case 7:
  339. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  340. if (bit < 32)
  341. {
  342. BITBAND_Peripheral(&(LCD->SEGD7L), bit, (unsigned int)enable);
  343. }
  344. #endif
  345. #if defined(_EFM32_GIANT_FAMILY)
  346. else
  347. {
  348. bit -= 32;
  349. BITBAND_Peripheral(&(LCD->SEGD7H), bit, (unsigned int)enable);
  350. }
  351. #endif
  352. break;
  353. default:
  354. EFM_ASSERT(0);
  355. break;
  356. }
  357. }
  358. /***************************************************************************//**
  359. * @brief
  360. * Updates the 0-31 lowest segments on a given COM-line in one operation,
  361. * according to bit mask
  362. *
  363. * @param[in] com
  364. * Which COM line to update
  365. *
  366. * @param[in] mask
  367. * Bit mask for segments 0-31
  368. *
  369. * @param[in] bits
  370. * Bit pattern for segments 0-31
  371. ******************************************************************************/
  372. void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)
  373. {
  374. uint32_t segData;
  375. /* Maximum number of com lines */
  376. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  377. EFM_ASSERT(com < 8);
  378. #else
  379. /* Gecko Family supports up to 4 COM lines */
  380. EFM_ASSERT(com < 4);
  381. #endif
  382. switch (com)
  383. {
  384. case 0:
  385. segData = LCD->SEGD0L;
  386. segData &= ~(mask);
  387. segData |= (mask & bits);
  388. LCD->SEGD0L = segData;
  389. break;
  390. case 1:
  391. segData = LCD->SEGD1L;
  392. segData &= ~(mask);
  393. segData |= (mask & bits);
  394. LCD->SEGD1L = segData;
  395. break;
  396. case 2:
  397. segData = LCD->SEGD2L;
  398. segData &= ~(mask);
  399. segData |= (mask & bits);
  400. LCD->SEGD2L = segData;
  401. break;
  402. case 3:
  403. segData = LCD->SEGD3L;
  404. segData &= ~(mask);
  405. segData |= (mask & bits);
  406. LCD->SEGD3L = segData;
  407. break;
  408. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  409. case 4:
  410. segData = LCD->SEGD4L;
  411. segData &= ~(mask);
  412. segData |= (mask & bits);
  413. LCD->SEGD4L = segData;
  414. break;
  415. #endif
  416. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  417. case 5:
  418. segData = LCD->SEGD5L;
  419. segData &= ~(mask);
  420. segData |= (mask & bits);
  421. LCD->SEGD5L = segData;
  422. break;
  423. #endif
  424. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  425. case 6:
  426. segData = LCD->SEGD6L;
  427. segData &= ~(mask);
  428. segData |= (mask & bits);
  429. LCD->SEGD6L = segData;
  430. break;
  431. #endif
  432. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  433. case 7:
  434. segData = LCD->SEGD7L;
  435. segData &= ~(mask);
  436. segData |= (mask & bits);
  437. LCD->SEGD7L = segData;
  438. break;
  439. #endif
  440. default:
  441. EFM_ASSERT(0);
  442. break;
  443. }
  444. }
  445. #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  446. /***************************************************************************//**
  447. * @brief
  448. * Updated the high (32-39) segments on a given COM-line in one operation
  449. *
  450. * @param[in] com
  451. * Which COM line to update
  452. *
  453. * @param[in] mask
  454. * Bit mask for segments 32-39
  455. *
  456. * @param[in] bits
  457. * Bit pattern for segments 32-39
  458. ******************************************************************************/
  459. void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)
  460. {
  461. uint32_t segData;
  462. #if defined(_EFM32_GIANT_FAMILY)
  463. EFM_ASSERT(com < 8);
  464. #endif
  465. #if defined(_EFM32_GECKO_FAMILY)
  466. EFM_ASSERT(com < 4);
  467. #endif
  468. /* Maximum number of com lines */
  469. switch (com)
  470. {
  471. case 0:
  472. segData = LCD->SEGD0H;
  473. segData &= ~(mask);
  474. segData |= (mask & bits);
  475. LCD->SEGD0H = segData;
  476. break;
  477. case 1:
  478. segData = LCD->SEGD1H;
  479. segData &= ~(mask);
  480. segData |= (mask & bits);
  481. LCD->SEGD1H = segData;
  482. break;
  483. case 2:
  484. segData = LCD->SEGD2H;
  485. segData &= ~(mask);
  486. segData |= (mask & bits);
  487. LCD->SEGD2H = segData;
  488. break;
  489. case 3:
  490. segData = LCD->SEGD3H;
  491. segData &= ~(mask);
  492. segData |= (mask & bits);
  493. LCD->SEGD3H = segData;
  494. break;
  495. #if defined(_EFM32_GIANT_FAMILY)
  496. case 4:
  497. segData = LCD->SEGD4H;
  498. segData &= ~(mask);
  499. segData |= (mask & bits);
  500. LCD->SEGD4H = segData;
  501. break;
  502. #endif
  503. #if defined(_EFM32_GIANT_FAMILY)
  504. case 5:
  505. segData = LCD->SEGD5H;
  506. segData &= ~(mask);
  507. segData |= (mask & bits);
  508. LCD->SEGD5H = segData;
  509. break;
  510. #endif
  511. #if defined(_EFM32_GIANT_FAMILY)
  512. case 6:
  513. segData = LCD->SEGD6H;
  514. segData &= ~(mask);
  515. segData |= (mask & bits);
  516. LCD->SEGD6H = segData;
  517. break;
  518. #endif
  519. #if defined(_EFM32_GIANT_FAMILY)
  520. case 7:
  521. segData = LCD->SEGD7H;
  522. segData &= ~(mask);
  523. segData |= (mask & bits);
  524. LCD->SEGD7H = segData;
  525. break;
  526. #endif
  527. default:
  528. break;
  529. }
  530. }
  531. #endif
  532. /***************************************************************************//**
  533. * @brief
  534. * Configure contrast level on LCD panel
  535. *
  536. * @param[in] level
  537. * Contrast level in the range 0-31
  538. ******************************************************************************/
  539. void LCD_ContrastSet(int level)
  540. {
  541. EFM_ASSERT(level < 32);
  542. LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_CONLEV_MASK)
  543. | (level << _LCD_DISPCTRL_CONLEV_SHIFT);
  544. }
  545. /***************************************************************************//**
  546. * @brief
  547. * Configure voltage booster
  548. *
  549. * The resulting voltage level is described in each part number's data sheet
  550. *
  551. * @param[in] vboost
  552. * Voltage boost level
  553. ******************************************************************************/
  554. void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost)
  555. {
  556. /* Reconfigure Voltage Boost */
  557. LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_VBLEV_MASK) | vboost;
  558. }
  559. #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY)
  560. /***************************************************************************//**
  561. * @brief
  562. * Configure bias level for a specific segment line for Direct Segment Control
  563. *
  564. * @note
  565. * When DSC is active, each configuration takes up 4 bits in the Segment
  566. * Registers (SEGD0L/SEGD1H) which defines bias level.
  567. * For optimal use of this feature, the entire SEGD-registers should be set
  568. * at once in a optimized routine, so this function is mainly here to
  569. * demonstrate how to correctly configure the bias levels, and should be used
  570. * with care.
  571. *
  572. * @param[in] segmentLine
  573. * Segment line number
  574. *
  575. * @param[in] biasLevel
  576. * Bias configuration level, 0-4. This value must be within the constraint
  577. * defined by the LCD_DISPCTRL bias setting, see Reference Manual/Datasheet
  578. ******************************************************************************/
  579. void LCD_BiasSegmentSet(int segmentLine, int biasLevel)
  580. {
  581. int biasRegister;
  582. int bitShift;
  583. volatile uint32_t *segmentRegister;
  584. #if defined(_EFM32_TINY_FAMILY)
  585. EFM_ASSERT(segmentLine < 20);
  586. #endif
  587. #if defined(_EFM32_GIANT_FAMILY)
  588. EFM_ASSERT(segmentLine < 40);
  589. #endif
  590. #if defined(_EFM32_TINY_FAMILY)
  591. /* Bias config for 8 segment lines per SEGDnL register */
  592. biasRegister = segmentLine / 8;
  593. bitShift = (segmentLine % 8) * 4;
  594. switch (biasRegister)
  595. {
  596. case 0:
  597. segmentRegister = &LCD->SEGD0L;
  598. break;
  599. case 1:
  600. segmentRegister = &LCD->SEGD1L;
  601. break;
  602. case 2:
  603. segmentRegister = &LCD->SEGD2L;
  604. break;
  605. case 3:
  606. segmentRegister = &LCD->SEGD3L;
  607. break;
  608. default:
  609. segmentRegister = (uint32_t *)0x00000000;
  610. EFM_ASSERT(0);
  611. break;
  612. }
  613. #endif
  614. #if defined(_EFM32_GIANT_FAMILY)
  615. /* Bias config for 10 segment lines per SEGDn L+H registers */
  616. biasRegister = segmentLine / 10;
  617. bitShift = (segmentLine % 10) * 4;
  618. switch (biasRegister)
  619. {
  620. case 0:
  621. if (bitShift < 32)
  622. {
  623. segmentRegister = &LCD->SEGD0L;
  624. }
  625. else
  626. {
  627. segmentRegister = &LCD->SEGD0H;
  628. bitShift -= 32;
  629. }
  630. break;
  631. case 1:
  632. if (bitShift < 32)
  633. {
  634. segmentRegister = &LCD->SEGD1L;
  635. }
  636. else
  637. {
  638. segmentRegister = &LCD->SEGD1H;
  639. bitShift -= 32;
  640. }
  641. break;
  642. case 2:
  643. if (bitShift < 32)
  644. {
  645. segmentRegister = &LCD->SEGD2L;
  646. }
  647. else
  648. {
  649. segmentRegister = &LCD->SEGD1H;
  650. bitShift -= 32;
  651. }
  652. break;
  653. case 3:
  654. if (bitShift < 32)
  655. {
  656. segmentRegister = &LCD->SEGD3L;
  657. }
  658. else
  659. {
  660. segmentRegister = &LCD->SEGD3H;
  661. bitShift -= 32;
  662. }
  663. break;
  664. default:
  665. segmentRegister = (uint32_t *)0x00000000;
  666. EFM_ASSERT(0);
  667. break;
  668. }
  669. #endif
  670. /* Configure new bias setting */
  671. *segmentRegister = (*segmentRegister & ~(0xF << bitShift)) | (biasLevel << bitShift);
  672. }
  673. /***************************************************************************//**
  674. * @brief
  675. * Configure bias level for a specific segment line
  676. *
  677. * @note
  678. * When DSC is active, each configuration takes up 4 bits in the Segment
  679. * Registers (SEGD4L/SEGD4H) which defines bias level.
  680. * For optimal use of this feature, the entire SEGD-registers should be set
  681. * at once in a optimized routine, so this function is mainly here to
  682. * demonstrate how to correctly configure the bias levels, and should be used
  683. * with care.
  684. *
  685. * @param[in] comLine
  686. * COM line number, 0-7
  687. *
  688. * @param[in] biasLevel
  689. * Bias configuration level, 0-4. This value must be within the constraint
  690. * defined by the LCD_DISPCTRL bias setting, see Reference Manual/Datasheet
  691. ******************************************************************************/
  692. void LCD_BiasComSet(int comLine, int biasLevel)
  693. {
  694. int bitShift;
  695. EFM_ASSERT(comLine < 8);
  696. bitShift = comLine * 4;
  697. LCD->SEGD4L = (LCD->SEGD4L & ~(0xF << bitShift)) | (biasLevel << bitShift);
  698. }
  699. #endif
  700. /** @} (end addtogroup LCD) */
  701. /** @} (end addtogroup EM_Library) */
  702. #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */