diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/display.cc | 64 | ||||
| -rw-r--r-- | src/display.h | 14 | ||||
| -rw-r--r-- | src/main.cc | 135 | ||||
| -rw-r--r-- | src/system.cc | 74 | ||||
| -rw-r--r-- | src/system.h | 18 | 
5 files changed, 172 insertions, 133 deletions
| diff --git a/src/display.cc b/src/display.cc new file mode 100644 index 0000000..e06f271 --- /dev/null +++ b/src/display.cc @@ -0,0 +1,64 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <stdlib.h> + +#include "display.h" + +Display display; + +extern volatile uint8_t disp[8]; + +void Display::turn_off() +{ +	TIMSK0 &= ~_BV(TOIE0); +	PORTB = 0; +	PORTD = 0; +} + +void Display::turn_on() +{ +	TIMSK0 |= _BV(TOIE0); +} + +/* + * Draws a single display column. This function should be called at least once + * per millisecond. + * + * Current configuration: + * Called every 256 microseconds. The whole display is refreshed every 2048us, + * giving a refresh rate of ~500Hz + */ +ISR(TIMER0_OVF_vect) +{ +	static uint8_t active_col = 0; +	static uint16_t scroll = 0; +	static uint8_t disp_offset = 0; + +	static uint8_t disp_buf[8]; + +	uint8_t i; + +	if (++scroll == 512) { +		scroll = 0; +		if (++disp_offset == sizeof(disp)) { +			disp_offset = 0; +		} + +		for (i = 0; i < 8; i++) { +			disp_buf[i] = ~disp[(disp_offset + i) % sizeof(disp)]; +		} +	} + +	/* +	 * To avoid flickering, do not put any code (or expensive index +	 * calculations) between the following three lines. +	 */ +	PORTB = 0; +	PORTD = disp_buf[active_col]; +	PORTB = _BV(active_col); + +	if (++active_col == 8) +		active_col = 0; +} diff --git a/src/display.h b/src/display.h new file mode 100644 index 0000000..647e474 --- /dev/null +++ b/src/display.h @@ -0,0 +1,14 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <stdlib.h> + +class Display { +	public: +		Display() {}; +		void turn_on(void); +		void turn_off(void); +}; + +extern Display display; diff --git a/src/main.cc b/src/main.cc index 9bf9f4e..4ba15aa 100644 --- a/src/main.cc +++ b/src/main.cc @@ -4,98 +4,13 @@  #include <util/delay.h>  #include <stdlib.h> +#include "display.h"  #include "font2.h"  #include "modem.h" - -#define SHUTDOWN_THRESHOLD 2048 +#include "system.h"  volatile uint8_t disp[8]; -class System { -	private: -		uint16_t want_shutdown; -	public: -		System() { want_shutdown = 0; }; -		void loop(void); -		void shutdown(void); -}; - -class Display { -	public: -		Display() {}; -		void turn_on(void); -		void turn_off(void); -}; - -System rocket; -Display display; - -void Display::turn_off() -{ -	TIMSK0 &= ~_BV(TOIE0); -	PORTB = 0; -	PORTD = 0; -} - -void Display::turn_on() -{ -	TIMSK0 |= _BV(TOIE0); -} - -void System::loop() -{ -	// both buttons are pressed -	if ((PINC & (_BV(PC3) | _BV(PC7))) == 0) { -		// naptime! -		// But not before both buttons have been pressed for -		// SHUTDOWN_THRESHOLD * 0.256 ms. And then, not before both have -		// been released, because otherwise we'd go te sleep when -		// they're pressed and wake up when they're released, which -		// isn't really the point here. - -		if (want_shutdown < SHUTDOWN_THRESHOLD) { -			want_shutdown++; -		} -		else { - -			// turn off display to indicate we're about to shut down -			display.turn_off(); - -			// wait until both buttons are released -			while (!((PINC & _BV(PC3)) && (PINC & _BV(PC7)))) ; - -			// and some more to debounce the buttons -			_delay_ms(10); - -			// actual naptime - -			// enable PCINT on PC3 (PCINT11) and PC7 (PCINT15) for wakeup -			PCMSK1 |= _BV(PCINT15) | _BV(PCINT11); -			PCICR |= _BV(PCIE1); - -			// go to power-down mode -			SMCR = _BV(SM1) | _BV(SE); -			asm("sleep"); - -			// execution will resume here - disable PCINT again. -			// Don't disable PCICR, something else might need it. -			PCMSK1 &= ~(_BV(PCINT15) | _BV(PCINT11)); - -			// turn on display -			display.turn_on(); - -			want_shutdown = 0; -		} -	} -	else { -		want_shutdown = 0; -	} - -	if (modem.buffer_available()) { -		disp[0] = modem.buffer_get(); -	} -} -  int main (void)  {  	// disable ADC to save power @@ -176,49 +91,3 @@ int main (void)  	return 0;  } - -/* - * Draws a single display column. This function should be called at least once - * per millisecond. - * - * Current configuration: - * Called every 256 microseconds. The whole display is refreshed every 2048us, - * giving a refresh rate of ~500Hz - */ -ISR(TIMER0_OVF_vect) -{ -	static uint8_t active_col = 0; -	static uint16_t scroll = 0; -	static uint8_t disp_offset = 0; - -	static uint8_t disp_buf[8]; - -	uint8_t i; - -	if (++scroll == 512) { -		scroll = 0; -		if (++disp_offset == sizeof(disp)) { -			disp_offset = 0; -		} - -		for (i = 0; i < 8; i++) { -			disp_buf[i] = ~disp[(disp_offset + i) % sizeof(disp)]; -		} -	} - -	/* -	 * To avoid flickering, do not put any code (or expensive index -	 * calculations) between the following three lines. -	 */ -	PORTB = 0; -	PORTD = disp_buf[active_col]; -	PORTB = _BV(active_col); - -	if (++active_col == 8) -		active_col = 0; -} - -ISR(PCINT1_vect) -{ -	// we use PCINT1 for wakeup, so we should catch it here (and do nothing) -} diff --git a/src/system.cc b/src/system.cc new file mode 100644 index 0000000..8b02275 --- /dev/null +++ b/src/system.cc @@ -0,0 +1,74 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <stdlib.h> + +#include "display.h" +#include "modem.h" +#include "system.h" + +#define SHUTDOWN_THRESHOLD 2048 + +System rocket; + +extern volatile uint8_t disp[8]; + +void System::loop() +{ +	// both buttons are pressed +	if ((PINC & (_BV(PC3) | _BV(PC7))) == 0) { +		// naptime! +		// But not before both buttons have been pressed for +		// SHUTDOWN_THRESHOLD * 0.256 ms. And then, not before both have +		// been released, because otherwise we'd go te sleep when +		// they're pressed and wake up when they're released, which +		// isn't really the point here. + +		if (want_shutdown < SHUTDOWN_THRESHOLD) { +			want_shutdown++; +		} +		else { + +			// turn off display to indicate we're about to shut down +			display.turn_off(); + +			// wait until both buttons are released +			while (!((PINC & _BV(PC3)) && (PINC & _BV(PC7)))) ; + +			// and some more to debounce the buttons +			_delay_ms(10); + +			// actual naptime + +			// enable PCINT on PC3 (PCINT11) and PC7 (PCINT15) for wakeup +			PCMSK1 |= _BV(PCINT15) | _BV(PCINT11); +			PCICR |= _BV(PCIE1); + +			// go to power-down mode +			SMCR = _BV(SM1) | _BV(SE); +			asm("sleep"); + +			// execution will resume here - disable PCINT again. +			// Don't disable PCICR, something else might need it. +			PCMSK1 &= ~(_BV(PCINT15) | _BV(PCINT11)); + +			// turn on display +			display.turn_on(); + +			want_shutdown = 0; +		} +	} +	else { +		want_shutdown = 0; +	} + +	if (modem.buffer_available()) { +		disp[0] = modem.buffer_get(); +	} +} + +ISR(PCINT1_vect) +{ +	// we use PCINT1 for wakeup, so we should catch it here (and do nothing) +} diff --git a/src/system.h b/src/system.h new file mode 100644 index 0000000..e944bb2 --- /dev/null +++ b/src/system.h @@ -0,0 +1,18 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <stdlib.h> + +#define SHUTDOWN_THRESHOLD 2048 + +class System { +	private: +		uint16_t want_shutdown; +	public: +		System() { want_shutdown = 0; }; +		void loop(void); +		void shutdown(void); +}; + +extern System rocket; | 
