Browse files

put the display and MCU to sleep after a while of inactivity

wake on button presses
  • Loading branch information...
1 parent 2b04a29 commit c84be08550821d3861a082440c071bef3f4edd15 @beerriot committed Feb 27, 2011
Showing with 116 additions and 3 deletions.
  1. +1 −1 Makefile
  2. +8 −0 include/nkbuttons.h
  3. +7 −0 include/nklcd.h
  4. +6 −0 include/nksleep.h
  5. +2 −0 include/nktimer.h
  6. +10 −0 src/bggame.c
  7. +9 −0 src/blockgame.c
  8. +21 −0 src/nkbuttons.c
  9. +12 −2 src/nklcd.c
  10. +31 −0 src/nksleep.c
  11. +9 −0 src/nktimer.c
View
2 Makefile
@@ -5,7 +5,7 @@ CFLAGS=-g -Os -Wall -mmcu=atmega168 -Iinclude -I$(LIBNERDKITS)
AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P /dev/cu.PL2303-0000101D
NKOBJECTS=$(LIBNERDKITS)/delay.o $(LIBNERDKITS)/lcd.o
OBJECTS=bggame.o bgmenu.o bghighscore.o \
- nktimer.o nklcd.o nkrand.o nkeeprom.o nkbuttons.o
+ nktimer.o nklcd.o nkrand.o nkeeprom.o nkbuttons.o nksleep.o
all: blockgame.hex
View
8 include/nkbuttons.h
@@ -8,6 +8,12 @@
#define B_RIGHT (1<<PC3)
#define B_SELECT (1<<PC4)
+#define B_LEFT_INT (1<<PCINT8)
+#define B_DOWN_INT (1<<PCINT9)
+#define B_UP_INT (1<<PCINT10)
+#define B_RIGHT_INT (1<<PCINT11)
+#define B_SELECT_INT (1<<PCINT13)
+
// living state for the button reader
struct nkbuttons {
// the stable state (repeated agreeing reads) of the buttons
@@ -22,6 +28,8 @@ struct nkbuttons {
};
void nkbuttons_init();
+void nkbuttons_enable_interrupts();
+void nkbuttons_disable_interrupts();
uint8_t nkbuttons_read(struct nkbuttons* state);
void nkbuttons_clear(struct nkbuttons* state);
View
7 include/nklcd.h
@@ -1,8 +1,15 @@
#ifndef __NKLCD_H__
#define __NKLCD_H__
+#define DISPLAY_CMD 0x08
+#define DISPLAY_BLINK 0x01
+#define DISPLAY_CURSOR 0x02
+#define DISPLAY_ON 0x04
+
void nklcd_init();
void nklcd_start_blinking();
void nklcd_stop_blinking();
+void nklcd_off();
+void nklcd_on();
#endif
View
6 include/nksleep.h
@@ -0,0 +1,6 @@
+#ifndef __NKSLEEP_H__
+#define __NKSLEEP_H__
+
+void nksleep_standby();
+
+#endif
View
2 include/nktimer.h
@@ -4,6 +4,8 @@
#define F_CPU 14745600
void nktimer_init();
+void nktimer_resume();
+void nktimer_pause();
uint8_t nktimer_animate();
void nktimer_simple_delay(int clicks);
View
10 src/bggame.c
@@ -14,6 +14,7 @@
#include "nkbuttons.h"
#include "nklcd.h"
#include "nktimer.h"
+#include "nksleep.h"
#include "bggame.h"
#include "bghighscore.h"
@@ -309,6 +310,8 @@ void bggame_play(struct game *game) {
uint8_t pressed_buttons;
// selection state
struct point selection;
+ // idle/sleep timer
+ uint16_t idle = 0;
nkbuttons_clear(&button_state);
cursor.row = 0;
@@ -328,6 +331,7 @@ void bggame_play(struct game *game) {
pressed_buttons = nkbuttons_read(&button_state);
if(pressed_buttons) {
+ idle = 0;
nklcd_stop_blinking();
bggame_move_cursor(*game, pressed_buttons, &cursor);
if(bggame_select(game, pressed_buttons, cursor, &selection)) {
@@ -336,6 +340,12 @@ void bggame_play(struct game *game) {
}
lcd_goto_position(cursor.row, cursor.column);
nklcd_start_blinking();
+ } else if (++idle > 3600) {
+ // go to sleep after a minute of no activity
+ idle = 0;
+ nksleep_standby();
+ // display comes out of standby with blink disabled
+ nklcd_start_blinking();
}
}
}
View
9 src/blockgame.c
@@ -15,13 +15,16 @@
#include "nkrand.h"
#include "nklcd.h"
#include "nktimer.h"
+#include "nksleep.h"
#include "bggame.h"
#include "bgmenu.h"
#include "bghighscore.h"
int main() {
struct game game;
+ // idle/sleep timer
+ uint8_t idle = 0;
// the playing board
game.width = MAX_WIDTH;
@@ -38,9 +41,15 @@ int main() {
while(1) {
if (bgmenu_display(&game)) {
+ idle = 0;
bggame_play(&game);
bggame_over(game.score);
bghighscore_maybe(game.score);
+ } else if(++idle > 4) {
+ // go to sleep after cycling menu<->highscore
+ // without a game several times
+ idle = 0;
+ nksleep_standby();
}
bghighscore_screen();
}
View
21 src/nkbuttons.c
@@ -6,9 +6,14 @@
// utilities for reading button states
#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
#include "nkbuttons.h"
+ISR(PCINT1_vect) {
+ // only triggered when a button is used to wake up
+}
+
// get the input pins setup at boot
void nkbuttons_init() {
// Set the 6 pins to input mode - four directions + select
@@ -18,6 +23,22 @@ void nkbuttons_init() {
PORTC |= (B_LEFT|B_DOWN|B_UP|B_RIGHT|B_SELECT);
}
+void nkbuttons_enable_interrupts() {
+ // enable bin change mask registers
+ PCMSK1 |= (B_LEFT_INT|B_DOWN_INT|B_UP_INT|B_RIGHT_INT|B_SELECT_INT);
+
+ // enable Pin Change Interrupt 1
+ PCICR |= (1<<PCIE1);
+}
+
+void nkbuttons_disable_interrupts() {
+ // enable bin change mask registers
+ PCMSK1 &= ~(B_LEFT_INT|B_DOWN_INT|B_UP_INT|B_RIGHT_INT|B_SELECT_INT);
+
+ // enable Pin Change Interrupt 1
+ PCICR &= (1<<PCIE1);
+}
+
// check the state of the buttons, returns a mask of
// what buttons are now pushed that weren't before
uint8_t nkbuttons_read(struct nkbuttons* state) {
View
14 src/nklcd.c
@@ -18,10 +18,20 @@ void nklcd_init() {
void nklcd_start_blinking() {
lcd_set_type_command();
- lcd_write_byte(0x0F);
+ lcd_write_byte(DISPLAY_CMD|DISPLAY_ON|DISPLAY_CURSOR|DISPLAY_BLINK);
}
void nklcd_stop_blinking() {
lcd_set_type_command();
- lcd_write_byte(0x0C);
+ lcd_write_byte(DISPLAY_CMD|DISPLAY_ON);
+}
+
+void nklcd_off() {
+ lcd_set_type_command();
+ lcd_write_byte(DISPLAY_CMD);
+}
+
+void nklcd_on() {
+ lcd_set_type_command();
+ lcd_write_byte(DISPLAY_CMD|DISPLAY_ON);
}
View
31 src/nksleep.c
@@ -0,0 +1,31 @@
+// blockgame
+// for NerdKits with ATmega168
+// copyright 2011 Bryan Fink
+// license: see LICENSE.txt
+
+// utilities for reducing power consumption
+
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+
+#include "nksleep.h"
+#include "nklcd.h"
+#include "nkbuttons.h"
+#include "nktimer.h"
+
+void nksleep_standby() {
+ nklcd_off();
+ nkbuttons_enable_interrupts();
+ nktimer_pause();
+ // SLEEP
+ SMCR = (1<<SM2)|(1<<SM1); //standby
+ sleep_enable();
+ sleep_cpu();
+ sleep_disable();
+ // ENDSLEEP
+ nktimer_resume();
+ nkbuttons_disable_interrupts();
+ nklcd_on();
+ sei();
+}
View
9 src/nktimer.c
@@ -35,10 +35,19 @@ void nktimer_init(int freq) {
// choose the value for Output Compare A
OCR0A = (F_CPU / 1024) / freq;
+ nktimer_resume();
+}
+
+void nktimer_resume() {
// endable Timer Output Compare Match A Interrupt 0
TIMSK0 |= (1<<OCIE0A);
}
+void nktimer_pause() {
+ // disable Timer Output Compare Match A Interrupt 0
+ TIMSK0 &= ~(1<<OCIE0A);
+}
+
uint8_t nktimer_animate() {
if (animatev) {
animatev = 0;

0 comments on commit c84be08

Please sign in to comment.