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