Contiki 2.6

raven3290.c

Go to the documentation of this file.
00001 /*
00002  *     \mainpage ATmega3290p LCD Driver Software for Contiki Raven
00003 */
00004 /**
00005  *     \image html raven3290p.jpg
00006  *     \ingroup platform
00007  *     \defgroup lcdraven RZRAVEN LCD 3290p
00008  *
00009  *     \section intro_lcd LCD Introduction
00010  *
00011  *  This Raven LCD Driver application software was designed for a user interface
00012  *  to the Contiki 6LoWPAN collaboration on board the ATmega3290p. The
00013  *  LCD functionality uses the binary command set described in the release notes.
00014  *  These binary commands can also be found in a list of main.h.
00015  *
00016  *     \section compile_lcd Compiling Raven LCD Driver
00017  *
00018  *  The Raven LCD Driver is located in /platforms/avr-ravenlcd but it is not a contiki platform.
00019  *  $make TARGET=avr-ravenlcd will not work! Build it using the AVR Studio project and WinAVR or
00020  *  in Linux/Windows cmd/Cygwin $make in that directory. The AVR Studio dependency folder will confuse
00021  *  additional makes, use $make CYG=1 to bypass /dep creation or do $rm -R dep as needed.
00022  *   The .h file dependencies will be lost, so also $make CYG=1 clean after modifying any of those.
00023  *
00024  *
00025  *     \section fuses_lcd Board fuse settings
00026  *
00027  *  The Raven LCD (3290p device) requires the proper fuse settings to function properly.
00028  *  They are automatically set when flashing the .elf file. When using a .hex file set them manually:
00029  *   -# Raven LCD (3290p device)
00030  *      -# Extended: <b>0xFF</b> (No Brown Out)
00031  *      -# High: <b>0x99</b> (JTAG and ISP enabled, No OCDEN or EEPROM saving required)
00032  *      -# Low: <b>0xE2</b> (Use Int RC OSC - Start-up Time:6CK + 65ms)
00033  *
00034  *     \section notes_lcd Operation Release Notes
00035  *
00036  *  After programming the Raven LCD 3290p with the proper image, you will be introduced to
00037  *  the menu in the picture below:
00038  *
00039  *     \image html contiki_menu_3290.jpg
00040  *
00041  *  Operating the menu requires that the matching command set has been programmed into
00042  *  the ATmega1284 application. This will allow the menu to communicate properly and control the
00043  *  Contiki 6LoWPAN applcation on the 1284p.
00044  *
00045  *  During normal operation, you will need to make note of these <b>IMPORTANT</b> operating instructions:
00046  *   -# <b>Temp Sensor</b> - The temperature sensor shares the same GPIO as the JTAG interface for the 3290p.
00047  *   This requires the JTAG feature to be <b>disabled</b> in order to have proper temperature readings.
00048  *   -# <b>Debug Menu</b> - The DEBUG menu setting is used to configure this JTAG feature.
00049  *      -# If the JTAG feature is enabled during a temperature reading attempt,
00050  *      the menu will signal a <b>caution</b> symbol to the user letting them know the JTAG
00051  *      feature needs to be disabled.
00052  *     \image html caution.gif
00053  *      -# The JTAG header may also need to be physically disconnected from any external
00054  *      programming/debugging device in order to obtain correct temperature readings.
00055  *      -# The software will disable JTAG in sleep/doze modes. If the JTAG connection fails during
00056  *       reprogramming with AVR Studio, "try again with external reset" to recover.
00057  *   -# <b>Temp Data</b> - Once the temperature reading is proper, the user can send this reading
00058  *   to the webserver for Sensor Reading Data (<b>Once</b> or <b>Auto</b>). The webserver will
00059  *   only update the html data when <b>refreshed</b>.
00060  *   -# <b>EXT_SUPL_SIG</b> - This signal connects the external supply voltage to ADC2 through a divider.
00061  *   Enabling MEASURE_ADC2 in temp.h causes it to be sampled and sent to the 1284p along
00062  *   with the temperature.
00063  *
00064  *   More information about the operation of the Raven with Contiki can be found in the contikiwiki at http://www.sics.se/~adam/wiki/index.php/Avr_Raven.
00065  *   \sa http://www.sics.se/contiki/tutorials/tutorial-running-contiki-with-uipv6-and-sicslowpan-support-on-the-atmel-raven.html
00066  *
00067  *     \section binary_lcd Binary Command Description
00068  *
00069  *  Using the binary commmand list described in main.h, the 3290p will contruct a binary
00070  *  command serial frame to control the 1284p. An example command frame is contructed below:
00071  *   -# <b>0x01,0x01,0x81,0x01,0x04</b> - Send Ping Request number 1 to 1284p
00072  *       -# <b>0x01</b> - Start of binary command frame
00073  *       -# <b>0x01</b> - Length of binary command payload
00074  *       -# <b>0x81</b> - Binary command SEND_PING
00075  *       -# <b>0x01</b> - Payload value (eg. ping Request number 1)
00076  *       -# <b>0x04</b> - End of binary command frame
00077  *
00078  *  The following commands are sent to the 1284p.
00079  *   -# <b>SEND_TEMP - (0x80)</b>
00080  *   -# <b>SEND_PING - (0x81)</b>
00081  *   -# <b>SEND_ADC2 - (0x82)</b>
00082  *   -# <b>SEND_SLEEP- (0x83)</b>
00083  *   -# <b>SEND_WAKE - (0x84)</b>
00084  *
00085  *  The following commands are received from the 1284p.
00086  *   -# <b>REPORT_PING      - (0xC0)</b>
00087  *   -# <b>REPORT_PING_BEEP - (0xC1)</b>
00088  *   -# <b>REPORT_TEXT_MSG  - (0xC2)</b>
00089  *   -# <b>REPORT_WAKE      - (0xC3)</b>
00090  *
00091  *     \section sleep_lcd Sleep and Doze
00092  *   -# The Raven draws 27 milliamps when the 3290p and 1284p are both running and the RF230 in receive mode.
00093  *   -# Sleeping the 3290p and LCD display drops this to 21 ma with no loss in contiki functionality.
00094  *   -# The RF230 radio draws 15.5/16.5/7.8/1.5/0.02 ma in Rx/Tx/PLL_ON/TRX_OFF/SLEEP states.
00095  *    It is controlled by contiki on the 1284p according to the selected MAC power protocols to obtain the
00096  *    bulk of power savings; however the 3290p menu can tell it to sleep unconditionally or in a doze cycle.
00097  *   -# Unconditional SLEEP requires pushing the joystick button for wakeup. Once awake the 3290p sends
00098  *    SEND_WAKE commands to the 1284p until it responds with a REPORT_WAKE. "WAIT 1284p" is displayed during this time.
00099  *    Current draw is 40 microamps.
00100  *   -# As configured, doze sleeps the 3290p for 5 seconds after telling 1284p to sleep for 4 seconds. The 3290p
00101  *    wakes briefly to send temperature and voltage to the 1284p (which should be awake at this time), then tells it to
00102  *    sleep again. Thus the 1284p will be active 20% of the time, although it may ignore the command to sleep
00103  *    if there are active TCP connections.  The 3290p energy usage is essentially zero in this mode; total savings will
00104  *    depend on actual 1284p wake time and radio usage. Alter the timings as desired, or comment out the 1284p sleep
00105  *    command to shut down only the 3290p in doze mode.
00106 */
00107 /*
00108  *  Copyright (c) 2008  Swedish Institute of Computer Science
00109  *  All rights reserved.
00110  *
00111  *  Redistribution and use in source and binary forms, with or without
00112  *  modification, are permitted provided that the following conditions are met:
00113  *
00114  *  * Redistributions of source code must retain the above copyright
00115  *    notice, this list of conditions and the following disclaimer.
00116  *  * Redistributions in binary form must reproduce the above copyright
00117  *    notice, this list of conditions and the following disclaimer in
00118  *    the documentation and/or other materials provided with the
00119  *    distribution.
00120  *  * Neither the name of the copyright holders nor the names of
00121  *    contributors may be used to endorse or promote products derived
00122  *    from this software without specific prior written permission.
00123  *
00124  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00125  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00126  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00127  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00128  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00129  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00130  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00131  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00132  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00133  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00134  * POSSIBILITY OF SUCH DAMAGE.
00135  */
00136 /**
00137  * \file
00138  *
00139  * \brief
00140  *      This is the main file for the Raven LCD application.
00141  *
00142  * \author
00143  *      Mike Vidales mavida404@gmail.com
00144  *
00145  */
00146 
00147 #include "lcd.h"
00148 #include "key.h"
00149 #include "main.h"
00150 #include "uart.h"
00151 #include "timer.h"
00152 #include "menu.h"
00153 #include "temp.h"
00154 
00155 #include <avr/io.h>
00156 #include <avr/fuse.h>
00157 FUSES =
00158         {
00159                 .low = 0xe2,
00160                 .high = 0x99,
00161                 .extended = 0xff,
00162         };
00163 
00164 
00165 /** \ingroup lcdraven
00166     \defgroup lcd LCD Functions and data
00167  *  \{
00168 */
00169 
00170 #if defined( DOXYGEN )
00171 const char menu_text0[];
00172 const char menu_text1[];
00173 const char menu_text2[];
00174 const char menu_text3[];
00175 const char menu_text4[];
00176 const char menu_text5[];
00177 const char menu_text6[];
00178 const char menu_text7[];
00179 const char menu_text8[];
00180 const char menu_text9[];
00181 const char menu_text10[];
00182 const char menu_text11[];
00183 const char menu_text12[];
00184 const char menu_text13[];
00185 const char menu_text14[];
00186 const char menu_text15[];
00187 const char menu_text16[];
00188 const char menu_text17[];
00189 const tmenu_item menu_items[18];
00190 #else  /* !DOXYGEN */
00191 /** \brief This is the menu text in Flash. See menu_items[] for menu operation. */
00192 const char menu_text0[] PROGMEM =  "CONTIKI";
00193 const char menu_text1[] PROGMEM =  "6LOWPAN";
00194 const char menu_text2[] PROGMEM =  "PING";
00195 const char menu_text3[] PROGMEM =  "PINGING";
00196 const char menu_text4[] PROGMEM =  "TEMP";
00197 const char menu_text5[] PROGMEM =  "MODE ";
00198 const char menu_text6[] PROGMEM =  "DEG F";
00199 const char menu_text7[] PROGMEM =  "DEG C";
00200 const char menu_text8[] PROGMEM =  "SEND";
00201 const char menu_text9[] PROGMEM =  "ONCE";
00202 const char menu_text10[] PROGMEM = "AUTO";
00203 const char menu_text11[] PROGMEM = "DEBUG";
00204 const char menu_text12[] PROGMEM = "DBG ON";
00205 const char menu_text13[] PROGMEM = "DBG OFF";
00206 const char menu_text14[] PROGMEM = "SENT";
00207 const char menu_text15[] PROGMEM = "SENDING";
00208 const char menu_text16[] PROGMEM = "SLEEP";
00209 const char menu_text17[] PROGMEM = "DOZE";
00210 
00211 /*---------------------------------------------------------------------------*/
00212 
00213 /**
00214  *   \brief Menus for user interface
00215  *
00216  *   This constructs the Raven 3290p menu for the Contiki and 6lowpan collaboration. This
00217  *   follows the struct description of tmenu_item.
00218  *
00219  *   { text, left, right, up, down, *state, tmenufunc enter_func}
00220 */
00221 const PROGMEM tmenu_item menu_items[18]  = {
00222     {menu_text0,   0,  2,  0,  0, 0,                       0                  },
00223     {menu_text1,   0,  2,  0,  0, 0,                       0                  },
00224     {menu_text2,   0,  3, 17,  4, 0,                       menu_ping_request  },
00225     {menu_text3,   2,  2,  2,  2, 0,                       0                  },
00226     {menu_text4,   0,  5,  2, 11, 0,                       0                  },
00227     {menu_text5,   4,  6,  8,  8, 0,                       0                  },
00228     {menu_text6,   5,  5,  7,  7, (uint8_t*)1,             menu_read_temp     },
00229     {menu_text7,   5,  5,  6,  6, (uint8_t*)0,             menu_read_temp     },
00230     {menu_text8,   4,  9,  5,  5, 0,                       0                  },
00231     {menu_text9,   8, 14, 10, 10, (uint8_t*)0,             menu_prepare_temp  },
00232     {menu_text10,  8, 15,  9,  9, (uint8_t*)1,             menu_prepare_temp  },
00233     {menu_text11,  0, 12,  4, 16, 0,                       0                  },
00234     {menu_text12, 11, 11, 13, 13, (uint8_t*)1,             menu_debug_mode    },
00235     {menu_text13, 11, 11, 12, 12, (uint8_t*)0,             menu_debug_mode    },
00236     {menu_text14, 9,  14, 14, 14, 0,                       0                  },
00237     {menu_text15, 10, 15, 15, 15, 0,                       0                  },
00238  //   {menu_text16,  0, 16, 11, 17, (uint8_t*)&menu_text16,  menu_run_sleep     },
00239  //   {menu_text17,  0, 17, 16,  2, (uint8_t*)&menu_text17,  menu_run_doze      },
00240     {menu_text16,  0, 16, 11, 17, (uint8_t*)1,  menu_run_sleep     },//display "sleep" on wake
00241     {menu_text17,  0, 17, 16,  2, (uint8_t*)1,  menu_run_doze      },//display "doze" on wake
00242 };
00243 #endif /* !DOXYGEN */
00244 
00245 key_state_t button=KEY_STATE_NO_KEY;
00246 tmenu_item menu;
00247 uint8_t count;
00248 uint8_t timeout_count;
00249 
00250 /*---------------------------------------------------------------------------*/
00251 
00252 /**
00253  *   \brief This will read the menu_items[] from the index requested.
00254  *
00255  *   \param ndx Position index of menu_items[] lookup.
00256 */
00257 void
00258 read_menu(uint8_t ndx)
00259 {
00260     /* Reads menu structure from Flash area */
00261     uint8_t i;
00262     uint8_t *src = (uint8_t*)&menu_items[ndx];
00263     uint8_t *dest = (uint8_t*)&menu;
00264 
00265     for (i=0;i<sizeof(tmenu_item);i++){
00266         *dest++ = pgm_read_byte(src+i);
00267     }
00268 }
00269 
00270 /*---------------------------------------------------------------------------*/
00271 char top_menu_text[20];
00272 /**
00273  *   \brief This will toggle the CONTIKI and 6LOWPAN LCD menus in the main
00274  *   menu position, unless alternate text has been sent from the 1284p.
00275  *   The other menus will display normally.
00276 */
00277 void
00278 check_main_menu(void)
00279 {
00280 uint8_t showtop=0;
00281 
00282     if(menu.text == menu_text0){
00283         read_menu(1);
00284         showtop=1;
00285     }
00286     else if(menu.text == menu_text1){
00287         read_menu(0);
00288         showtop=1;
00289     }
00290     if (showtop) {
00291         if (top_menu_text[0]) {
00292             lcd_puts(top_menu_text);
00293             return;
00294         }
00295     }
00296     lcd_puts_P(menu.text);
00297 }
00298 
00299 /*---------------------------------------------------------------------------*/
00300 
00301 /**
00302  *   \brief This will check for the temp menu screen to determine if we need to
00303  *   clear the 4 digit LCD segments or stop an auto temp send. Also check for
00304  *   stopping a ping request.
00305 */
00306 void
00307 check_menu(void)
00308 {
00309     if(menu.text == menu_text12){
00310        menu_clear_temp();
00311     }
00312 
00313     if(menu.text == menu_text10){
00314         menu_stop_temp();
00315     }
00316 
00317     if(menu.text == menu_text2){
00318         menu_stop_ping();
00319         lcd_num_clr();
00320     }
00321 }
00322 
00323 /*---------------------------------------------------------------------------*/
00324 
00325 /**
00326  *   \brief This is main...
00327 */
00328 int
00329 main(void)
00330 {
00331     lcd_init();
00332 
00333     key_init();
00334 
00335     uart_init();
00336 
00337     eeprom_init();
00338 
00339     temp_init();
00340 
00341     timer_init();
00342 
00343     sei();
00344 
00345     lcd_symbol_set(LCD_SYMBOL_RAVEN);
00346     lcd_symbol_set(LCD_SYMBOL_IP);
00347 
00348     /* Start with main menu */
00349     read_menu(0);
00350     /* and draw it */
00351     lcd_puts_P(menu.text);
00352 
00353     timer_start();
00354 
00355     for (;;){
00356         /* Make sure interrupts are always on */
00357         sei();
00358 
00359         /* The one second timer has fired. */
00360         if(timer_flag){
00361             timer_flag = false;
00362             /* Check if main menu needs toggled. */
00363             check_main_menu();
00364             /* Update LCD with temp data. */
00365             if(temp_flag){
00366                 menu_display_temp();
00367             }
00368             /* Auto send temp data to 1284p. */
00369             if(auto_temp){
00370                 menu_send_temp();
00371             }
00372             /* If ping mode, send 4 ping requests and then stop. */
00373             if(ping_mode){
00374                 if((PING_ATTEMPTS == count) && !timeout_flag){
00375                     count = 0;
00376                     timeout_count = 0;
00377                     menu_stop_ping();
00378                 }
00379                 else if(timeout_flag){
00380                     timeout_flag = false;
00381                     timeout_count++;
00382                     /* Display timeout message if all PING_ATTEMPTS were not successful. */
00383                     if(PING_ATTEMPTS == timeout_count){
00384                         lcd_puts_P(PSTR("PINGS FAILED"));
00385                     }
00386                 }
00387                 else{
00388                     count = menu_send_ping();
00389                 }
00390             }
00391         }
00392 
00393         /* Check for button press and deal with it */
00394         if (is_button()){
00395             /* Dispatch the button pressed */
00396             switch (get_button()){
00397                 case KEY_UP:
00398                     read_menu(menu.up);
00399                     lcd_puts_P(menu.text);
00400                     break;
00401                 case KEY_DOWN:
00402                     read_menu(menu.down);
00403                     lcd_puts_P(menu.text);
00404                     break;
00405                 case KEY_LEFT:
00406                     read_menu(menu.left);
00407                     lcd_puts_P(menu.text);
00408                     break;
00409                 case KEY_RIGHT:
00410                     /*
00411                      * Check to see if we should show another menu or
00412                      * run a function
00413                      */
00414                     if (!menu.enter_func){
00415                         /* Just another menu to display */
00416                         read_menu(menu.right);
00417                         lcd_puts_P(menu.text);
00418                         break;
00419                     }
00420                     /* Drop through here */
00421                 case KEY_ENTER:
00422                     /* Call the menu function on right or enter buttons */
00423                     if (menu.enter_func){
00424                         menu.enter_func(menu.state);
00425                         if (menu.state){
00426                             /*
00427                              * We just called a selection menu (not a test),
00428                              * so re-display the text for this menu level
00429                              */
00430                             lcd_puts_P(menu.text);
00431                         }
00432                         /* After enter key, check the right button menu and display. */
00433                         read_menu(menu.right);
00434                         lcd_puts_P(menu.text);
00435                     }
00436                     break;
00437                 default:
00438                     break;
00439             }
00440             /* After button press, check for menus... */
00441             check_menu();
00442         }
00443         /* Process any progress frames */
00444         uart_serial_rcv_frame(false);
00445     } /* end for(). */
00446 } /* end main(). */
00447 
00448 /** \} */