00001
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <stdbool.h>
00039 #include "em_device.h"
00040 #include "em_cmu.h"
00041 #include "em_gpio.h"
00042
00043 #include "segmentlcd.h"
00044
00045
00067 typedef struct
00068 {
00069 uint8_t com[14];
00070 uint8_t bit[14];
00071 } CHAR_TypeDef;
00072
00073
00074
00077 typedef struct
00078 {
00079 uint8_t com[7];
00080 uint8_t bit[7];
00081 } NUMBER_TypeDef;
00082
00083
00086 typedef struct
00087 {
00088 uint8_t com[5];
00089 uint8_t bit[5];
00090 } EM_TypeDef;
00091
00092
00095 typedef struct
00096 {
00097 uint8_t com[8];
00098 uint8_t bit[8];
00099 } ARING_TypeDef;
00100
00101
00104 typedef struct
00105 {
00106 uint8_t com[4];
00107 uint8_t bit[4];
00108 } BATTERY_TypeDef;
00109
00110
00113 typedef struct
00114 {
00115 CHAR_TypeDef Text[7];
00116 NUMBER_TypeDef Number[4];
00117 EM_TypeDef EMode;
00118 ARING_TypeDef ARing;
00119 BATTERY_TypeDef Battery;
00120 } MCU_DISPLAY;
00121
00122
00125 static const MCU_DISPLAY EFM_Display = EFM_DISPLAY_DEF;
00126
00127
00128
00134 static const uint16_t EFM_Alphabet[] = {
00135 0x0000,
00136 0x1100,
00137 0x0280,
00138 0x0000,
00139 0x0000,
00140 0x0602,
00141 0x0000,
00142 0x0020,
00143 0x0039,
00144 0x000f,
00145 0x0000,
00146 0x1540,
00147 0x2000,
00148 0x0440,
00149 0x1000,
00150 0x2200,
00151
00152 0x003f,
00153 0x0006,
00154 0x045b,
00155 0x044f,
00156 0x0466,
00157 0x046d,
00158 0x047d,
00159 0x0007,
00160 0x047f,
00161 0x046f,
00162
00163 0x0000,
00164 0x0000,
00165 0x0a00,
00166 0x0000,
00167 0x2080,
00168 0x0000,
00169 0xffff,
00170
00171 0x0477,
00172 0x0a79,
00173 0x0039,
00174 0x20b0,
00175 0x0079,
00176 0x0071,
00177 0x047d,
00178 0x0476,
00179 0x0006,
00180 0x000e,
00181 0x0a70,
00182 0x0038,
00183 0x02b6,
00184 0x08b6,
00185 0x003f,
00186 0x0473,
00187 0x083f,
00188 0x0c73,
00189 0x046d,
00190 0x1101,
00191 0x003e,
00192 0x2230,
00193 0x2836,
00194 0x2a80,
00195 0x046e,
00196 0x2209,
00197
00198 0x0039,
00199 0x0880,
00200 0x000f,
00201 0x0001,
00202 0x0008,
00203 0x0100,
00204
00205 0x1058,
00206 0x047c,
00207 0x0058,
00208 0x045e,
00209 0x2058,
00210 0x0471,
00211 0x0c0c,
00212 0x0474,
00213 0x0004,
00214 0x000e,
00215 0x0c70,
00216 0x0038,
00217 0x1454,
00218 0x0454,
00219 0x045c,
00220 0x0473,
00221 0x0467,
00222 0x0450,
00223 0x0c08,
00224 0x0078,
00225 0x001c,
00226 0x2010,
00227 0x2814,
00228 0x2a80,
00229 0x080c,
00230 0x2048,
00231
00232 0x0000,
00233 };
00234
00235
00240 static const uint16_t EFM_Numbers[] = {
00241 0x003f,
00242 0x0006,
00243 0x005b,
00244 0x004f,
00245 0x0066,
00246 0x006d,
00247 0x007d,
00248 0x0007,
00249 0x007f,
00250 0x006f,
00251 0x0077,
00252 0x007c,
00253 0x0039,
00254 0x005e,
00255 0x0079,
00256 0x0071,
00257 0x0040
00258 };
00259
00261
00262 static const uint16_t signIndex = sizeof(EFM_Numbers)/sizeof(uint16_t) - 1 ;
00263
00264 static const LCD_Init_TypeDef lcdInit = LCD_INIT_DEF;
00268
00271 void SegmentLCD_AllOff(void)
00272 {
00273
00274 LCD_ALL_SEGMENTS_OFF();
00275 }
00276
00277
00278
00281 void SegmentLCD_AllOn(void)
00282 {
00283 LCD_ALL_SEGMENTS_ON();
00284 }
00285
00286
00287
00290 void SegmentLCD_AlphaNumberOff(void)
00291 {
00292 LCD_ALPHA_NUMBER_OFF();
00293 return;
00294 }
00295
00296
00297
00302 void SegmentLCD_ARing(int anum, int on)
00303 {
00304 uint32_t com, bit;
00305
00306 com = EFM_Display.ARing.com[anum];
00307 bit = EFM_Display.ARing.bit[anum];
00308
00309 if (on)
00310 {
00311 LCD_SegmentSet(com, bit, true);
00312 }
00313 else
00314 {
00315 LCD_SegmentSet(com, bit, false);
00316 }
00317 }
00318
00319
00320
00324 void SegmentLCD_Battery(int batteryLevel)
00325 {
00326 uint32_t com, bit;
00327 int i, on;
00328
00329 for (i = 0; i < 4; i++)
00330 {
00331 if (i < batteryLevel)
00332 {
00333 on = 1;
00334 }
00335 else
00336 {
00337 on = 0;
00338 }
00339 com = EFM_Display.Battery.com[i];
00340 bit = EFM_Display.Battery.bit[i];
00341
00342 if (on)
00343 {
00344 LCD_SegmentSet(com, bit, true);
00345 }
00346 else
00347 {
00348 LCD_SegmentSet(com, bit, false);
00349 }
00350 }
00351 }
00352
00353
00354
00357 void SegmentLCD_Disable(void)
00358 {
00359
00360 LCD_Enable(false);
00361
00362
00363 LCD_SyncBusyDelay(LCD_SYNCBUSY_CTRL);
00364
00365
00366 CMU_ClockEnable(cmuClock_LCD, false);
00367
00368
00369 CMU->LCDCTRL = 0;
00370 }
00371
00372
00373
00378 void SegmentLCD_EnergyMode(int em, int on)
00379 {
00380 uint32_t com, bit;
00381
00382 com = EFM_Display.EMode.com[em];
00383 bit = EFM_Display.EMode.bit[em];
00384
00385 if (on)
00386 {
00387 LCD_SegmentSet(com, bit, true);
00388 }
00389 else
00390 {
00391 LCD_SegmentSet(com, bit, false);
00392 }
00393 }
00394
00395
00396
00400 void SegmentLCD_Init(bool useBoost)
00401 {
00402
00403
00404 CMU_ClockEnable(cmuClock_CORELE, true);
00405
00406
00407 CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
00408
00409
00410 CMU_ClockDivSet(cmuClock_LCDpre, LCD_CMU_CLK_PRE);
00411
00412
00413 CMU_LCDClkFDIVSet(LCD_CMU_CLK_DIV);
00414
00415
00416 CMU_ClockEnable(cmuClock_LCD, true);
00417
00418 LCD_DISPLAY_ENABLE();
00419
00420
00421 LCD_IntDisable(0xFFFFFFFF);
00422
00423
00424 LCD_Init(&lcdInit);
00425
00426
00427 LCD_SEGMENTS_ENABLE();
00428
00429
00430 if (useBoost)
00431 {
00432 LCD_VBoostSet(LCD_BOOST_LEVEL);
00433 LCD_VLCDSelect(lcdVLCDSelVExtBoost);
00434 CMU->LCDCTRL |= CMU_LCDCTRL_VBOOSTEN;
00435 }
00436
00437
00438 SegmentLCD_AllOff();
00439
00440 LCD_SyncBusyDelay(0xFFFFFFFF);
00441 }
00442
00443
00444
00450 void SegmentLCD_LowerHex( uint32_t num )
00451 {
00452 int i;
00453 char str[7];
00454 uint32_t nibble;
00455
00456 SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);
00457
00458 for ( i=6; i>=0; i-- )
00459 {
00460 nibble = num & 0xF;
00461
00462 if ( nibble < 10 )
00463 str[i] = nibble + '0';
00464 else if ( nibble == 11 )
00465 str[i] = 'b';
00466 else if ( nibble == 13 )
00467 str[i] = 'd';
00468 else
00469 str[i] = (nibble - 10) + 'A';
00470
00471 num >>= 4;
00472 }
00473
00474 SegmentLCD_Write(str);
00475 }
00476
00477
00481 void SegmentLCD_LowerNumber( int num )
00482 {
00483 int i;
00484 char str[7];
00485
00486 SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);
00487
00488 if ( ( num > 9999999 ) || ( num < -9999999 ) )
00489 {
00490 SegmentLCD_Write("Ovrflow");
00491 return;
00492 }
00493
00494 if ( num < 0 )
00495 {
00496 SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 1);
00497 num = -num;
00498 }
00499
00500 for ( i=6; i>=0; i-- )
00501 {
00502 if ( ( i < 6 ) && ( num == 0 ) )
00503 {
00504 str[i] = ' ';
00505 }
00506 else
00507 {
00508 str[i] = (num % 10) + '0';
00509 num /= 10;
00510 }
00511 }
00512
00513 SegmentLCD_Write(str);
00514 }
00515
00516
00517
00521 void SegmentLCD_Number(int value)
00522 {
00523 int i, com, bit, digit, div, neg;
00524 uint16_t bitpattern;
00525 uint16_t num;
00526
00527
00528 if (value >= 9999)
00529 {
00530 value = 9999;
00531 }
00532 if (value <= -1000)
00533 {
00534 value = -999;
00535 }
00536 if (value < 0)
00537 {
00538 value = abs(value);
00539 neg = 1;
00540 }
00541 else
00542 {
00543 neg = 0;
00544 }
00545
00546
00547 LCD_SyncBusyDelay(0xFFFFFFFF);
00548
00549
00550 LCD_FreezeEnable(true);
00551
00552
00553 SegmentLCD_NumberOff();
00554
00555
00556 div = 1;
00557 for (digit = 0; digit < 4; digit++)
00558 {
00559 num = (value / div) % 10;
00560 if ((neg == 1) && (digit == 3)) num = signIndex;
00561
00562 bitpattern = EFM_Numbers[num];
00563 for (i = 0; i < 7; i++)
00564 {
00565 bit = EFM_Display.Number[digit].bit[i];
00566 com = EFM_Display.Number[digit].com[i];
00567 if (bitpattern & (1 << i))
00568 {
00569 LCD_SegmentSet(com, bit, true);
00570 }
00571 }
00572 div = div * 10;
00573 }
00574
00575 LCD_FreezeEnable(false);
00576 }
00577
00578
00579
00582 void SegmentLCD_NumberOff(void)
00583 {
00584
00585 LCD_NUMBER_OFF();
00586 return;
00587 }
00588
00589
00590
00595 void SegmentLCD_Symbol(lcdSymbol s, int on)
00596 {
00597 int com = 0;
00598 int bit = 0;
00599
00600 switch (s)
00601 {
00602 case LCD_SYMBOL_GECKO:
00603 com = LCD_SYMBOL_GECKO_COM;
00604 bit = LCD_SYMBOL_GECKO_SEG;
00605 break;
00606 case LCD_SYMBOL_ANT:
00607 com = LCD_SYMBOL_ANT_COM;
00608 bit = LCD_SYMBOL_ANT_SEG;
00609 break;
00610 case LCD_SYMBOL_PAD0:
00611 com = LCD_SYMBOL_PAD0_COM;
00612 bit = LCD_SYMBOL_PAD0_SEG;
00613 break;
00614 case LCD_SYMBOL_PAD1:
00615 com = LCD_SYMBOL_PAD1_COM;
00616 bit = LCD_SYMBOL_PAD1_SEG;
00617 break;
00618 case LCD_SYMBOL_EFM32:
00619 com = LCD_SYMBOL_EFM32_COM;
00620 bit = LCD_SYMBOL_EFM32_SEG;
00621 break;
00622 case LCD_SYMBOL_MINUS:
00623 com = LCD_SYMBOL_MINUS_COM;
00624 bit = LCD_SYMBOL_MINUS_SEG;
00625 break;
00626 case LCD_SYMBOL_COL3:
00627 com = LCD_SYMBOL_COL3_COM;
00628 bit = LCD_SYMBOL_COL3_SEG;
00629 break;
00630 case LCD_SYMBOL_COL5:
00631 com = LCD_SYMBOL_COL5_COM;
00632 bit = LCD_SYMBOL_COL5_SEG;
00633 break;
00634 case LCD_SYMBOL_COL10:
00635 com = LCD_SYMBOL_COL10_COM;
00636 bit = LCD_SYMBOL_COL10_SEG;
00637 break;
00638 #ifdef LCD_SYMBOL_DEGC_SEG
00639 case LCD_SYMBOL_DEGC:
00640 com = LCD_SYMBOL_DEGC_COM;
00641 bit = LCD_SYMBOL_DEGC_SEG;
00642 break;
00643 #endif
00644 #ifdef LCD_SYMBOL_DEGF_SEG
00645 case LCD_SYMBOL_DEGF:
00646 com = LCD_SYMBOL_DEGF_COM;
00647 bit = LCD_SYMBOL_DEGF_SEG;
00648 break;
00649 #endif
00650 #ifdef LCD_SYMBOL_DP2_SEG
00651 case LCD_SYMBOL_DP2:
00652 com = LCD_SYMBOL_DP2_COM;
00653 bit = LCD_SYMBOL_DP2_SEG;
00654 break;
00655 #endif
00656 #ifdef LCD_SYMBOL_DP3_SEG
00657 case LCD_SYMBOL_DP3:
00658 com = LCD_SYMBOL_DP3_COM;
00659 bit = LCD_SYMBOL_DP3_SEG;
00660 break;
00661 #endif
00662 #ifdef LCD_SYMBOL_DP4_SEG
00663 case LCD_SYMBOL_DP4:
00664 com = LCD_SYMBOL_DP4_COM;
00665 bit = LCD_SYMBOL_DP4_SEG;
00666 break;
00667 #endif
00668 #ifdef LCD_SYMBOL_DP5_SEG
00669 case LCD_SYMBOL_DP5:
00670 com = LCD_SYMBOL_DP5_COM;
00671 bit = LCD_SYMBOL_DP5_SEG;
00672 break;
00673 #endif
00674 case LCD_SYMBOL_DP6:
00675 com = LCD_SYMBOL_DP6_COM;
00676 bit = LCD_SYMBOL_DP6_SEG;
00677 break;
00678 case LCD_SYMBOL_DP10:
00679 com = LCD_SYMBOL_DP10_COM;
00680 bit = LCD_SYMBOL_DP10_SEG;
00681 break;
00682 #ifdef LCD_SYMBOL_AM_SEG
00683 case LCD_SYMBOL_AM:
00684 com = LCD_SYMBOL_AM_COM;
00685 bit = LCD_SYMBOL_AM_SEG;
00686 break;
00687 #endif
00688 #ifdef LCD_SYMBOL_PM_SEG
00689 case LCD_SYMBOL_PM:
00690 com = LCD_SYMBOL_PM_COM;
00691 bit = LCD_SYMBOL_PM_SEG;
00692 break;
00693 #endif
00694 #ifdef LCD_SYMBOL_MICROAMP_SEG
00695 case LCD_SYMBOL_MICROAMP:
00696 com = LCD_SYMBOL_MICROAMP_COM;
00697 bit = LCD_SYMBOL_MICROAMP_SEG;
00698 break;
00699 #endif
00700 #ifdef LCD_SYMBOL_MILLIAMP_SEG
00701 case LCD_SYMBOL_MILLIAMP:
00702 com = LCD_SYMBOL_MILLIAMP_COM;
00703 bit = LCD_SYMBOL_MILLIAMP_SEG;
00704 break;
00705 #endif
00706
00707 }
00708 if (on)
00709 {
00710 LCD_SegmentSet(com, bit, true);
00711 }
00712 else
00713 {
00714 LCD_SegmentSet(com, bit, false);
00715 }
00716 }
00717
00718
00719
00723 void SegmentLCD_UnsignedHex(uint16_t value)
00724 {
00725 int num, i, com, bit, digit;
00726 uint16_t bitpattern;
00727
00728
00729 if (value >= 0xffff)
00730 {
00731 value = 0xffff;
00732 }
00733
00734
00735 LCD_SyncBusyDelay(0xFFFFFFFF);
00736
00737
00738 LCD_FreezeEnable(true);
00739
00740
00741 SegmentLCD_NumberOff();
00742
00743 for (digit = 0; digit < 4; digit++)
00744 {
00745 num = (value >> (4 * digit)) & 0x0f;
00746 bitpattern = EFM_Numbers[num];
00747 for (i = 0; i < 7; i++)
00748 {
00749 bit = EFM_Display.Number[digit].bit[i];
00750 com = EFM_Display.Number[digit].com[i];
00751 if (bitpattern & (1 << i))
00752 {
00753 LCD_SegmentSet(com, bit, true);
00754 }
00755 }
00756 }
00757
00758
00759 LCD_FreezeEnable(false);
00760 }
00761
00762
00763
00767 void SegmentLCD_Write(char *string)
00768 {
00769 int data, length, index;
00770 uint16_t bitfield;
00771 uint32_t com, bit;
00772 int i;
00773
00774 length = strlen(string);
00775 index = 0;
00776
00777
00778 LCD_SyncBusyDelay(0xFFFFFFFF);
00779
00780
00781 LCD_FreezeEnable(true);
00782
00783
00784 SegmentLCD_AlphaNumberOff();
00785
00786
00787 for (index = 0; index < 7; index++)
00788 {
00789 if (index < length)
00790 {
00791 data = (int) *string;
00792 }
00793 else
00794 {
00795 data = 0x20;
00796 }
00797
00798 data = data - 0x20;
00799
00800 bitfield = EFM_Alphabet[data];
00801
00802 for (i = 0; i < 14; i++)
00803 {
00804 bit = EFM_Display.Text[index].bit[i];
00805 com = EFM_Display.Text[index].com[i];
00806
00807 if (bitfield & (1 << i))
00808 {
00809
00810 LCD_SegmentSet(com, bit, true);
00811 }
00812 }
00813 string++;
00814 }
00815
00816 LCD_FreezeEnable(false);
00817 }