Add SLEEP and DOZE functions to the menu.

Give serial commands the same defines as in the 1284p for grepping.
This commit is contained in:
dak664 2010-12-18 20:35:58 +00:00
parent 8f76c82433
commit 555fab59a3
9 changed files with 185 additions and 77 deletions

View file

@ -57,6 +57,8 @@
#define SEND_TEMP (0x80) #define SEND_TEMP (0x80)
#define SEND_PING (0x81) #define SEND_PING (0x81)
#define SEND_ADC2 (0x82) #define SEND_ADC2 (0x82)
#define SEND_SLEEP (0x83)
#define SEND_WAKE (0x84)
/** \} */ /** \} */
/** \name These are the Radio to GUI binary commands. */ /** \name These are the Radio to GUI binary commands. */
@ -64,6 +66,7 @@
#define REPORT_PING (0xC0) #define REPORT_PING (0xC0)
#define REPORT_PING_BEEP (0xC1) #define REPORT_PING_BEEP (0xC1)
#define REPORT_TEXT_MSG (0xC2) #define REPORT_TEXT_MSG (0xC2)
#define REPORT_WAKE (0xC3)
/** \} */ /** \} */

View file

@ -40,6 +40,7 @@
*/ */
#include <avr/eeprom.h> #include <avr/eeprom.h>
#include <util/delay.h>
#include "menu.h" #include "menu.h"
#include "main.h" #include "main.h"
#include "lcd.h" #include "lcd.h"
@ -47,7 +48,9 @@
#include "uart.h" #include "uart.h"
#include "sleep.h" #include "sleep.h"
#include "temp.h" #include "temp.h"
#include "beep.h"
uint8_t sleep_count;
uint8_t ping_count; uint8_t ping_count;
uint8_t ping_response; uint8_t ping_response;
bool ping_mode; bool ping_mode;
@ -156,40 +159,43 @@ eeprom_init(void)
/** /**
* \brief This will start a sleep operation. * \brief This will start a sleep operation.
* *
* \param val Used for rembering the new menu to display after a wakeup. * \param val Used for remembering the new menu to display after a wakeup.
*/ */
void void
menu_run_sleep(uint8_t *val) menu_run_sleep(uint8_t *val)
{ {
/* Turn off LED */ /* Turn off LED, LCD, ADC, Timer 1, SPI */
led_off(); led_off();
lcd_deinit();
/* Turn off Timer 1, SPI, uart */ key_deinit();
PRR |= (1 << PRTIM1) | (1 << PRSPI); PRR |= (1 << PRTIM1) | (1 << PRSPI);
/* Turn off the LCD display for sleeping */ /* Tell the 1284P to turn off the radio and sleep */
lcd_deinit(); sleep_count=0;
uart_serial_send_frame(SEND_SLEEP, 1, (uint8_t *)&sleep_count);
/* Turn off A/D converter */ /* Turn off UART when transmission is complete */
key_deinit(); while(!(UCSR0A & (1 << TXC0)));
_delay_us(10000); //deinit trash clears done flag on 1284p
uart_deinit();
/* Go to sleep now */ /* Go to sleep until button is pushed */
sleep_now(); sleep_now(0);
/* Wake up LCD Display */ /* Yawn, waking up, turn on LCD with Raven Logo */
lcd_init(); lcd_init();
/* Tell user we're waking up */
lcd_puts_P(PSTR("WAKE---"));
/* Turn on Raven logo */
lcd_symbol_set(LCD_SYMBOL_RAVEN); lcd_symbol_set(LCD_SYMBOL_RAVEN);
/* Wake up ADC */ /* Disable interrupts before powering everything up */
cli();
key_init(); key_init();
PRR &= ~((1 << PRTIM1) | (1 << PRSPI));
uart_init();
/* Wake up radio */ /* Enable interrupts, Wake up 1284p and radio */
sei();
sleep_wakeup(); sleep_wakeup();
// uart_init();//flush receive buffer
/* Wait for buttons up */ /* Wait for buttons up */
while (key_state_get() != KEY_NO_KEY) while (key_state_get() != KEY_NO_KEY)
@ -197,9 +203,53 @@ menu_run_sleep(uint8_t *val)
if (is_button()){ if (is_button()){
get_button(); get_button();
} }
}
/*---------------------------------------------------------------------------*/
/* Print last menu tex */ /**
lcd_puts_P((char *)&val); * \brief This will start a sleep with wakes for temperature measurement and web requests.
*
* \param val Used for remembering the new menu to display after a wakeup.
*/
void
menu_run_doze(uint8_t *val)
{
/* Turn off LED, LCD */
led_off();
lcd_deinit();
/* Debounce */
while (key_state_get() != KEY_NO_KEY) ;
/* Stay in doze loop until button is pressed*/
while (ENTER_PORT & (1<<ENTER_PIN)) {
/* Tell 1284p to sleep for 4 seconds */
/* It will ignore the request if TCP/IP sessions are active */
sleep_count=4;
uart_serial_send_frame(SEND_SLEEP, 1, (uint8_t *)&sleep_count);
/* Wait for transmission complete, then sleep 3290p for 5 seconds */
while(!(UCSR0A & (1 << TXC0)));
// uart_deinit();
sleep_now(sleep_count+1);
// uart_init();
/* 1284p should be awake by now, update temperature and give it time to process */
menu_send_temp();
_delay_us(20000);
}
/* Wake LCD, turn on Raven logo */
lcd_init();
lcd_symbol_set(LCD_SYMBOL_RAVEN);
sleep_wakeup();
/* Wait for buttons up */
while (key_state_get() != KEY_NO_KEY)
;
if (is_button()){
get_button();
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -65,10 +65,12 @@ extern bool timeout_flag;
extern bool temp_flag; extern bool temp_flag;
extern bool auto_temp; extern bool auto_temp;
extern const PROGMEM tmenu_item menu_items[]; extern const PROGMEM tmenu_item menu_items[];
char top_menu_text[20];
#define EEPROM_DEBUG_ADDR 0 #define EEPROM_DEBUG_ADDR 0
void menu_run_sleep(uint8_t *val); void menu_run_sleep(uint8_t *val);
void menu_run_doze(uint8_t *val);
void dectoascii(uint8_t val, char *str); void dectoascii(uint8_t val, char *str);
uint8_t *signed_dectoascii(int16_t n, uint8_t *str); uint8_t *signed_dectoascii(int16_t n, uint8_t *str);
void eeprom_init(void); void eeprom_init(void);

View file

@ -84,11 +84,14 @@
* The following commands are used to control the 1284p. * The following commands are used to control the 1284p.
* -# <b>SEND_TEMP - (0x80)</b> * -# <b>SEND_TEMP - (0x80)</b>
* -# <b>SEND_PING - (0x81)</b> * -# <b>SEND_PING - (0x81)</b>
*...-# <b>SEND_SLEEP- (0x82)</b>
*...-# <b>SEND_WAKE - (0x83)</b>
* *
* The following commands are used to update the 3290p. * The following commands are used to update the 3290p.
* -# <b>REPORT_PING - (0xC0)</b> * -# <b>REPORT_PING - (0xC0)</b>
* -# <b>REPORT_PING_BEEP - (0xC1)</b> * -# <b>REPORT_PING_BEEP - (0xC1)</b>
* -# <b>REPORT_TEXT_MSG - (0xC2)</b> * -# <b>REPORT_TEXT_MSG - (0xC2)</b>
* -# <b>REPORT_WAKE - (0xC3)</b>
*/ */
/* /*
* Copyright (c) 2008 Swedish Institute of Computer Science * Copyright (c) 2008 Swedish Institute of Computer Science
@ -170,7 +173,9 @@ const char menu_text12[];
const char menu_text13[]; const char menu_text13[];
const char menu_text14[]; const char menu_text14[];
const char menu_text15[]; const char menu_text15[];
const tmenu_item menu_items[16]; const char menu_text16[];
const char menu_text17[];
const tmenu_item menu_items[18];
#else /* !DOXYGEN */ #else /* !DOXYGEN */
/** \brief This is the menu text in Flash. See menu_items[] for menu operation. */ /** \brief This is the menu text in Flash. See menu_items[] for menu operation. */
const char menu_text0[] PROGMEM = "CONTIKI"; const char menu_text0[] PROGMEM = "CONTIKI";
@ -189,6 +194,8 @@ const char menu_text12[] PROGMEM = "DBG ON";
const char menu_text13[] PROGMEM = "DBG OFF"; const char menu_text13[] PROGMEM = "DBG OFF";
const char menu_text14[] PROGMEM = "SENT"; const char menu_text14[] PROGMEM = "SENT";
const char menu_text15[] PROGMEM = "SENDING"; const char menu_text15[] PROGMEM = "SENDING";
const char menu_text16[] PROGMEM = "SLEEP";
const char menu_text17[] PROGMEM = "DOZE";
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -200,10 +207,10 @@ const char menu_text15[] PROGMEM = "SENDING";
* *
* { text, left, right, up, down, *state, tmenufunc enter_func} * { text, left, right, up, down, *state, tmenufunc enter_func}
*/ */
const PROGMEM tmenu_item menu_items[16] = { const PROGMEM tmenu_item menu_items[18] = {
{menu_text0, 0, 2, 0, 0, 0, 0 }, {menu_text0, 0, 2, 0, 0, 0, 0 },
{menu_text1, 0, 2, 0, 0, 0, 0 }, {menu_text1, 0, 2, 0, 0, 0, 0 },
{menu_text2, 0, 3, 11, 4, 0, menu_ping_request }, {menu_text2, 0, 3, 17, 4, 0, menu_ping_request },
{menu_text3, 2, 2, 2, 2, 0, 0 }, {menu_text3, 2, 2, 2, 2, 0, 0 },
{menu_text4, 0, 5, 2, 11, 0, 0 }, {menu_text4, 0, 5, 2, 11, 0, 0 },
{menu_text5, 4, 6, 8, 8, 0, 0 }, {menu_text5, 4, 6, 8, 8, 0, 0 },
@ -212,11 +219,15 @@ const PROGMEM tmenu_item menu_items[16] = {
{menu_text8, 4, 9, 5, 5, 0, 0 }, {menu_text8, 4, 9, 5, 5, 0, 0 },
{menu_text9, 8, 14, 10, 10, (uint8_t*)0, menu_prepare_temp }, {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_text10, 8, 15, 9, 9, (uint8_t*)1, menu_prepare_temp },
{menu_text11, 0, 12, 4, 2, 0, 0 }, {menu_text11, 0, 12, 4, 16, 0, 0 },
{menu_text12, 11, 11, 13, 13, (uint8_t*)1, menu_debug_mode }, {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_text13, 11, 11, 12, 12, (uint8_t*)0, menu_debug_mode },
{menu_text14, 9, 14, 14, 14, 0, 0 }, {menu_text14, 9, 14, 14, 14, 0, 0 },
{menu_text15, 10, 15, 15, 15, 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 */ #endif /* !DOXYGEN */
@ -248,20 +259,31 @@ read_menu(uint8_t ndx)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief This will toggle the CONTIKI and 6LOWPAN LCD menus only in the main * \brief This will toggle the CONTIKI and 6LOWPAN LCD menus in the main
* menu position. * menu position, unless alternate text has been sent from the 1284p.
* The other menus will display normally.
*/ */
char top_menu_text[20];
void void
check_main_menu(void) check_main_menu(void)
{ {
uint8_t showtop=0;
if(menu.text == menu_text0){ if(menu.text == menu_text0){
read_menu(1); read_menu(1);
lcd_puts_P(menu.text); showtop=1;
} }
else if(menu.text == menu_text1){ else if(menu.text == menu_text1){
read_menu(0); read_menu(0);
lcd_puts_P(menu.text); showtop=1;
} }
if (showtop) {
if (top_menu_text[0]) {
lcd_puts(top_menu_text);
return;
}
}
lcd_puts_P(menu.text);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -41,9 +41,14 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include <util/delay.h>
#include <stdbool.h> #include <stdbool.h>
#include "main.h"
#include "sleep.h" #include "sleep.h"
#include "uart.h" #include "uart.h"
#include "key.h"
#include "timer.h"
#include "lcd.h" //temp
/** /**
* \addtogroup lcd * \addtogroup lcd
@ -55,53 +60,79 @@
/** /**
* \brief Prepares for and executes sleep. This function sets up the * \brief Prepares for and executes sleep. This function sets up the
* processor to enter sleep mode, and to wake up when the joystick * processor to enter sleep mode, and to wake up when the joystick
* button (PE2/PCINT2) is pressed. * button (PE2/PCINT2) is pressed or after the specified interval.
*
* \param howlong Seconds to sleep, 0=until button pushed
*/ */
void void
sleep_now(void) sleep_now(int howlong)
{ {
/* Disable watchdog */ /* Disable watchdog (not currently used elsewhere) */
wdt_disable(); wdt_disable();
/* Setup sleep mode */ /* Setup sleep mode */
set_sleep_mode(SLEEP_MODE_PWR_DOWN); if (howlong==0) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
MCUCR |= (1<<JTD); //Disable JTAG so clock can stop
} else {
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
/* Using 8 bit TIMER2 */
TCNT2 = 0;
TCCR2A = (1<<CS22)|(1<<CS21)|(1<<CS20); //Prescale by 1024
TIMSK2 = (1<<TOIE2); //Enable overflow interrupt
howlong*=30; //which is approximately 30 Hz
/* Enable wakeup interrupt */ /* Using 16 bit TIMER1, which takes a bit more power
timer_stop; //Disable interrupt
timer_init; //make sure initialized for 1 second
timer_start; //Start timer, enable interrupt
*/
}
/* Enable pin change 0 wakeup interrupt */
EIMSK |= (1 << PCIE0); EIMSK |= (1 << PCIE0);
/* Enable PCINT2 as interrupt */ /* Select joystick button input pin */
PCMSK0 |= (1 << PCINT2); PCMSK0 |= (1 << PCINT2);
/* Go to sleep now */ /* Sleep until timeout or button pushed */
sleep_mode(); while (ENTER_PORT & (1<<ENTER_PIN)) {
sleep_mode();
if (!howlong--) break;
}
/* Disable the interrupt for the enter button */ /* Disable the interrupts for the enter button and TIMER2 */
EIMSK &= ~(1 << PCIE0); EIMSK &= ~(1 << PCIE0);
PCMSK0&= ~(1 <<PCINT2);
TIMSK2&= ~(1 << TOIE2);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief This will send a single character forever to the ATmega1284p to cause a wakeup.
* \brief This will send a wakeup command to ATmega1284p
* It may already be awake, if not it will respond during the next wake cycle
* Upon receiving the command it will return an acknowledgement frame
* *
* \brief This will send a single character forever to the ATmega1284p to cause a wakeup.
* The 1284p polls the USART for new data during each sleep cycle. Upon receiving a * The 1284p polls the USART for new data during each sleep cycle. Upon receiving a
* character from the user LCD, it will wake up and send an acknowledgement frame. * character from the user LCD, it will wake up and send an acknowledgement frame.
*/ */
void void
sleep_wakeup(void) sleep_wakeup(void)
{ {
/* First, clear the input buffer and get any chars waiting */ lcd_puts_P(PSTR("WAKE 1284p"));
while(rx_char_ready()){
uart_get_char_rx(); /* Flood 1284p with wake commands until it responds*/
for(;;){
uart_serial_send_frame(SEND_WAKE,0,0);
_delay_us(1000);
if (rx_char_ready())
break;
} }
/* Flood 1284p with serial chars until it responds. */
for(;;){
uart_send_byte('x');
if (rx_char_ready())
break;
}
/* Get a frame back */ /* Get a frame back */
uart_serial_rcv_frame(true); uart_serial_rcv_frame(true);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -115,6 +146,17 @@ ISR
(PCINT0_vect) (PCINT0_vect)
{ {
}
/*---------------------------------------------------------------------------*/
/**
* \brief This is the timer2 overflow interrupt. When this interrupt fires,
* the CPU will wake.
*/
ISR
(TIMER2_OVF_vect)
{
} }
/** \} */ /** \} */

View file

@ -42,7 +42,7 @@
#define __SLEEP_H__ #define __SLEEP_H__
/* Prototypes */ /* Prototypes */
void sleep_now(void); void sleep_now(int howlong);
void sleep_wakeup(void); void sleep_wakeup(void);
#endif /* __SLEEP_H__ */ #endif /* __SLEEP_H__ */

View file

@ -72,7 +72,7 @@ typedef enum {
* *
* \return EOF on error * \return EOF on error
*/ */
//#define MEASURE_ADC2 1 //adds 250 bytes to program size #define MEASURE_ADC2 1 //adds 250 bytes to program size
int temp_init(void); int temp_init(void);

View file

@ -261,6 +261,9 @@ uart_send_byte(uint8_t byte)
while(!(UCSR0A & (1 << UDRE0))) while(!(UCSR0A & (1 << UDRE0)))
; ;
UDR0 = byte; UDR0 = byte;
/* Clear the TXC bit to allow transmit complete test before sleep*/
UCSR0A |=(1 << TXC0);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -341,7 +344,7 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
volatile uint8_t ch; volatile uint8_t ch;
volatile uint8_t length; volatile uint8_t length;
volatile uint8_t cmd; volatile uint8_t cmd;
volatile uint8_t payload[10]; volatile uint8_t payload[20];
uint16_t i; uint16_t i;
if (!wait_for_ack && !rx_char_ready()){ if (!wait_for_ack && !rx_char_ready()){
@ -374,7 +377,7 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
} }
length = ch; length = ch;
if (length > 10){ if (length > sizeof(payload)){
/* invalid length */ /* invalid length */
return; return;
} }
@ -402,7 +405,7 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
return uart_timeout_msg(7); return uart_timeout_msg(7);
} }
/* Now print something based on rx'd frame */ /* Process the received command */
switch (cmd){ switch (cmd){
case REPORT_PING: case REPORT_PING:
/* /*
@ -431,15 +434,18 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
beep(); beep();
lcd_symbol_clr(LCD_SYMBOL_BELL); lcd_symbol_clr(LCD_SYMBOL_BELL);
break; break;
case REPORT_TEXT_MSG:
/* Copy text message to menu buffer and fall through to beep */
/* Prezero in case no string terminator in command */
for (i=0;i<sizeof(top_menu_text);i++) top_menu_text[i]=0;
memcpy(&top_menu_text,(char *)payload,sizeof(top_menu_text)-1); //leave zero byte at end
case REPORT_PING_BEEP: case REPORT_PING_BEEP:
lcd_symbol_set(LCD_SYMBOL_BELL); lcd_symbol_set(LCD_SYMBOL_BELL);
beep(); beep();
lcd_symbol_clr(LCD_SYMBOL_BELL); lcd_symbol_clr(LCD_SYMBOL_BELL);
break; break;
case REPORT_TEXT_MSG: case REPORT_WAKE:
/* Get text message, print to lcd. */ /* Indicates 1284 is awake*/
lcd_puts((char *)payload);
beep();
break; break;
default: default:
break; break;

View file

@ -48,29 +48,12 @@
/** \{ */ /** \{ */
#define SOF_CHAR (0x01) /**< Start-of-frame character. */ #define SOF_CHAR (0x01) /**< Start-of-frame character. */
#define EOF_CHAR (0x04) /**< End-of-frame character. */ #define EOF_CHAR (0x04) /**< End-of-frame character. */
#define TERM_CHAR (0x14) /**< Control-T ASCII value for entering terminal mode. */
/** \} */ /** \} */
/** \name Define Lengths. */
/** \{ */
#define MAX_CMD_LENGTH (0x0A)
#define ACK_LENGTH (0x02)
/** \} */
/** \name Define IO result values. */
/** \{ */
#define IO_SUCCESS (0)
#define IO_FAIL (1)
/** \} */
#define LEN_BYTE (0)
#define CMD_BYTE (1)
#define BAUD_RATE_38400 (12)
/* Macros & Defines */ /* Macros & Defines */
#define BUFSIZE 80 #define BUFSIZE 80
#define BAUD_RATE_38400 (12)
/** \brief Circular buffer structure */ /** \brief Circular buffer structure */
typedef struct { typedef struct {