Skip to content

Instantly share code, notes, and snippets.

@adamgreig
Created May 1, 2011 00:10
Show Gist options
  • Save adamgreig/950119 to your computer and use it in GitHub Desktop.
Save adamgreig/950119 to your computer and use it in GitHub Desktop.
ATtiny code to sense touch and flash an LED a few times
// 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