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 /** \} */