449stk2.c

Go to the documentation of this file.
00001 /*
00002  * File:        449stk2.c
00003  * Purpose:     Main program
00004  * Author:      Peter Ivanov and others
00005  * Modified by:
00006  * Created:     2007-05-19 11:29:32
00007  * Last modify: 2007-12-09 17:12:51 ivanovp {Time-stamp}
00008  * Copyright:   (C) Peter Ivanov, 2007
00009  * Licence:     GPL
00010  */
00011 /**
00012  * \file 449stk2.c
00013  * \brief Main program
00014  * \author Peter Ivanov and others
00015  */
00016 
00017 #include <msp430x44x.h>
00018 #include <msp430/basic_clock.h>
00019 #include <msp430/system_clock.h>
00020 #include <stdarg.h>
00021 #include <stdlib.h>
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 #include <signal.h>
00026 #include <math.h>
00027 #include "lcd.h"
00028 #include "uart.h"
00029 #include "rtc.h"
00030 //#include "rtc_calendar.h"
00031 #include "menu.h"
00032 #include "common.h"
00033 #include "nrf24l01.h"
00034 
00035 #define SIZE_OPTIMIZED
00036 
00037 #ifdef SIZE_OPTIMIZED
00038 #define TEST_DELAY  250
00039 #else
00040 #define TEST_DELAY  5000
00041 #endif
00042 
00043 uint8_t menuOn = 0;
00044 
00045 uint8_t tickOn = 0;
00046 uint8_t mode24hOn = 1;
00047 uint8_t alarmHour = 0x12;
00048 uint8_t alarmPm = 0;
00049 uint8_t alarmMinute = 0;
00050 uint8_t alarmOn = 0;
00051 //uint8_t alarmMinute = 1; // DEBUG
00052 //uint8_t alarmOn = 1;     // DEBUG
00053 volatile uint8_t alarmStarted = 0;
00054 //volatile uint32_t time = 0;
00055 
00056 /**
00057  * Software delay.
00058  *
00059  * @author Peter Ivanov
00060  *
00061  * Input:
00062  *    @param a Loop count.
00063  */
00064 void delay (unsigned int a)                           //9+a*12 cycles
00065 {
00066     unsigned int i;
00067     for (i = 0; i < a; i++);
00068 }
00069 
00070 /**
00071  * Software longer delay.
00072  *
00073  * @author Peter Ivanov
00074  *
00075  * Input:
00076  *    @param b Loop count.
00077  */
00078 void delayX (unsigned int b)
00079 {
00080     unsigned int i;
00081     for (i = 0; i < b; i++) 
00082     {
00083         delay (255);
00084     }
00085 }
00086 
00087 /**
00088  * Switches red LED on/off.
00089  *
00090  * @author Peter Ivanov
00091  *
00092  * Input:
00093  *    @param on TRUE: switch on, FALSE: switch off.
00094  */
00095 void setStatusLed (bool_t on)
00096 {
00097     if (on)
00098     {
00099         P1OUT &= ~STATUS_LED; // switch on status LED
00100     }
00101     else  
00102     {
00103         P1OUT |= STATUS_LED;  // switch off status LED
00104     }
00105 }
00106 
00107 /**
00108  * Switches buzzer on or off. You should frequently switch on and off to 
00109  * generate a sound.
00110  *
00111  * @author Peter Ivanov
00112  *
00113  * Input:
00114  *    @param on TRUE: switch on, FALSE: switch off.
00115  */
00116 void setBuzzer (bool_t on)
00117 {
00118     if (on)
00119     {
00120         P1OUT &= ~BIT0;    //P1.2
00121         P1OUT |= BIT2;     //P1.3
00122     }
00123     else
00124     {
00125         P1OUT |= BIT0;     //P1.2
00126         P1OUT &= ~BIT2;    //P1.3
00127     }
00128 }
00129 
00130 /**
00131  * Generates tick sound.
00132  *
00133  * @author Peter Ivanov
00134  */
00135 void tick (void)
00136 {
00137     setBuzzer (TRUE);
00138 #ifndef SIZE_OPTIMIZED
00139     delay (50);
00140 #endif
00141     setBuzzer (FALSE);
00142 }
00143 
00144 /**
00145  * Generates sound.
00146  *
00147  * @author Peter Ivanov
00148  *
00149  * Input:
00150  *   @param Delay It is in inverse ratio to pitch.
00151  *   @param length Length of sound.
00152  */
00153 void sound (uint16_t Delay, uint length)
00154 {
00155     while (--length)
00156     {
00157         setBuzzer (TRUE);
00158         delay (Delay);
00159         setBuzzer (FALSE);
00160         delay (Delay);
00161     }
00162 }
00163 
00164 /**
00165  * Samples and returns AD-converter value of channel 10
00166  * (MSP430's internal temperature reference diode)
00167  * NOTE: to get a more exact value, 8-times oversampling is used
00168  *
00169  * @author Andreas Dannenberg, Peter Ivanov
00170  *
00171  * Output:
00172  *   @return Temperature.
00173  */
00174 unsigned int getTemp ()
00175 {
00176     unsigned long rv;
00177 
00178     ADC12CTL0 = ADC12ON | SHT0_15 | MSH | REFON;    // ADC on, int. ref. on (1,5 V),
00179     // multiple sample & conversion
00180     ADC12CTL1 = ADC12SSEL_2 | ADC12DIV_7 | CSTARTADD_0 | CONSEQ_1 | SHP;   // MCLK / 8 = 1 MHz
00181 
00182     ADC12MCTL0 = SREF_1 | INCH_10;                  // int. ref., channel 10
00183     ADC12MCTL1 = SREF_1 | INCH_10;                  // int. ref., channel 10
00184     ADC12MCTL2 = SREF_1 | INCH_10;                  // int. ref., channel 10
00185     ADC12MCTL3 = SREF_1 | INCH_10;                  // int. ref., channel 10
00186     ADC12MCTL4 = SREF_1 | INCH_10;                  // int. ref., channel 10
00187     ADC12MCTL5 = SREF_1 | INCH_10;                  // int. ref., channel 10
00188     ADC12MCTL6 = SREF_1 | INCH_10;                  // int. ref., channel 10
00189     ADC12MCTL7 = EOS | SREF_1 | INCH_10;            // int. ref., channel 10, last seg.
00190                                                     
00191     ADC12CTL0 |= ENC;                               // enable conversion
00192     ADC12CTL0 |= ADC12SC;                           // sample & convert
00193                                                     
00194     while (ADC12CTL0 & ADC12SC);                    // wait until conversion is complete
00195                                                     
00196     ADC12CTL0 &= ~ENC;                              // disable conversion
00197 
00198     rv = ADC12MEM0;                                 // sum up values...
00199     rv += ADC12MEM1;
00200     rv += ADC12MEM2;
00201     rv += ADC12MEM3;
00202     rv += ADC12MEM4;
00203     rv += ADC12MEM5;
00204     rv += ADC12MEM6;
00205     rv += ADC12MEM7;
00206 
00207     // Peter Ivanov: switch off AD module to save power
00208     ADC12CTL0 &= ~(ADC12ON | REFON);
00209 
00210     rv >>= 3;                                       // ... and divide by 8
00211     return rv;
00212 }
00213 
00214 /** 
00215  * Temperature offset in Celsius. This value is for my MSP430-449STK2 board!
00216  *
00217  * My calibration:
00218  * A/D: 2799 -> 7.1 Celsius
00219  * A/D: 2965 -> 25.0 Celsius
00220  */
00221 #define TEMP_OFFSET     -3.3
00222 
00223 /**
00224  * Calculates internal temperature of MSP430.
00225  * You should calibrate the value! Change the TEMP_OFFSET define!
00226  *
00227  * @author Peter Ivanov
00228  *
00229  * Output:
00230  *   @return Temperature in Celsius-degrees.
00231  */
00232 float getTempCelsius ()
00233 {
00234     unsigned int temp =  getTemp ();
00235     float tempCelsius = (1.5 * temp / 4096 - 0.986) / 0.00355 + TEMP_OFFSET;
00236 #if 0
00237     UART_printf ("%s(): temp: %i tempCelsius: %i.%02i\r\n", __FUNCTION__, 
00238             temp, (int) (tempCelsius), ((int) ((tempCelsius - floor (tempCelsius)) * 100.0))
00239             );
00240 #endif
00241     return tempCelsius;
00242 }
00243 
00244 /**
00245  * Increase BCD variable by one.
00246  *
00247  * @author Peter Ivanov
00248  *
00249  * Input/Output:
00250  *   @param variable Pointer to variable to increase.
00251  */
00252 void bcdInc (uint8_t* variable)
00253 {
00254     uint8_t in, out;
00255     in = *variable;
00256     asm (
00257             "clrc\n"
00258             "dadd.b #0x01, %1\n"
00259             "mov.b %1, %0\n"
00260             : "=r" (out) // %0  // output operands
00261             : "r" (in)   // %1  // input operands
00262 //          :                   // clobbered registers
00263         );
00264     *variable = out;
00265 }
00266 
00267 /**
00268  * Decrease BCD variable by one.
00269  *
00270  * @author Peter Ivanov
00271  *
00272  * Input/Output:
00273  *   @param variable Pointer to variable to decrease.
00274  */
00275 void bcdDec (uint8_t* variable)
00276 {
00277     uint8_t in, out;
00278     in = *variable;
00279     asm (
00280             "setc\n"
00281             "dadd.b #0x98, %1\n"
00282             "mov.b %1, %0\n"
00283             : "=r" (out) // %0  // output operands
00284             : "r" (in)   // %1  // input operands
00285 //          : ""                // clobbered registers
00286         );
00287     *variable = out;
00288 }
00289 
00290 /**
00291  * Initializes Real-Time-Clock system: enables watchdog interrupt. We will get 
00292  * an interrupt in every second.
00293  *
00294  * @author Peter Ivanov
00295  */
00296 void RTC_init ()
00297 {
00298     FLL_CTL0 |= XCAP18PF;       // Set load cap for 32k xtal
00299     WDTCTL = WDT_ADLY_1000;     // WDT interrupt in every second
00300     IE1 |= WDTIE;
00301     _EINT ();
00302 }
00303 
00304 /// Variable changed by watchdog ISR.
00305 volatile uint8_t colonOn = 0;
00306 
00307 /// Temperature in Celsius multiplied by 10.
00308 int16_t tempCelsius;
00309 
00310 /**
00311  * Updates LCD display to show clock and temperature values.
00312  *
00313  * @author Peter Ivanov
00314  */
00315 void updateDisplay ()
00316 {
00317     int8_t hour;
00318     if (menuOn || alarmStarted)
00319     {
00320         LCD_writeClockDigit (0, TI_minute & 0x0F);
00321         LCD_writeClockDigit (1, TI_minute >> 4);
00322         if (mode24hOn)
00323         {
00324             hour = get24Hour (TI_hour, TI_PM);
00325             LCD_writeClockDigit (2, hour & 0x0F);
00326             LCD_writeClockDigit (3, hour >> 4);
00327             LCD_setClockDot (0, 0);
00328         }
00329         else
00330         {
00331             LCD_writeClockDigit (2, TI_hour & 0x0F);
00332             LCD_writeClockDigit (3, TI_hour >> 4);
00333             LCD_setClockDot (0, TI_PM);
00334         }
00335         LCD_setClockColon (colonOn);
00336     }
00337     else
00338     {
00339         if (mode24hOn)
00340         {
00341             hour = get24Hour (TI_hour, TI_PM);
00342             LCD_printf ("%02X%02X%02X ", hour, TI_minute, TI_second);
00343             LCD_setClockDot (0, 0);
00344         }
00345         else
00346         {
00347             LCD_printf ("%02X%02X%02X ", TI_hour, TI_minute, TI_second);
00348             LCD_setClockDot (0, TI_PM);
00349         }
00350         LCD_writeLetter (2, '.');
00351         //if (TI_second & 1)
00352         if (colonOn)
00353         {
00354             LCD_writeLetter (4, ':');
00355         }
00356         if ((TI_second & 0x0F) == 0x00)
00357         {
00358             // update temperature in every 10 seconds
00359             tempCelsius = getTempCelsius () * 10.0;
00360         }
00361         LCD_writeClockInt (tempCelsius, FALSE);
00362         LCD_setClockDot (0, TRUE);
00363     }
00364     if (alarmOn)
00365     {
00366         if (TI_hour == alarmHour && TI_minute == alarmMinute && 
00367                 TI_second == 0x00)
00368         {
00369             alarmStarted = 1;
00370         }
00371         if (alarmStarted)
00372         {
00373             if (!(TI_second & 1))
00374             {
00375                 setStatusLed (TRUE);
00376                 LCD_printf (" ALARM ");
00377 #ifdef SIZE_OPTIMIZED
00378                 sound (100, 500);
00379 #else
00380                 sound (2000, 500);
00381 #endif
00382             }
00383             else
00384             {
00385                 setStatusLed (FALSE);
00386                 LCD_printf ("       ");
00387             }
00388         }
00389         if (alarmStarted && TI_second == 0x29)
00390         {
00391             // Stop alarm after 30 seconds
00392             alarmStarted = 0;
00393         }
00394     }
00395 }
00396 
00397 volatile uint8_t clockOn = 1;
00398 /**
00399  * Interrupt service routine of watchdog. It is called in every second.
00400  *
00401  * @author Peter Ivanov
00402  */
00403 interrupt (WDT_VECTOR) wakeup watchdog_isr (void)
00404 {
00405     //time++;
00406     if (clockOn)
00407     {
00408         incrementSeconds ();
00409         colonOn = !colonOn;
00410         updateDisplay ();
00411         if (tickOn && !alarmStarted)
00412         {
00413             tick ();
00414         }
00415     }
00416     //LPM3_EXIT;
00417 }
00418 
00419 /// Previous status of buttons
00420 uint8_t buttonStatusPrev;
00421 /// Current status of buttons
00422 uint8_t buttonStatus;
00423 /// Pressed buttons
00424 uint8_t buttonPressed;
00425 /// Released buttons
00426 uint8_t buttonReleased;
00427 
00428 /**
00429  * Keyboard handler function. You should call this function frequently, because
00430  * it uses polling method.
00431  *
00432  * @author Peter Ivanov
00433  */
00434 void buttonHandler ()
00435 {
00436     if (buttonPressed)
00437     {
00438         // szoftveres pergesmentesites
00439 #ifdef SIZE_OPTIMIZED
00440         delayX (300);
00441 #else
00442         delayX (2000);
00443 #endif
00444     }
00445     buttonStatusPrev = buttonStatus;
00446     buttonStatus = ~(P3IN & BTN_MASK);
00447     buttonPressed = (buttonStatusPrev ^ buttonStatus) & buttonStatus;
00448     buttonReleased = (buttonStatusPrev ^ buttonStatus) & buttonStatusPrev;
00449     if (buttonPressed && alarmStarted)
00450     {
00451         setStatusLed (FALSE);
00452         setBuzzer (FALSE);
00453         LCD_printf ("       ");
00454         alarmStarted = 0;
00455 
00456         buttonPressed = 0;
00457         MENU_showCurrentMenuItem ();
00458     }
00459 }
00460 
00461 /*
00462  * ### MENU FUNCTIONS ###
00463  */
00464 
00465 /**
00466  * Decrease hour variable by one (BCD).
00467  *
00468  * @author Peter Ivanov
00469  */
00470 void hourDec (uint8_t* hour, uint8_t* pm)
00471 {
00472     if (*hour == 0x12)
00473     {
00474         if (*pm)
00475         {
00476             *pm = 0;
00477         }
00478         else
00479         {
00480             *pm = 1;
00481         }
00482     }
00483     bcdDec (hour);
00484     if (*hour == 0x00)
00485     {
00486         *hour = 0x12;
00487     }
00488 }
00489 
00490 /**
00491  * Increase hour variable by one (BCD).
00492  *
00493  * @author Peter Ivanov
00494  */
00495 void hourInc (uint8_t* hour, uint8_t* pm)
00496 {
00497     bcdInc (hour);
00498     if (*hour >= 0x13)
00499     {
00500         *hour = 1;
00501     }
00502     if (*hour == 0x12)
00503     {
00504         if (*pm)
00505         {
00506             *pm = 0;
00507         }
00508         else
00509         {
00510             *pm = 1;
00511         }
00512     }
00513 }
00514 
00515 /**
00516  * Menu callback function to set hour.
00517  *
00518  * @author Peter Ivanov
00519  */
00520 void setClockHour ()
00521 {
00522     uint8_t hour = TI_hour;
00523     uint8_t pm = TI_PM;
00524     uint8_t write = 1;
00525     buttonPressed = 0;
00526     LCD_showArrows (LCD_ARROW_ALL);
00527     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00528     {
00529         buttonHandler ();
00530         if (buttonPressed & BTN_UP)
00531         {
00532             hourInc (&hour, &pm);
00533             write = 1;
00534         }
00535         if (buttonPressed & BTN_DOWN)
00536         {
00537             hourDec (&hour, &pm);
00538             write = 1;
00539         }
00540         if (write)
00541         {
00542             if (mode24hOn)
00543             {
00544                 LCD_printf ("HOUR %02X", get24Hour (hour, pm));
00545             }
00546             else
00547             {
00548                 LCD_printf ("H %s %02X", pm ? "PM" : "AM", hour);
00549             }
00550             write = 0;
00551         }
00552     }
00553     if (buttonPressed & BTN_OK)
00554     {
00555         clockOn = 0;
00556         TI_hour = hour;
00557         TI_PM = pm;
00558         updateDisplay ();
00559         clockOn = 1;
00560     }
00561 }
00562 
00563 /**
00564  * Decrease minute variable by one (BCD).
00565  *
00566  * @author Peter Ivanov
00567  */
00568 void minDec (uint8_t* min)
00569 {
00570     bcdDec (min);
00571     if (*min == 0x99)
00572     {
00573         *min = 0x59;
00574     }
00575 }
00576 
00577 /**
00578  * Increase minute variable by one (BCD).
00579  *
00580  * @author Peter Ivanov
00581  */
00582 void minInc (uint8_t* min)
00583 {
00584     bcdInc (min);
00585     if (*min >= 0x60)
00586     {
00587         *min = 0x00;
00588     }
00589 }
00590 
00591 /**
00592  * Menu callback function to set minute.
00593  *
00594  * @author Peter Ivanov
00595  */
00596 void setClockMin ()
00597 {
00598     uint8_t min = TI_minute;
00599     uint8_t write = 1;
00600     buttonPressed = 0;
00601     LCD_showArrows (LCD_ARROW_ALL);
00602     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00603     {
00604         buttonHandler ();
00605         if (buttonPressed & BTN_UP)
00606         {
00607             minInc (&min);
00608             write = 1;
00609         }
00610         if (buttonPressed & BTN_DOWN)
00611         {
00612             minDec (&min);
00613             write = 1;
00614         }
00615         if (write)
00616         {
00617             LCD_printf ("MIN  %02X", min);
00618             write = 0;
00619         }
00620     }
00621     if (buttonPressed & BTN_OK)
00622     {
00623         clockOn = 0;
00624         TI_minute = min;
00625         TI_second = 0;
00626         updateDisplay ();
00627         clockOn = 1;
00628     }
00629 }
00630 
00631 /**
00632  * Menu callback function to 24 hour mode on/off.
00633  *
00634  * @author Peter Ivanov
00635  */
00636 void setMode24h ()
00637 {
00638     uint8_t write = 1;
00639     uint8_t on = mode24hOn;
00640     buttonPressed = 0;
00641     LCD_showArrows (LCD_ARROW_ALL);
00642     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00643     {
00644         buttonHandler ();
00645         if ((buttonPressed & BTN_UP) || (buttonPressed & BTN_DOWN))
00646         {
00647             on = !on;
00648             write = 1;
00649         }
00650         if (write)
00651         {
00652             LCD_printf ("24H %s", on ? "ON " : "OFF");
00653             write = 0;
00654         }
00655     }
00656     if (buttonPressed & BTN_OK)
00657     {
00658         clockOn = 0;
00659         mode24hOn = on;
00660         updateDisplay ();
00661         clockOn = 1;
00662     }
00663 }
00664 
00665 /**
00666  * Menu callback function to set tick sound on/off.
00667  *
00668  * @author Peter Ivanov
00669  */
00670 void setTick ()
00671 {
00672     uint8_t write = 1;
00673     uint8_t on = tickOn;
00674     buttonPressed = 0;
00675     LCD_showArrows (LCD_ARROW_ALL);
00676     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00677     {
00678         buttonHandler ();
00679         if ((buttonPressed & BTN_UP) || (buttonPressed & BTN_DOWN))
00680         {
00681             on = !on;
00682             write = 1;
00683         }
00684         if (write)
00685         {
00686             LCD_printf ("TCK %s", on ? "ON " : "OFF");
00687             write = 0;
00688         }
00689     }
00690     if (buttonPressed & BTN_OK)
00691     {
00692         tickOn = on;
00693     }
00694 }
00695 
00696 /**
00697  * Menu callback function to set hour of alarm.
00698  *
00699  * @author Peter Ivanov
00700  */
00701 void setAlarmHour ()
00702 {
00703     uint8_t hour = alarmHour;
00704     uint8_t pm = alarmPm;
00705     uint8_t write = 1;
00706     buttonPressed = 0;
00707     LCD_showArrows (LCD_ARROW_ALL);
00708     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00709     {
00710         buttonHandler ();
00711         if (buttonPressed & BTN_UP)
00712         {
00713             hourInc (&hour, &pm);
00714             write = 1;
00715         }
00716         if (buttonPressed & BTN_DOWN)
00717         {
00718             hourDec (&hour, &pm);
00719             write = 1;
00720         }
00721         if (write)
00722         {
00723             if (mode24hOn)
00724             {
00725                 LCD_printf ("HOUR %02X", get24Hour (hour, pm));
00726             }
00727             else
00728             {
00729                 LCD_printf ("H %s %02X", pm ? "PM" : "AM", hour);
00730             }
00731             write = 0;
00732         }
00733     }
00734     if (buttonPressed & BTN_OK)
00735     {
00736         clockOn = 0;
00737         alarmHour = hour;
00738         alarmPm = pm;
00739         updateDisplay ();
00740         clockOn = 1;
00741     }
00742 }
00743 
00744 /**
00745  * Menu callback function to set minute of alarm.
00746  *
00747  * @author Peter Ivanov
00748  */
00749 void setAlarmMin ()
00750 {
00751     uint8_t min = alarmMinute;
00752     uint8_t write = 1;
00753     buttonPressed = 0;
00754     LCD_showArrows (LCD_ARROW_ALL);
00755     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00756     {
00757         buttonHandler ();
00758         if (buttonPressed & BTN_UP)
00759         {
00760             minInc (&min);
00761             write = 1;
00762         }
00763         if (buttonPressed & BTN_DOWN)
00764         {
00765             minDec (&min);
00766             write = 1;
00767         }
00768         if (write)
00769         {
00770             LCD_printf ("MIN  %02X", min);
00771             write = 0;
00772         }
00773     }
00774     if (buttonPressed & BTN_OK)
00775     {
00776         clockOn = 0;
00777         alarmMinute = min;
00778         updateDisplay ();
00779         clockOn = 1;
00780     }
00781 }
00782 
00783 /**
00784  * Menu callback function to switch on/off alarm.
00785  *
00786  * @author Peter Ivanov
00787  */
00788 void setAlarmOnOff ()
00789 {
00790     uint8_t write = 1;
00791     uint8_t on = alarmOn;
00792     buttonPressed = 0;
00793     LCD_showArrows (LCD_ARROW_ALL);
00794     while (!((buttonPressed & BTN_QUIT) || (buttonPressed & BTN_OK)))
00795     {
00796         buttonHandler ();
00797         if ((buttonPressed & BTN_UP) || (buttonPressed & BTN_DOWN))
00798         {
00799             on = !on;
00800             write = 1;
00801         }
00802         if (write)
00803         {
00804             LCD_printf ("ALM %s", on ? "ON " : "OFF");
00805             write = 0;
00806         }
00807     }
00808     if (buttonPressed & BTN_OK)
00809     {
00810         clockOn = 0;
00811         alarmOn = on;
00812         updateDisplay ();
00813         clockOn = 1;
00814     }
00815 }
00816 
00817 #ifdef NRF24L01
00818 /**
00819  * Menu point to test extension module MOD-RF24Lx (2.4 GHz transceiver module) in master mode.
00820  */
00821 void rf24lMasterTest ()
00822 {
00823     uint8_t inByte;
00824     uint8_t outByte = 0x7F;
00825 
00826     LCD_printf ("NRF INIT");
00827     NRF_init ();
00828     LCD_printf ("NRF OK  ");
00829 
00830     buttonPressed = 0;
00831     LCD_clearArrows (LCD_ARROW_RIGHT | LCD_ARROW_UP | LCD_ARROW_DOWN);
00832     LCD_showArrows (LCD_ARROW_LEFT);
00833     while (!(buttonPressed & BTN_QUIT))
00834     {
00835         buttonHandler ();
00836 
00837         if (buttonPressed & BTN_OK)
00838         {
00839             NRF_send (outByte);
00840             NRF_prepareForReceive ();
00841             LCD_printf (">%02X    ", outByte);
00842             outByte++;
00843         }
00844         if (NRF_receive (&inByte))
00845         {
00846             LCD_printf ("%02X%02X %s", outByte - 1, inByte, inByte == (256 - outByte) ? "OK" : "ER");
00847         }
00848 
00849         delayX (10);
00850     };
00851 }
00852 
00853 /**
00854  * Menu point to test extension module MOD-RF24Lx (2.4 GHz transceiver module) in slave mode.
00855  */
00856 void rf24lSlaveTest ()
00857 {
00858     uint8_t inByte;
00859     uint8_t outByte;
00860 
00861     LCD_printf ("NRF INIT");
00862     NRF_init ();
00863     LCD_printf ("NRF OK  ");
00864 
00865     buttonPressed = 0;
00866     LCD_clearArrows (LCD_ARROW_RIGHT | LCD_ARROW_UP | LCD_ARROW_DOWN);
00867     LCD_showArrows (LCD_ARROW_LEFT);
00868     while (!(buttonPressed & BTN_QUIT))
00869     {
00870         buttonHandler ();
00871 
00872         if (NRF_receive (&inByte))
00873         {
00874             outByte = 255 - inByte;
00875             delayX (100); // wait for the other side to switch to RX mode!
00876             NRF_send (outByte);
00877             NRF_prepareForReceive ();
00878             LCD_printf ("<%02X >%02X", inByte, outByte);
00879         }
00880 
00881         delayX (10);
00882     };
00883 }
00884 #endif
00885 
00886 /**
00887  * Clock sub-menu.
00888  * The length of menu title must be seven characters long (add spaces to the end)!
00889  *
00890  * @author Peter Ivanov
00891  */
00892 menuPoint_t setClockMenu[] =
00893 {
00894     //1234567   sub-menu        callback function
00895     {"HOUR   ", NULL,           &setClockHour},
00896     {"MINUTE ", NULL,           &setClockMin},
00897     {"24H    ", NULL,           &setMode24h},
00898     {"TICK   ", NULL,           &setTick},
00899     {NULL,      NULL,           NULL}   // end of menu
00900 };
00901 
00902 /**
00903  * Alarm sub-menu.
00904  * The length of menu title must be seven characters long (add spaces to the end)!
00905  *
00906  * @author Peter Ivanov
00907  */
00908 menuPoint_t setAlarmMenu[] =
00909 {
00910     //1234567   sub-menu        callback function
00911     {"HOUR   ", NULL,           &setAlarmHour},
00912     {"MINUTE ", NULL,           &setAlarmMin},
00913     {"ON/OFF ", NULL,           &setAlarmOnOff},
00914     {NULL,      NULL,           NULL}   // end of menu
00915 };
00916 
00917 /**
00918  * RF test sub-menu. This menu is for test MOD-NRF24Lx.
00919  * The length of menu title must be seven characters long (add spaces to the end)
00920  *
00921  * @author Peter Ivanov
00922  */
00923 menuPoint_t rfTestMenu[] =
00924 {
00925     //1234567   sub-menu        callback function
00926     {"MASTER ", NULL,           &rf24lMasterTest},
00927     {"SLAVE  ", NULL,           &rf24lSlaveTest},
00928     {NULL,      NULL,           NULL}   // end of menu
00929 };
00930 
00931 /**
00932  * Root menu. 
00933  * The length of menu title must be seven characters long (add spaces to the end)!
00934  *
00935  * @author Peter Ivanov
00936  */
00937 menuPoint_t rootMenu[] = 
00938 {
00939     //1234567   sub-menu        callback function
00940 #ifdef NRF24L01
00941     {"RF TEST", rfTestMenu,     NULL},
00942 #endif
00943     {"SET CLK", setClockMenu,   NULL},
00944     {"SET ALM", setAlarmMenu,   NULL},
00945     {NULL,      NULL,           NULL}   // end of menu
00946 };
00947 
00948 /**
00949  * Initialize system.
00950  *
00951  * @author Peter Ivanov and others
00952  */
00953 void init ()
00954 {
00955     WDTCTL = WDTPW | WDTHOLD;                       // stop watchdog timer
00956 
00957     FLL_CTL0 &= ~XTS_FLL;                           // XT1 as low-frequency
00958     // !!!!!!!!!!!
00959     FLL_CTL0 = XCAP18PF;                            // set load capacitance for 32k xtal
00960     // !!!!!!!!!!!
00961 
00962     _BIC_SR (OSCOFF);                               // turn on XT1 oscillator
00963 
00964     do                                              // wait in loop until crystal is stable
00965     {
00966         IFG1 &= ~OFIFG;
00967     }
00968     while (IFG1 & OFIFG);
00969 
00970     FLL_CTL1 &= ~FLL_DIV0;                          // ACLK = XT1
00971     FLL_CTL1 &= ~FLL_DIV1;
00972 
00973     IFG1 &= ~OFIFG;                                 // clear osc. fault int. flag
00974 
00975     FLL_CTL1 &= ~SELM0;                             // set DCO as MCLK
00976     FLL_CTL1 &= ~SELM1;
00977 
00978 //  SVSCTL = 0x68;                                  //brown out
00979 
00980 //  WDTCTL = WDTPW + WDTHOLD;                       // Stop watchdog timer
00981 
00982 //  SCFI0 = BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7;    
00983 //  SCFI0 |= FN_4;                                  // x2 DCO frequency, 8MHz nominal DCO
00984 //  SCFQCTL = SCFQ_1M;            
00985 
00986 //  FLL_CTL0 = /*DCOPLUS + */XCAP10PF;                  //Set load Cap. for Cristal = 10pF
00987 // x2 DCO frequency, 8MHz nominal DCO    
00988 
00989 //  FLL_CTL1 |= SELM_XT2;                             //Select XT2 for CPU MCLK
00990 //  SCFI1 = 0;
00991 //  SCFQCTL = SCFQ_M | SCFQ_1M;                       //M=1, 1Mhz
00992 //  _BIS_SR(SCG0+SCG1);                               //disable DCO in status_reg
00993 //  delayX(200);
00994 
00995     UART_init ();
00996     UART_printf (
00997             "\r\n"
00998             "\r\n"
00999             "MSP430-449STK2 board started\r\n"
01000             "Compiled on " __DATE__ " " __TIME__ "\r\n"
01001             "\r\n"
01002             );
01003     LCD_init ();
01004 
01005     // Initialize IO port
01006     P1SEL = BIT5;                                             //p1.5 is 32768Hz
01007     P1DIR = BIT5 | BIT3 | BIT0 | BIT2;                        //BUZ,LED are outputs
01008 
01009     LCD_all ();                                               // turn on all LCD segments
01010 #ifdef SIZE_OPTIMIZED
01011     sound (100, 100);        // if the code is optimized with -Os switch
01012 #else
01013     sound (2000, 100);    // if the code is optimized with -O3 switch
01014 #endif
01015     setStatusLed (TRUE);
01016     delayX (TEST_DELAY);
01017     setStatusLed (FALSE);
01018     delayX (TEST_DELAY);
01019     setStatusLed (TRUE);
01020     delayX (TEST_DELAY);
01021     setStatusLed (FALSE);
01022     LCD_clear ();
01023     
01024 #if 0
01025     LCD_writeLetter (0, ':'); // olimex
01026     LCD_printf (" rulez");
01027     delayX (TEST_DELAY * 2);
01028     LCD_clear ();
01029 #endif
01030 
01031     LCD_clearArrows (LCD_ARROW_LEFT | LCD_ARROW_UP | LCD_ARROW_DOWN);
01032     LCD_showArrows (LCD_ARROW_RIGHT);
01033 
01034     setTime (0x12, 0, 0, 0); // initialize time to 12:00:00 AM
01035     //setDate (2007, JANUARY, 1);
01036     RTC_init ();
01037     updateDisplay ();
01038 
01039     MENU_init (rootMenu);
01040 
01041     buttonStatusPrev = ~(P3IN & BTN_MASK);
01042 }
01043 
01044 /**
01045  * Main (end-less) loop.
01046  *
01047  * @author Peter Ivanov
01048  */
01049 void run ()
01050 {
01051     while (1)
01052     {
01053         buttonHandler ();
01054         if (buttonPressed)
01055         {
01056             if (menuOn)
01057             {
01058                 MENU_handler (buttonPressed);
01059                 if (currentMenuLevel == -1)
01060                 {
01061                     menuOn = FALSE;
01062                     LCD_clearClock ();
01063                     updateDisplay ();
01064                 }
01065             }
01066             else
01067             {
01068                 if (buttonPressed == BTN_OK)
01069                 {
01070                     menuOn = TRUE;
01071                     updateDisplay ();
01072                     MENU_handler (buttonPressed);
01073                 }
01074             }
01075         }
01076         if (UART_getCharIsReady ()) 
01077         {
01078             uint8_t c = UART_getChar ();
01079             UART_putChar (c); //echo
01080             if (c == '\r')           // CR
01081             {
01082                 UART_putChar ('\n'); // LF
01083                 // TODO: parser!
01084             }
01085         }
01086         //while ((DALLAS) == 0) testBuzzer ();                            //test DALLAS button
01087     }
01088 }
01089 
01090 /**
01091  * Entry point of the program.
01092  *
01093  * @author Peter Ivanov
01094  */
01095 int main (void)
01096 {
01097     init ();
01098     run ();
01099     return 0;
01100 }
01101 /**
01102  * @mainpage
01103  * This is an example project for the MSP430-449STK2 development board,
01104  * which is produced by Olimex Ltd. I've used Linux, but maybe you can use any
01105  * operating system which has GNU make and mspgcc (http://mspgcc.sourceforge.net/).
01106  * The code is from Olimex, Muneem Shahriar and me.
01107  *
01108  * Features:
01109  * - Clock and alarm functions
01110  * - Simple menu system:
01111  *   MENU_handler()
01112  * - LCD handling. Writing text to display with printf:
01113  *   LCD_printf()
01114  * - UART (RS232) handling. Writing text to the serial line with printf:
01115  *   UART_printf()
01116  * - MOD-NRF24Lx extension board handling: NRF_send() NRF_receive() <br>
01117  *   You should connect P3.0 to CSN, P3.1 to MOSI, P3.2 to MISO, P3.3 to CLK and P1.6 to CE using 
01118  *   the EXT connector of MSP430-449STK2.
01119  * 
01120  * Quick how-to for make:
01121  *  - Type <code>make</code> to compile the code.
01122  *  - Type <code>make flash</code> to flash program to the MSP430's ROM.
01123  *  - Type <code>make doc</code> to generate documentation.
01124  *
01125  * You can download this sample here:
01126  * http://dev.ivanov.eu/projects/msp430-449stk2_sample/msp430-449stk2_sample.tar.gz
01127  * http://dev.ivanov.eu/projects/msp430-449stk2_sample/msp430-449stk2_sample.zip
01128  *
01129  * Contact: Peter Ivanov 
01130  * E-mail: ivanovp__AT__gmail__DOT__com__NOSPAM
01131  */

Generated on Thu Dec 27 14:21:51 2007 for Sample MSP430-449STK2 project by  doxygen 1.5.1