Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * ATtiny85_Eyes.c
- *
- * Created: 11/25/2014 7:36:41 PM
- * Author: grist.carrigafoyl
- Some code to make 2 LEDs behave kind of like eyes.
- Want periodic blinking and the occasional wink.
- */
- #define F_CPU 8000000UL // 8Mhz
- #define LEFT_EYE PB0 // pin5
- #define RIGHT_EYE PB1 // pin6
- #define DELAY_MIN 20000 // about 6 seconds, rand() will add 0 - 32767 to this
- // Using the ADC as a random seed
- #define ADMUX_BITS 0b0000 // All default (VCC ref, ADLAR unset)
- #define ADC_PIN PB3 // an unconnected pin that will be floating
- // macros to set eye brightness
- #define SET_RIGHT_EYE_LEVEL(x) OCR0A = (255 - x)
- #define SET_LEFT_EYE_LEVEL(x) OCR0B = (255 - x)
- #include <avr/io.h>
- #include <avr/interrupt.h>
- // volatile because it's changed in the interrupt routine.
- volatile unsigned long counter = 0;
- // function prototypes
- void wink(uint8_t eye);
- void winkwink();
- void blink();
- void delay(unsigned int time);
- void fade_up(int delay_length);
- int read_adc();
- int main(void)
- {
- srand(read_adc()); // Should be fairly random with a floating pin
- unsigned int delay_time;
- int action;
- // Set the LED pins as output
- DDRB = _BV(LEFT_EYE) | _BV(RIGHT_EYE);
- // Enable ALL the Timer0 output compare interrupts!
- TIMSK = _BV(OCIE0A) | _BV(OCIE0B) | _BV(TOIE0);
- // Settings for the delay timer
- TIMSK |= _BV(TOIE1); // overflow timer 1
- // start the delay timer
- TCCR1 = _BV(CS12); // prescaler 8
- // start the PWM timer, prescaler 64, for around 485Hz
- TCCR0B = _BV(CS01) | _BV(CS00);
- // Enable global interrupts
- sei();
- // Time to get started
- fade_up(200);
- while(1)
- {
- action = rand(); // 0 - 32767
- // Change the thresholds to make actions more or less likely
- if (action < 25000) {
- blink();
- } else if (action < 28000) {
- wink(RIGHT_EYE);
- } else if (action < 31000) {
- wink(LEFT_EYE);
- } else {
- winkwink();
- }
- delay_time = rand() + DELAY_MIN;
- delay(delay_time);
- }
- }
- void blink()
- // Blink the eyes
- {
- int i; // brightness
- int delay_length = 2; // delay between changing brightness levels.
- for (i=255;i>0;i--) {
- SET_LEFT_EYE_LEVEL(i);
- SET_RIGHT_EYE_LEVEL(i);
- delay(delay_length);
- }
- delay(1000);
- for (i=0;i<255;i++) {
- SET_LEFT_EYE_LEVEL(i);
- SET_RIGHT_EYE_LEVEL(i);
- delay(delay_length);
- }
- }
- void wink(uint8_t eye)
- // Wink an eye
- {
- int i; // brightness
- int delay_length = 2; // delay between changing brightness levels.
- for (i=255;i>0;i--) {
- if (eye == RIGHT_EYE) {
- SET_RIGHT_EYE_LEVEL(i);
- } else {
- SET_LEFT_EYE_LEVEL(i);
- }
- delay(delay_length);
- }
- delay(1000);
- for (i=0;i<255;i++) {
- if (eye == RIGHT_EYE) {
- SET_RIGHT_EYE_LEVEL(i);
- } else {
- SET_LEFT_EYE_LEVEL(i);
- }
- delay(delay_length);
- }
- }
- void winkwink()
- // Wink both eyes in quick succession
- {
- wink(RIGHT_EYE);
- delay(1000);
- wink(LEFT_EYE);
- }
- void fade_up(int delay_length)
- // Fade both eyes up slowly.
- {
- int i; // brightness
- for (i=1;i<255;i++) {
- TCNT0 = 0; // reset the hardware counter
- SET_LEFT_EYE_LEVEL(i);
- SET_RIGHT_EYE_LEVEL(i);
- delay(delay_length);
- }
- }
- void delay(unsigned int time)
- // an arbitrary blocking delay
- {
- TCNT1 = 0; // reset the hardware counter
- counter = 0; // this is incremented by the overflow interrupt
- while (counter < time) {
- // dum de doo, twiddle twiddle.
- }
- }
- int read_adc()
- // Read the analog value from the ADC input pin. Using this as a random
- // seed as the pins are floating and could return almost anything.
- {
- // ADC settings. Check with data sheet that this is what you want
- ADCSRA |= _BV(ADEN) | // Enable ADC
- (_BV(ADPS0)) | // set pre-scaler to clock/128
- (_BV(ADPS1)) | // 8MHz/128 = 62.5Khz (aiming for 50 - 200)
- (_BV(ADPS2)); // so this is good
- // Code based on samples from http://avrbasiccode.wikispaces.com/
- int ret_val;
- // Assumes ADCSRA enabled and prescalars are set already
- // Set the input channel and other ADMUX bits
- ADMUX = (ADMUX_BITS << 4) | ADC_PIN;
- // Take a reading
- ADCSRA |= _BV(ADSC); // start a single conversion
- while (ADCSRA & _BV(ADSC)); // wait until conversion is done
- ret_val = ADCL; // Get ADCL first for 10bit and combine with ADCH
- return((ADCH << 8) | ret_val);
- }
- // Interrupt routines. Using COMPA & COMPB to generate PWM signals
- // on the two output pins. PWM frequency works out at about 495Hz
- ISR(TIMER0_OVF_vect)
- // Timer 0 overflow, so end of the pulse
- {
- PORTB = 0; // might as well turn 'em all off in one hit. no other output pins in this application.
- }
- ISR(TIMER0_COMPA_vect)
- // Start of the pulse for the left eye
- {
- PORTB |= _BV(LEFT_EYE);
- }
- ISR(TIMER0_COMPB_vect)
- // Start of the pulse for the right eye
- {
- PORTB |= _BV(RIGHT_EYE);
- }
- ISR(TIMER1_OVF_vect)
- // Overflow for timer 1. Used for the delay timer
- {
- counter++;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement