nes-proj/platform/avr-ravenlcd/raven3290.c

449 lines
17 KiB
C

/*
* \mainpage ATmega3290p LCD Driver Software for Contiki Raven
*/
/**
* \image html raven3290p.jpg
* \ingroup platform
* \defgroup lcdraven RZRAVEN LCD 3290p
*
* \section intro_lcd LCD Introduction
*
* This Raven LCD Driver application software was designed for a user interface
* to the Contiki 6LoWPAN collaboration on board the ATmega3290p. The
* LCD functionality uses the binary command set described in the release notes.
* These binary commands can also be found in a list of main.h.
*
* \section compile_lcd Compiling Raven LCD Driver
*
* The Raven LCD Driver is located in /platforms/avr-ravenlcd but it is not a contiki platform.
* $make TARGET=avr-ravenlcd will not work! Build it using the AVR Studio project and WinAVR or
* in Linux/Windows cmd/Cygwin $make in that directory. The AVR Studio dependency folder will confuse
* additional makes, use $make CYG=1 to bypass /dep creation or do $rm -R dep as needed.
* The .h file dependencies will be lost, so also $make CYG=1 clean after modifying any of those.
*
*
* \section fuses_lcd Board fuse settings
*
* The Raven LCD (3290p device) requires the proper fuse settings to function properly.
* They are automatically set when flashing the .elf file. When using a .hex file set them manually:
* -# Raven LCD (3290p device)
* -# Extended: <b>0xFF</b> (No Brown Out)
* -# High: <b>0x99</b> (JTAG and ISP enabled, No OCDEN or EEPROM saving required)
* -# Low: <b>0xE2</b> (Use Int RC OSC - Start-up Time:6CK + 65ms)
*
* \section notes_lcd Operation Release Notes
*
* After programming the Raven LCD 3290p with the proper image, you will be introduced to
* the menu in the picture below:
*
* \image html contiki_menu_3290.jpg
*
* Operating the menu requires that the matching command set has been programmed into
* the ATmega1284 application. This will allow the menu to communicate properly and control the
* Contiki 6LoWPAN applcation on the 1284p.
*
* During normal operation, you will need to make note of these <b>IMPORTANT</b> operating instructions:
* -# <b>Temp Sensor</b> - The temperature sensor shares the same GPIO as the JTAG interface for the 3290p.
* This requires the JTAG feature to be <b>disabled</b> in order to have proper temperature readings.
* -# <b>Debug Menu</b> - The DEBUG menu setting is used to configure this JTAG feature.
* -# If the JTAG feature is enabled during a temperature reading attempt,
* the menu will signal a <b>caution</b> symbol to the user letting them know the JTAG
* feature needs to be disabled.
* \image html caution.gif
* -# The JTAG header may also need to be physically disconnected from any external
* programming/debugging device in order to obtain correct temperature readings.
* -# The software will disable JTAG in sleep/doze modes. If the JTAG connection fails during
* reprogramming with AVR Studio, "try again with external reset" to recover.
* -# <b>Temp Data</b> - Once the temperature reading is proper, the user can send this reading
* to the webserver for Sensor Reading Data (<b>Once</b> or <b>Auto</b>). The webserver will
* only update the html data when <b>refreshed</b>.
* -# <b>EXT_SUPL_SIG</b> - This signal connects the external supply voltage to ADC2 through a divider.
* Enabling MEASURE_ADC2 in temp.h causes it to be sampled and sent to the 1284p along
* with the temperature.
*
* 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.
* \sa http://www.sics.se/contiki/tutorials/tutorial-running-contiki-with-uipv6-and-sicslowpan-support-on-the-atmel-raven.html
*
* \section binary_lcd Binary Command Description
*
* Using the binary commmand list described in main.h, the 3290p will contruct a binary
* command serial frame to control the 1284p. An example command frame is contructed below:
* -# <b>0x01,0x01,0x81,0x01,0x04</b> - Send Ping Request number 1 to 1284p
* -# <b>0x01</b> - Start of binary command frame
* -# <b>0x01</b> - Length of binary command payload
* -# <b>0x81</b> - Binary command SEND_PING
* -# <b>0x01</b> - Payload value (eg. ping Request number 1)
* -# <b>0x04</b> - End of binary command frame
*
* The following commands are sent to the 1284p.
* -# <b>SEND_TEMP - (0x80)</b>
* -# <b>SEND_PING - (0x81)</b>
* -# <b>SEND_ADC2 - (0x82)</b>
* -# <b>SEND_SLEEP- (0x83)</b>
* -# <b>SEND_WAKE - (0x84)</b>
*
* The following commands are received from the 1284p.
* -# <b>REPORT_PING - (0xC0)</b>
* -# <b>REPORT_PING_BEEP - (0xC1)</b>
* -# <b>REPORT_TEXT_MSG - (0xC2)</b>
* -# <b>REPORT_WAKE - (0xC3)</b>
*
* \section sleep_lcd Sleep and Doze
* -# The Raven draws 27 milliamps when the 3290p and 1284p are both running and the RF230 in receive mode.
* -# Sleeping the 3290p and LCD display drops this to 21 ma with no loss in contiki functionality.
* -# The RF230 radio draws 15.5/16.5/7.8/1.5/0.02 ma in Rx/Tx/PLL_ON/TRX_OFF/SLEEP states.
* It is controlled by contiki on the 1284p according to the selected MAC power protocols to obtain the
* bulk of power savings; however the 3290p menu can tell it to sleep unconditionally or in a doze cycle.
* -# Unconditional SLEEP requires pushing the joystick button for wakeup. Once awake the 3290p sends
* SEND_WAKE commands to the 1284p until it responds with a REPORT_WAKE. "WAIT 1284p" is displayed during this time.
* Current draw is 40 microamps.
* -# As configured, doze sleeps the 3290p for 5 seconds after telling 1284p to sleep for 4 seconds. The 3290p
* wakes briefly to send temperature and voltage to the 1284p (which should be awake at this time), then tells it to
* sleep again. Thus the 1284p will be active 20% of the time, although it may ignore the command to sleep
* if there are active TCP connections. The 3290p energy usage is essentially zero in this mode; total savings will
* depend on actual 1284p wake time and radio usage. Alter the timings as desired, or comment out the 1284p sleep
* command to shut down only the 3290p in doze mode.
*/
/*
* Copyright (c) 2008 Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* \brief
* This is the main file for the Raven LCD application.
*
* \author
* Mike Vidales mavida404@gmail.com
*
*/
#include "lcd.h"
#include "key.h"
#include "main.h"
#include "uart.h"
#include "timer.h"
#include "menu.h"
#include "temp.h"
#include <avr/io.h>
#include <avr/fuse.h>
FUSES =
{
.low = 0xe2,
.high = 0x99,
.extended = 0xff,
};
/** \ingroup lcdraven
\defgroup lcd LCD Functions and data
* \{
*/
#if defined( DOXYGEN )
const char menu_text0[];
const char menu_text1[];
const char menu_text2[];
const char menu_text3[];
const char menu_text4[];
const char menu_text5[];
const char menu_text6[];
const char menu_text7[];
const char menu_text8[];
const char menu_text9[];
const char menu_text10[];
const char menu_text11[];
const char menu_text12[];
const char menu_text13[];
const char menu_text14[];
const char menu_text15[];
const char menu_text16[];
const char menu_text17[];
const tmenu_item menu_items[18];
#else /* !DOXYGEN */
/** \brief This is the menu text in Flash. See menu_items[] for menu operation. */
const char menu_text0[] PROGMEM = "CONTIKI";
const char menu_text1[] PROGMEM = "6LOWPAN";
const char menu_text2[] PROGMEM = "PING";
const char menu_text3[] PROGMEM = "PINGING";
const char menu_text4[] PROGMEM = "TEMP";
const char menu_text5[] PROGMEM = "MODE ";
const char menu_text6[] PROGMEM = "DEG F";
const char menu_text7[] PROGMEM = "DEG C";
const char menu_text8[] PROGMEM = "SEND";
const char menu_text9[] PROGMEM = "ONCE";
const char menu_text10[] PROGMEM = "AUTO";
const char menu_text11[] PROGMEM = "DEBUG";
const char menu_text12[] PROGMEM = "DBG ON";
const char menu_text13[] PROGMEM = "DBG OFF";
const char menu_text14[] PROGMEM = "SENT";
const char menu_text15[] PROGMEM = "SENDING";
const char menu_text16[] PROGMEM = "SLEEP";
const char menu_text17[] PROGMEM = "DOZE";
/*---------------------------------------------------------------------------*/
/**
* \brief Menus for user interface
*
* This constructs the Raven 3290p menu for the Contiki and 6lowpan collaboration. This
* follows the struct description of tmenu_item.
*
* { text, left, right, up, down, *state, tmenufunc enter_func}
*/
const PROGMEM tmenu_item menu_items[18] = {
{menu_text0, 0, 2, 0, 0, 0, 0 },
{menu_text1, 0, 2, 0, 0, 0, 0 },
{menu_text2, 0, 3, 17, 4, 0, menu_ping_request },
{menu_text3, 2, 2, 2, 2, 0, 0 },
{menu_text4, 0, 5, 2, 11, 0, 0 },
{menu_text5, 4, 6, 8, 8, 0, 0 },
{menu_text6, 5, 5, 7, 7, (uint8_t*)1, menu_read_temp },
{menu_text7, 5, 5, 6, 6, (uint8_t*)0, menu_read_temp },
{menu_text8, 4, 9, 5, 5, 0, 0 },
{menu_text9, 8, 14, 10, 10, (uint8_t*)0, menu_prepare_temp },
{menu_text10, 8, 15, 9, 9, (uint8_t*)1, menu_prepare_temp },
{menu_text11, 0, 12, 4, 16, 0, 0 },
{menu_text12, 11, 11, 13, 13, (uint8_t*)1, menu_debug_mode },
{menu_text13, 11, 11, 12, 12, (uint8_t*)0, menu_debug_mode },
{menu_text14, 9, 14, 14, 14, 0, 0 },
{menu_text15, 10, 15, 15, 15, 0, 0 },
// {menu_text16, 0, 16, 11, 17, (uint8_t*)&menu_text16, menu_run_sleep },
// {menu_text17, 0, 17, 16, 2, (uint8_t*)&menu_text17, menu_run_doze },
{menu_text16, 0, 16, 11, 17, (uint8_t*)1, menu_run_sleep },//display "sleep" on wake
{menu_text17, 0, 17, 16, 2, (uint8_t*)1, menu_run_doze },//display "doze" on wake
};
#endif /* !DOXYGEN */
key_state_t button=KEY_STATE_NO_KEY;
tmenu_item menu;
uint8_t count;
uint8_t timeout_count;
/*---------------------------------------------------------------------------*/
/**
* \brief This will read the menu_items[] from the index requested.
*
* \param ndx Position index of menu_items[] lookup.
*/
void
read_menu(uint8_t ndx)
{
/* Reads menu structure from Flash area */
uint8_t i;
uint8_t *src = (uint8_t*)&menu_items[ndx];
uint8_t *dest = (uint8_t*)&menu;
for (i=0;i<sizeof(tmenu_item);i++){
*dest++ = pgm_read_byte(src+i);
}
}
/*---------------------------------------------------------------------------*/
char top_menu_text[20];
/**
* \brief This will toggle the CONTIKI and 6LOWPAN LCD menus in the main
* menu position, unless alternate text has been sent from the 1284p.
* The other menus will display normally.
*/
void
check_main_menu(void)
{
uint8_t showtop=0;
if(menu.text == menu_text0){
read_menu(1);
showtop=1;
}
else if(menu.text == menu_text1){
read_menu(0);
showtop=1;
}
if (showtop) {
if (top_menu_text[0]) {
lcd_puts(top_menu_text);
return;
}
}
lcd_puts_P(menu.text);
}
/*---------------------------------------------------------------------------*/
/**
* \brief This will check for the temp menu screen to determine if we need to
* clear the 4 digit LCD segments or stop an auto temp send. Also check for
* stopping a ping request.
*/
void
check_menu(void)
{
if(menu.text == menu_text12){
menu_clear_temp();
}
if(menu.text == menu_text10){
menu_stop_temp();
}
if(menu.text == menu_text2){
menu_stop_ping();
lcd_num_clr();
}
}
/*---------------------------------------------------------------------------*/
/**
* \brief This is main...
*/
int
main(void)
{
lcd_init();
key_init();
uart_init();
eeprom_init();
temp_init();
timer_init();
sei();
lcd_symbol_set(LCD_SYMBOL_RAVEN);
lcd_symbol_set(LCD_SYMBOL_IP);
/* Start with main menu */
read_menu(0);
/* and draw it */
lcd_puts_P(menu.text);
timer_start();
for (;;){
/* Make sure interrupts are always on */
sei();
/* The one second timer has fired. */
if(timer_flag){
timer_flag = false;
/* Check if main menu needs toggled. */
check_main_menu();
/* Update LCD with temp data. */
if(temp_flag){
menu_display_temp();
}
/* Auto send temp data to 1284p. */
if(auto_temp){
menu_send_temp();
}
/* If ping mode, send 4 ping requests and then stop. */
if(ping_mode){
if((PING_ATTEMPTS == count) && !timeout_flag){
count = 0;
timeout_count = 0;
menu_stop_ping();
}
else if(timeout_flag){
timeout_flag = false;
timeout_count++;
/* Display timeout message if all PING_ATTEMPTS were not successful. */
if(PING_ATTEMPTS == timeout_count){
lcd_puts_P(PSTR("PINGS FAILED"));
}
}
else{
count = menu_send_ping();
}
}
}
/* Check for button press and deal with it */
if (is_button()){
/* Dispatch the button pressed */
switch (get_button()){
case KEY_UP:
read_menu(menu.up);
lcd_puts_P(menu.text);
break;
case KEY_DOWN:
read_menu(menu.down);
lcd_puts_P(menu.text);
break;
case KEY_LEFT:
read_menu(menu.left);
lcd_puts_P(menu.text);
break;
case KEY_RIGHT:
/*
* Check to see if we should show another menu or
* run a function
*/
if (!menu.enter_func){
/* Just another menu to display */
read_menu(menu.right);
lcd_puts_P(menu.text);
break;
}
/* Drop through here */
case KEY_ENTER:
/* Call the menu function on right or enter buttons */
if (menu.enter_func){
menu.enter_func(menu.state);
if (menu.state){
/*
* We just called a selection menu (not a test),
* so re-display the text for this menu level
*/
lcd_puts_P(menu.text);
}
/* After enter key, check the right button menu and display. */
read_menu(menu.right);
lcd_puts_P(menu.text);
}
break;
default:
break;
}
/* After button press, check for menus... */
check_menu();
}
/* Process any progress frames */
uart_serial_rcv_frame(false);
} /* end for(). */
} /* end main(). */
/** \} */