Created
May 1, 2011 00:10
-
-
Save adamgreig/950119 to your computer and use it in GitHub Desktop.
ATtiny code to sense touch and flash an LED a few times
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Firefly | |
// An ATtiny13 connected to a bit of metal to detect touch | |
// and an LED which it can PWM. | |
// | |
// Sleep most of the time, wake up occasionally, if we're being touched | |
// then light up a bit. | |
// | |
// Adam Greig, July 2010 | |
#include <avr/io.h> | |
inline void init_io() { | |
// Set PB1 to be an output and everything else an input pulled high | |
// (defined levels help save power) | |
DDRB = (1<<PB1); | |
PORTB = (1<<PB0) | (1<<PB2) | (1<<PB3) | (1<<PB4); | |
} | |
inline void deinit_io() { | |
// Set all pins to input, and all but PB1 to be pulled high | |
DDRB = 0; | |
PORTB = (1<<PB0) | (1<<PB2) | (1<<PB3) | (1<<PB4); | |
} | |
inline void init_timer() { | |
// Set for Fast PWM with TOP at 0xFF, set OC0B on compare match | |
TCCR0A = (1<<COM0B1) | (1<<COM0B0) | (1<<WGM01) | (1<<WGM00); | |
TCCR0B = (1<<CS00); | |
OCR0B = 255; | |
} | |
inline void deinit_timer() { | |
// Turn off the timer | |
TCCR0A = 0; | |
TCCR0B = 0; | |
OCR0B = 0; | |
} | |
uint8_t lfsr; | |
uint8_t rand() { | |
uint8_t feedback = lfsr & 1; | |
lfsr >>= 1; | |
if(feedback == 1) | |
lfsr ^= 0xB8; | |
return lfsr; | |
} | |
inline void init_rand() { | |
// Read EEPROM address 0x00 | |
EEARL = 0x00; | |
EECR = (1<<EERE); | |
// Increment the value and use it as a random seed, special casing zero | |
// as it produces all 0s for the pseudorandom sequence | |
lfsr = EEDR; | |
lfsr++; | |
if(lfsr == 0) | |
lfsr = 1; | |
EEDR = lfsr; | |
// Store the newly incremented value | |
EECR = (0<<EEPM1) | (0<<EEPM0); | |
EEARL = 0x00; | |
EECR = (1<<EEMPE); | |
EECR = (1<<EEPE) | (1<<EEMPE); | |
} | |
inline void clear_wdt() { | |
// After the watchdog reset, clear it properly | |
MCUSR = (0<<WDRF); | |
WDTCR = (1<<WDE) | (1<<WDCE); | |
WDTCR = 0; | |
} | |
inline void start_wdt() { | |
// Set the watchdog timer to reset the system after eight seconds | |
// and start it going | |
WDTCR = (1<<WDE) | (1<<WDCE); | |
WDTCR = (1<<WDE) | (1<<WDP3) | (1<<WDP0); | |
} | |
inline void sleep() { | |
// Enable sleeping and set us up for power down mode, then sleep | |
MCUCR = (1<<SE) | (1<<SM1); | |
asm("SLEEP"); | |
} | |
void init() { | |
// Clear watchdog reset flag | |
clear_wdt(); | |
// Turn off the analogue comparator to save power | |
ACSR = (1<<ACD); | |
// Initialise I/O ports | |
init_io(); | |
// Initialise timer for fast PWM | |
init_timer(); | |
// Initialise the rand() system | |
init_rand(); | |
} | |
void deinit() { | |
// Turn off timer | |
deinit_timer(); | |
// Turn off I/O | |
deinit_io(); | |
// Start the watchdog to wake us up in 8 seconds | |
start_wdt(); | |
// Go to sleep | |
sleep(); | |
} | |
uint8_t touched() { | |
// Set PB4 to output and ground it | |
DDRB = (1<<PB1) | (1<<PB4); | |
PORTB = (1<<PB0) | (1<<PB2) | (1<<PB3); | |
// Set PB4 to input and enable pullup | |
DDRB = (1<<PB1); | |
PORTB = (1<<PB0) | (1<<PB2) | (1<<PB3) | (1<<PB4); | |
// See if it's charged | |
asm("nop \r\n nop"); | |
return !(PINB & (1<<PB4)); | |
} | |
volatile inline void delay() { | |
asm("nop \r\n nop \r\n nop \r\n nop \r\n nop \r\n"); | |
} | |
void fade_in() { | |
uint16_t i; | |
uint8_t j; | |
for(i=65280; i>12800; i--) { | |
OCR0B = i >> 8; | |
for(j=0; j<10; j++) | |
delay(); | |
} | |
OCR0B = 50; | |
} | |
void light() { | |
uint16_t i; | |
uint16_t imax = rand() << 2; | |
uint8_t j; | |
for(i=0; i<imax; i++) | |
for(j=0; j<255; j++) | |
delay(); | |
} | |
void fade_out() { | |
uint16_t i; | |
uint8_t j; | |
for(i=12800; i<65280; i++) { | |
OCR0B = i >> 8; | |
for(j=0; j<10; j++) | |
delay(); | |
} | |
OCR0B = 255; | |
} | |
void dark() { | |
uint16_t i; | |
uint16_t imax = rand() << 4; | |
uint8_t j; | |
for(i=0; i<imax; i++) | |
for(j=0; j<255; j++) | |
delay(); | |
} | |
int main() { | |
// Initialise sub-systems | |
init(); | |
// Check for capacitance, if found, light up | |
while(touched()) { | |
uint16_t i; | |
uint8_t imax = rand() >> 4; | |
for(i=0; i<imax; i++) { | |
fade_in(); | |
light(); | |
fade_out(); | |
dark(); | |
} | |
} | |
// Turn everything off and go to sleep | |
deinit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment