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_PING (0x81)
#define SEND_ADC2 (0x82)
#define SEND_SLEEP (0x83)
#define SEND_WAKE (0x84)
/** \} */
/** \name These are the Radio to GUI binary commands. */
@ -64,6 +66,7 @@
#define REPORT_PING (0xC0)
#define REPORT_PING_BEEP (0xC1)
#define REPORT_TEXT_MSG (0xC2)
#define REPORT_WAKE (0xC3)
/** \} */

View file

@ -40,6 +40,7 @@
*/
#include <avr/eeprom.h>
#include <util/delay.h>
#include "menu.h"
#include "main.h"
#include "lcd.h"
@ -47,7 +48,9 @@
#include "uart.h"
#include "sleep.h"
#include "temp.h"
#include "beep.h"
uint8_t sleep_count;
uint8_t ping_count;
uint8_t ping_response;
bool ping_mode;
@ -156,40 +159,43 @@ eeprom_init(void)
/**
* \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
menu_run_sleep(uint8_t *val)
{
/* Turn off LED */
/* Turn off LED, LCD, ADC, Timer 1, SPI */
led_off();
/* Turn off Timer 1, SPI, uart */
lcd_deinit();
key_deinit();
PRR |= (1 << PRTIM1) | (1 << PRSPI);
/* Turn off the LCD display for sleeping */
lcd_deinit();
/* Tell the 1284P to turn off the radio and sleep */
sleep_count=0;
uart_serial_send_frame(SEND_SLEEP, 1, (uint8_t *)&sleep_count);
/* Turn off A/D converter */
key_deinit();
/* Turn off UART when transmission is complete */
while(!(UCSR0A & (1 << TXC0)));
_delay_us(10000); //deinit trash clears done flag on 1284p
uart_deinit();
/* Go to sleep now */
sleep_now();
/* Go to sleep until button is pushed */
sleep_now(0);
/* Wake up LCD Display */
/* Yawn, waking up, turn on LCD with Raven Logo */
lcd_init();
/* Tell user we're waking up */
lcd_puts_P(PSTR("WAKE---"));
/* Turn on Raven logo */
lcd_symbol_set(LCD_SYMBOL_RAVEN);
/* Wake up ADC */
/* Disable interrupts before powering everything up */
cli();
key_init();
PRR &= ~((1 << PRTIM1) | (1 << PRSPI));
uart_init();
/* Wake up radio */
/* Enable interrupts, Wake up 1284p and radio */
sei();
sleep_wakeup();
// uart_init();//flush receive buffer
/* Wait for buttons up */
while (key_state_get() != KEY_NO_KEY)
@ -197,9 +203,53 @@ menu_run_sleep(uint8_t *val)
if (is_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 auto_temp;
extern const PROGMEM tmenu_item menu_items[];
char top_menu_text[20];
#define EEPROM_DEBUG_ADDR 0
void menu_run_sleep(uint8_t *val);
void menu_run_doze(uint8_t *val);
void dectoascii(uint8_t val, char *str);
uint8_t *signed_dectoascii(int16_t n, uint8_t *str);
void eeprom_init(void);

View file

@ -84,11 +84,14 @@
* The following commands are used to control the 1284p.
* -# <b>SEND_TEMP - (0x80)</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.
* -# <b>REPORT_PING - (0xC0)</b>
* -# <b>REPORT_PING - (0xC0)</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
@ -170,7 +173,9 @@ const char menu_text12[];
const char menu_text13[];
const char menu_text14[];
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 */
/** \brief This is the menu text in Flash. See menu_items[] for menu operation. */
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_text14[] PROGMEM = "SENT";
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}
*/
const PROGMEM tmenu_item menu_items[16] = {
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, 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_text4, 0, 5, 2, 11, 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_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, 2, 0, 0 },
{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 */
@ -248,20 +259,31 @@ read_menu(uint8_t ndx)
/*---------------------------------------------------------------------------*/
/**
* \brief This will toggle the CONTIKI and 6LOWPAN LCD menus only in the main
* menu position.
* \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.
*/
char top_menu_text[20];
void
check_main_menu(void)
{
uint8_t showtop=0;
if(menu.text == menu_text0){
read_menu(1);
lcd_puts_P(menu.text);
showtop=1;
}
else if(menu.text == menu_text1){
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/sleep.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdbool.h>
#include "main.h"
#include "sleep.h"
#include "uart.h"
#include "key.h"
#include "timer.h"
#include "lcd.h" //temp
/**
* \addtogroup lcd
@ -55,53 +60,79 @@
/**
* \brief Prepares for and executes sleep. This function sets up the
* 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
sleep_now(void)
sleep_now(int howlong)
{
/* Disable watchdog */
/* Disable watchdog (not currently used elsewhere) */
wdt_disable();
/* 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);
/* Enable PCINT2 as interrupt */
/* Select joystick button input pin */
PCMSK0 |= (1 << PCINT2);
/* Go to sleep now */
sleep_mode();
/* Sleep until timeout or button pushed */
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);
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
* character from the user LCD, it will wake up and send an acknowledgement frame.
*/
void
sleep_wakeup(void)
{
/* First, clear the input buffer and get any chars waiting */
while(rx_char_ready()){
uart_get_char_rx();
lcd_puts_P(PSTR("WAKE 1284p"));
/* 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 */
uart_serial_rcv_frame(true);
uart_serial_rcv_frame(true);
}
/*---------------------------------------------------------------------------*/
@ -115,6 +146,17 @@ ISR
(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__
/* Prototypes */
void sleep_now(void);
void sleep_now(int howlong);
void sleep_wakeup(void);
#endif /* __SLEEP_H__ */

View file

@ -72,7 +72,7 @@ typedef enum {
*
* \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);

View file

@ -261,6 +261,9 @@ uart_send_byte(uint8_t byte)
while(!(UCSR0A & (1 << UDRE0)))
;
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 length;
volatile uint8_t cmd;
volatile uint8_t payload[10];
volatile uint8_t payload[20];
uint16_t i;
if (!wait_for_ack && !rx_char_ready()){
@ -374,7 +377,7 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
}
length = ch;
if (length > 10){
if (length > sizeof(payload)){
/* invalid length */
return;
}
@ -402,7 +405,7 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
return uart_timeout_msg(7);
}
/* Now print something based on rx'd frame */
/* Process the received command */
switch (cmd){
case REPORT_PING:
/*
@ -431,15 +434,18 @@ uart_serial_rcv_frame(uint8_t wait_for_ack)
beep();
lcd_symbol_clr(LCD_SYMBOL_BELL);
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:
lcd_symbol_set(LCD_SYMBOL_BELL);
beep();
lcd_symbol_clr(LCD_SYMBOL_BELL);
break;
case REPORT_TEXT_MSG:
/* Get text message, print to lcd. */
lcd_puts((char *)payload);
beep();
case REPORT_WAKE:
/* Indicates 1284 is awake*/
break;
default:
break;

View file

@ -48,29 +48,12 @@
/** \{ */
#define SOF_CHAR (0x01) /**< Start-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 */
#define BUFSIZE 80
#define BAUD_RATE_38400 (12)
/** \brief Circular buffer structure */
typedef struct {