output.c

Go to the documentation of this file.
00001 
00002 
00003 
00013 
00014 
00015 
00016     #define     OUTPUT_C
00017 
00018     #include    "output.h"
00019 
00020 
00022 // Local Variables
00024 
00025 static BYTE * _pu8LCD_row;
00026 static BYTE _u8LCD_contrast;
00027 static BYTE _u8LCD_progress;
00028 static BYTE _u8LED_blinking;
00029 static DWORD _u32BlinkTimer;
00030 static DWORD _u32LastProgTime;
00031 volatile WORD _u16LCDTime;
00032 static DWORD _u32DisplayTimer;
00033 
00034 
00036 // Local function prototypes
00038 
00039 static void _writeToLCD(BYTE nValue, BOOL bRAM);
00040 static void _setLCDAddress(BYTE nCol, BYTE nRow);
00041 static void _startLCDTimer(WORD u16WaitValue);
00042 static void _initLCDTimer(void);
00043 static BOOL _isLCDTimerElapsed(void);
00044 void _peripheralTimerISR(void);
00045 
00046 
00048 // Function implementation
00050 
00051 void OutInit(void)
00052 {
00053     BYTE i = 0;
00054 
00055     // Init values for LCD, see the st7036 datasheet for details.
00056     BYTE initArray[] = { // Function set: 8 Bit | 2 rows | Inst table 1
00057                         0x39, 0x39,
00058 
00059                         // BIAS set: 1/5 | 2 rows
00060                         0x14, 
00061 
00062                         // Follower control: Circuit on | 3,3 V boost
00063                         0x6D,
00064 
00065                         // Contrast set (low byte), the contrast value is later
00066                         // ored to by the function _writeToLCD.
00067                         0x70, 
00068 
00069                         // ICON off | Booster circuit on | Contrast set (high 
00070                         // byte), later ored to by the function _writeToLCD.
00071                         0x54, 
00072 
00073                         // Display On | No cursor | No cursor blinkink
00074                         0x0C, 
00075 
00076                         // Shift of entire display is not performed.
00077                         0x06, 
00078 
00079                         // Clear display.
00080                         0x01, 
00081 
00082                         // Function set: 8 Bit | 2 rows | Inst table 0
00083                         0x38, 
00084 
00085                         // Set CGRAM address to address 0x08.
00086                         0x48 };
00087 
00088     BYTE patternArray[] = {0x18, 0x04, 0x02, 0x18, 0x1A, 0x1F, 0x1F, 0x0A,
00089                            0x03, 0x04, 0x08, 0x03, 0x0B, 0x1F, 0x1F, 0x0A,
00090                            0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00,
00091                            0x00, 0x0E, 0x1F, 0x1F, 0x1F, 0x0E, 0x00, 0x00,
00092                            0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04,
00093                            0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04};
00094 
00095     // Disable analog and comparator module 
00096     ADCON1 = 0x0F;
00097     CMCON = 0x07;
00098 
00099     // Initialize PORTF...
00100     // PORTF.RF0 - Not connected
00101     // PORTF.RF1 -> LCD_PWR (LCD power supply, high active )
00102     // PORTF.RF2 -> LCD_RS (select mode at LCD, register or ram access)
00103     // PORTF.RF3 -> /LCD_CSB (LCD chip select for SPI access)
00104     // PORTF.RF4 -> LCD_LED (Enables the backlight at LCD)
00105     // PORTF.RF5 -> /EEPROM_CS (Selects the EEPROM for SPI access, low active)
00106     // -> Configure the whole port as output.
00107 
00108     PORTF = 0x28;   // Turn off all signals.
00109     Nop();
00110     TRISF = 0;      // Configure all bits of PORTF as outputs.
00111     
00112 
00113     // Initialize PORTB...
00114     // PORTB.RB0 -> /LED_PWR (LED of the power button, low active)
00115     // PORTB.RB1 -> /LED_F4 (LED of the F4 button, low active)
00116     // PORTB.RB2 -> /LED_F3 (LED of the F3 button, low active)
00117     // PORTB.RB3 -> /LED_F2 (LED of the F2 button, low active)
00118     // PORTB.RB4 - PORTB.RB7 not used by the display functions.
00119     // Only the lower 4 Bits of PORTB will be configured as outputs. The other 
00120     // bits remain unintended.
00121 
00122     PORTB = 0x0F;       // Switch off all the PORTB LEDs.
00123     Nop();
00124     TRISB &= 0xF0;  
00125 
00126 
00127     // Initialize PORTC...
00128     // PORTC.RC0 -> /FL_LED (LED of the FL button, low active)
00129     // PORTC.RC1 -> /F1_LED (LED of the F1 button, low active)
00130     // PORTC.RC2 -> not connected
00131     // PORTC.RC3 -> LCD_CLK (SPI clock for communication with the LCD)
00132     // PORTC.RC4 <- SPI MISO (Not used by LCD)
00133     // PORTC.RC5 -> LCD_SI (SPI data line to LCD)
00134     // PORTC.RC6 -> /SEL_LED (LED of the SEL button, low active)
00135     // PORTC.RC7 -> /ACC_LED (LED of the ACC button, low active)
00136     // All bits are initialized as outputs, but RC4 is configured as input.
00137 
00138     PORTC = 0xC3;       // Switch off all the PORTB LEDs.
00139     Nop();
00140     TRISC = 0x10;
00141 
00142     _u8LED_blinking = 0;
00143 
00144 
00145     // Initilaize register for LCD operations:
00146     lcd_status = 0;
00147     _pu8LCD_row = 0;
00148     _u8LCD_progress = 16;
00149 
00150     
00151     // Set a well known contrast value.
00152     _u8LCD_contrast = 0x18;
00153 
00154 
00155     // The LCD uses an internal timer for all its access routines because the
00156     // display has no back communication channel and therefore the ouput 
00157     // routines can not poll the busy flag of the LCD. It simply performs wait
00158     // cycles before sending the next data to the display.
00159     _initLCDTimer();
00160 
00161     _startLCDTimer(10); // Wait for stabilized outputs before enabling the LCD.
00162     while(_isLCDTimerElapsed() == FALSE);
00163 
00164     PORTFbits.RF1 = 1;  // Switch on LCD.
00165 
00166 
00167     // Wait some time (ca. 50 ms) before starting the init sequence of the
00168     // display (internal startup time of the display).
00169     _startLCDTimer(500);
00170 
00171     // Init sequence
00172     for (i = 0; i < sizeof(initArray); i++)
00173     {
00174         while(_isLCDTimerElapsed() == FALSE);
00175         _writeToLCD(initArray[i], FALSE);
00176     }
00177 
00178     // Send new symbols to display. 
00180     for (i = 0; i <  sizeof(patternArray); i++)
00181     {
00182         while(_isLCDTimerElapsed() == FALSE);
00183         _writeToLCD(patternArray[i], TRUE);
00184     }
00185 
00186     PORTFbits.RF4 = 1;  // Switch on LCD backlight.
00187 }
00188 
00191 
00192 void OutTriggerDisplay(void)
00193 {
00194     _u32DisplayTimer = TickGet();
00195 
00196     if (sPCommonConfig.u8LCDLight == 0xFF)
00197     {
00198         OutSwitchLCDBacklight(TRUE);
00199     }
00200     else if (sPCommonConfig.u8LCDLight == 0)
00201     {
00202         OutSwitchLCDBacklight(FALSE);
00203     }
00204     else
00205     {
00206         _u32DisplayTimer += sPCommonConfig.u8LCDLight*TICKS_PER_SECOND;
00207         OutSwitchLCDBacklight(TRUE);
00208     }
00209 }
00210 
00213 
00214 void OutMain(void)
00215 {
00216     if (_u8LED_blinking && (_u32BlinkTimer < TickGet()))
00217     {
00218         OutSetLED(_u8LED_blinking, LED_TOGGLE);
00219         _u32BlinkTimer = TickGet() + LED_BLINK_INTERVAL * TICKS_PER_SECOND;
00220     }
00221 
00222     // Is the LCD ready (Waiting time over)?
00223     if (_isLCDTimerElapsed() == FALSE)
00224     {
00225         return;
00226     }
00227 
00228     // If commands for the display are pending, the LCD is busy and therefore
00229     // the display stays on!
00230     if (lcd_status)
00231     {
00232         OutTriggerDisplay();
00233     }
00234     else if ((_u32DisplayTimer < TickGet()) && sPCommonConfig.u8LCDLight)
00235     {
00236         OutSwitchLCDBacklight(FALSE);
00237     }
00238 
00239     // Check the LCD command:   
00240     if (lcd_status & LCD_CLR_MASK)
00241     {
00242         _pu8LCD_row = 0;
00243         lcd_status &= ~(LCD_CLR_MASK);
00244         _writeToLCD(0x01, FALSE);
00245     }
00246     else if (_pu8LCD_row)
00247     {
00248         if (*_pu8LCD_row == 0)
00249         {
00250             _pu8LCD_row = 0;
00251         }
00252         else
00253         {   
00254             _writeToLCD(*_pu8LCD_row, TRUE);
00255             _pu8LCD_row++;
00256         }
00257     }
00258     else if (lcd_status & LCD_ROW1_MASK)
00259     {
00260         lcd_status &= ~LCD_ROW1_MASK;
00261         if (lcd_status & LCD_CENTER1_MASK)
00262         {
00263             lcd_addr1 = (LCD_CHARS_IN_A_ROW - strlen(lcdram_row1))>>1;
00264             lcd_status &= ~LCD_CENTER1_MASK;
00265         }
00266         if (strlen(lcdram_row1) == 0)
00267         {
00268             return;
00269         }
00270         _pu8LCD_row = lcdram_row1;
00271         _setLCDAddress(lcd_addr1, 0);
00272     }
00273 #ifdef LCD_WITH_2_ROWS
00274     else if (lcd_status & LCD_ROW2_MASK)
00275     {
00276         lcd_status &= ~LCD_ROW2_MASK;
00277         if (lcd_status & LCD_CENTER2_MASK)
00278         {
00279             lcd_addr2 = (LCD_CHARS_IN_A_ROW - strlen(lcdram_row2))>>1;
00280             lcd_status &= ~LCD_CENTER2_MASK;
00281         }
00282 
00283         if (strlen(lcdram_row2) == 0)
00284         {
00285             return;
00286         }
00287         _pu8LCD_row = lcdram_row2;
00288         _u8LCD_progress = strlen(lcdram_row2);
00289         _u32LastProgTime = TickGet() + LCD_PROGRESS_TIME * TICKS_PER_SECOND;
00290         _setLCDAddress(lcd_addr2, 1);
00291     }
00292 #ifdef LCD_WITH_3_ROWS
00293     else if (lcd_status & LCD_ROW3_MASK)
00294     {
00295         lcd_status &= ~LCD_ROW3_MASK;
00296         // ToDo: Implement.
00297     }
00298 #endif
00299 #endif
00300     else if (lcd_status & LCD_CLR_PROG_MASK)
00301     {
00302         BYTE i;
00303         lcd_status &= ~LCD_CLR_PROG_MASK;
00304     
00305         for (i = 0; i < 16; i++)
00306         {
00307             if (lcdram_row2[i] == '.')
00308             {
00309                 lcdram_row2[i] = 0;
00310                 lcd_status |= LCD_ROW2_MASK;
00311                 break;
00312             }
00313         }
00314     }
00315     else if (lcd_status & LCD_PROGRESS_MASK)
00316     {
00317         // Is it time for a new character?
00318         if (_u32LastProgTime < TickGet())
00319         {
00320             lcdram_row2[_u8LCD_progress++] = LCD_PROGRESS_CHAR;
00321             lcdram_row2[_u8LCD_progress] = 0;
00322             lcd_status |= LCD_ROW2_MASK;
00323             if (_u8LCD_progress > (15 - lcd_addr2)) 
00324             {
00325                 lcd_status &= ~LCD_PROGRESS_MASK;
00326             }
00327         }
00328     }
00329 }
00330 
00333 
00334 #ifdef DEBEXT_MODE
00335 
00336 void OutDebugOut(BYTE nValue)
00337 {
00338     PORTCbits.RC0 = nValue & LED_FL ? 0 : 1;
00339     PORTCbits.RC1 = nValue & LED_F1 ? 0 : 1;
00340     PORTBbits.RB3 = nValue & LED_F2 ? 0 : 1;
00341     PORTBbits.RB2 = nValue & LED_F3 ? 0 : 1;
00342     PORTBbits.RB1 = nValue & LED_F4 ? 0 : 1;
00343     PORTBbits.RB0 = nValue & LED_PWR ? 0 : 1;
00344     PORTCbits.RC7 = nValue & LED_ACC ? 0 : 1;
00345     PORTCbits.RC6 = nValue & LED_SEL ? 0 : 1;
00346 }
00347 
00348 #endif
00349 
00352 
00353 void OutSwitchOffLCD(void)
00354 {
00355     PORTF &= 0x2C;
00356 } 
00357 
00360 
00361 void OutSwitchLCDBacklight(BOOL On)
00362 {
00363     if (On == FALSE)
00364     {
00365         PORTF &= 0x2E;
00366     }
00367     else
00368     {
00369         PORTF |= 0x10;
00370     }
00371 } 
00372 
00375 
00376 BOOL OutIsLCDBusy(void)
00377 {
00378     if ((_isLCDTimerElapsed() == FALSE) || (lcd_status) || (_pu8LCD_row))
00379     {
00380         return TRUE;
00381     }
00382     else
00383     {
00384         return FALSE;
00385     }
00386 }
00387 
00390 
00391 void OutEnableCursor(BOOL On)
00392 {
00393     if (On == TRUE)
00394     {
00395         _writeToLCD(0x0E, FALSE);
00396     }
00397     else
00398     {
00399         _writeToLCD(0x0C, FALSE);
00400     }
00401 }
00402 
00405 
00406 void OutSetCursor(BYTE Column, BYTE Row)
00407 {
00408     _setLCDAddress(Column, Row);
00409 }
00410 
00413 
00414 void OutSwitchOffAllLEDs(void)
00415 {
00416     BYTE i;
00417 
00418     for (i = LED_FL; i != 0; i = i<<1)
00419     {
00420         OutSetLED(i, LED_OFF);
00421     }
00422 }
00423 
00426 
00427 void OutSetLEDMask(BYTE LedMask, BYTE LedSwitchMask)
00428 {
00429     BYTE setmask = LedMask & LedSwitchMask;
00430     BYTE clearmask = LedMask & (~LedSwitchMask);
00431     OutSetLED(setmask, LED_ON);
00432     OutSetLED(clearmask, LED_OFF);
00433 }
00434 
00437 
00438 void OutSetLED(BYTE LedMask, eLED_Modes Mode)
00439 {
00440     BOOL ledOff = TRUE;
00441 
00442     switch(Mode)
00443     {
00444     case LED_BLINK:
00445         _u8LED_blinking |= LedMask;
00446         _u32BlinkTimer = TickGet() + LED_BLINK_INTERVAL;
00447         break;
00448 
00449     case LED_ON:
00450         ledOff = FALSE;
00451         // Intended fall through
00452 
00453     case LED_OFF:
00454         _u8LED_blinking &= ~LedMask;
00455 
00456         if (LedMask & LED_FL)
00457         {
00458             PORTCbits.RC0 = ledOff;
00459         }
00460         if (LedMask & LED_F1)
00461         {
00462             PORTCbits.RC1 = ledOff;
00463         }
00464         if (LedMask & LED_F2)
00465         {
00466             PORTBbits.RB3 = ledOff;
00467         }
00468         if (LedMask & LED_F3)
00469         {
00470             PORTBbits.RB2 = ledOff;
00471         }
00472         if (LedMask & LED_F4)
00473         {
00474             PORTBbits.RB1 = ledOff;
00475         }
00476         if (LedMask & LED_PWR)
00477         {
00478             PORTBbits.RB0 = ledOff;
00479         }
00480         if (LedMask & LED_ACC)
00481         {
00482             PORTCbits.RC7 = ledOff;
00483         }       
00484         if (LedMask & LED_SEL)
00485         {
00486             PORTCbits.RC6 = ledOff;
00487         }
00488         break;
00489 
00490     case LED_TOGGLE:
00491         if (LedMask & LED_FL)
00492         {
00493             PORTCbits.RC0 = ~PORTCbits.RC0;
00494         }
00495         if (LedMask & LED_F1)
00496         {
00497             PORTCbits.RC1 = ~PORTCbits.RC1;
00498         }
00499         if (LedMask & LED_F2)
00500         {
00501             PORTBbits.RB3 = ~PORTBbits.RB3;
00502         }
00503         if (LedMask & LED_F3)
00504         {
00505             PORTBbits.RB2 = ~PORTBbits.RB2;
00506         }
00507         if (LedMask & LED_F4)
00508         {
00509             PORTBbits.RB1 = ~PORTBbits.RB1;
00510         }
00511         if (LedMask & LED_PWR)
00512         {
00513             PORTBbits.RB0 = ~PORTBbits.RB0;
00514         }
00515         if (LedMask & LED_ACC)
00516         {
00517             PORTCbits.RC7 = ~PORTCbits.RC7; 
00518         }   
00519         if (LedMask & LED_SEL)
00520         {
00521             PORTCbits.RC6 = ~PORTCbits.RC6; 
00522         }
00523     }
00524 }
00525 
00528 
00529 eLED_Modes OutGetLEDMode(BYTE Led)
00530 {
00531     BOOL ledOff = TRUE;
00532 
00533     if (_u8LED_blinking & Led)
00534     {
00535         return LED_BLINK;
00536     }
00537 
00538     if (Led & LED_FL)
00539     {
00540         ledOff = PORTCbits.RC0;
00541     }
00542 
00543     if (Led & LED_F1)
00544     {
00545         ledOff = PORTCbits.RC1;
00546     }
00547 
00548     if (Led & LED_F2)
00549     {
00550         ledOff = PORTBbits.RB3;
00551     }
00552 
00553     if (Led & LED_F3)
00554     {
00555         ledOff = PORTBbits.RB2;
00556     }
00557 
00558     if (Led & LED_F4)
00559     {
00560         ledOff = PORTBbits.RB1;
00561     }
00562 
00563     if (Led & LED_PWR)
00564     {
00565         ledOff = PORTBbits.RB0;
00566     }
00567 
00568     if (Led & LED_ACC)
00569     {
00570         ledOff = PORTCbits.RC7; 
00571     }
00572 
00573     if (Led & LED_SEL)
00574     {
00575         ledOff = PORTCbits.RC6;
00576     }
00577 
00578     if (ledOff)
00579     {
00580         return LED_OFF;
00581     }
00582     else
00583     {
00584         return LED_ON;
00585     }
00586 }
00587 
00590 
00591 static void _writeToLCD(BYTE nValue, BOOL bRAM)
00592 {
00593     if (bRAM == FALSE) 
00594     {
00595         if ((nValue & 0xF0) == 0x60)
00596         {
00597             // Wait 200 ms for stabilizing of the power supply when writing the
00598             // follower control to display.
00599             _startLCDTimer(2000);
00600         }
00601         else if ((nValue & 0xFC) == 0x00)
00602         {
00603             // Return Home and Clear Diplay need ca. 1,08 ms
00604             _startLCDTimer(11);
00605         }
00606         else
00607         {
00608             if ((nValue & 0xF0) == 0x70)
00609             {
00610                 // Oring the low nibble of the contrast value for setting the
00611                 // contrast low byte.
00612                 nValue = 0x70 | (_u8LCD_contrast & 0x0F);
00613             }
00614             else if ((nValue & 0xF0) == 0x50)
00615             {
00616                 nValue &= 0xFC;
00617                 nValue |= (_u8LCD_contrast >> 4) & 0x03;
00618             }
00619             _startLCDTimer(1);  // Wait 100 us.
00620         }
00621     }
00622     else
00623     {
00624         _startLCDTimer(1);  // Wait 100 us.
00625     }
00626 
00627     // SPI-Configuration for LCD:
00628     // SPI Master | Clock = Fosc/64 | Enable | Clock idle state is high 
00629     SSP1CON1 = 0x32;
00630     SSP1STAT = 0x00;    // CKE = 0
00631 
00632     PORTFbits.RF2 = bRAM;
00633     PORTFbits.RF3 = 0;  // Select LCD.
00634     PIR1bits.SSP1IF = 0;
00635     SSP1BUF = nValue;   // Write value on SPI bus.
00636 
00637     // Wait until SPI transmission is finished:
00638     while(PIR1bits.SSP1IF == 0);
00639 
00640     PORTFbits.RF3 = 1;  // Deselect LCD.
00641 
00642     return;
00643 }
00644 
00647 
00648 static void _setLCDAddress(BYTE nCol, BYTE nRow)
00649 {
00650 
00651 #ifdef LCD_WITH_3_ROWS
00652     nCol &= 0x0F;
00653     if (nRow == 1)
00654     {
00655         nCol |= 0x10;
00656     }
00657     else if (nRow == 2)
00658     {
00659         nCol |= 0x20;
00660     }
00661 #endif  
00662 
00663 #ifdef LCD_WITH_2_ROWS
00664     nCol &= 0x3F;
00665     if (nRow == 1)
00666     {
00667         nCol |= 0x40;
00668     }
00669 #endif
00670 
00671     _writeToLCD(nCol | 0x80, FALSE);
00672 }
00673 
00676 
00677 static void _initLCDTimer(void)
00678 {
00679     // Init the 100 us timer:
00680     T2CON = 0x03;   // Reset timer 2 (8 bit timer, 1:16 Prescaler).
00681     PR2 = (GetPeripheralClock() * 0.0001) / 16;     // Match register.
00682     IPR1bits.TMR2IP = 0;    // Low interrupt priority.
00683     PIE1bits.TMR2IE = 0;    // Disable the interrupt flag.
00684 }
00685 
00688 
00689 static void _startLCDTimer(WORD u16WaitValue)
00690 {
00691     PIE1bits.TMR2IE = 0;    // Disable the interrupt.
00692     _u16LCDTime = u16WaitValue;
00693     T2CONbits.TMR2ON = 0;   // Stop timer.
00694     TMR2 = 0;
00695     PIR1bits.TMR2IF = 0;    // Clearing the compare match interrupt flag.
00696     PIE1bits.TMR2IE = 1;    // Enable the interrupt.
00697 
00698     T2CONbits.TMR2ON = 1;   // Start timer.
00699 }
00700 
00703 
00704 static BOOL _isLCDTimerElapsed(void)
00705 {
00706     if (PIE1bits.TMR2IE == 0)
00707     {
00708         return TRUE;
00709     }
00710     
00711     return FALSE;
00712 }
00713 
00716 
00717 void OutConvertNameForDisplay(BYTE * pString)
00718 {
00719     BYTE i;
00720     for (i = 0; i < strlen(pString); i++)
00721     {
00722         switch(pString[i])
00723         {
00724         case 0xE4:
00725             pString[i] = '\x84';
00726             break;
00727 
00728         case 0xFC:
00729             pString[i] = '\x81';
00730             break;
00731 
00732         case 0xF6:
00733             pString[i] = '\x94';
00734             break;
00735 
00736         case 0xDC:
00737             pString[i] = '\x9A';
00738             break;
00739 
00740         case 0xC4:
00741             pString[i] = '\x8E';
00742             break;
00743 
00744         case 0xD6:
00745             pString[i] = '\x99';
00746             break;
00747         }
00748     }
00749 }
00750 
00753 
00754 void OutInterruptHandler(void)
00755 {
00756     if (PIR1bits.TMR2IF == 1)
00757     {
00758         // Decrement LCD wait time...
00759         _u16LCDTime--;
00760     
00761         if (_u16LCDTime == 0)
00762         {
00763             PIE1bits.TMR2IE = 0;    // Time is over, disable interrupt.
00764             T2CONbits.TMR2ON = 0;   // Disable timer.
00765         }
00766 
00767         PIR1bits.TMR2IF = 0;    // Clearing the interrupt flag.
00768     }
00769 }
00770 

Generated on Sun Nov 27 20:02:38 2011 for eWicht by  doxygen 1.5.5