/*
 * Simple photoresistor-based motion detector
 * ATtiny version
 * 
 * This project is part of Accrochages
 * See http://accrochages.drone.ws
 * 
 * (c) 2008 Sofian Audry (info@sofianaudry.com)
 * (c) 2008 Samuel St-Aubin (samuel.staubin@gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */ 
#include <avr/io.h>
 
#define PIEZZO PB4                     // Define PIEZZO ext output pin on PB2

int i;                              // 8 bits integer

#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
 
// this is just a program that 'kills time' in a calibrated method
void delay_ms(uint8_t ms) {
  uint16_t delay_count = F_CPU / 17500;
  volatile uint16_t i;
  
  while (ms != 0) {
    for (i=0; i != delay_count; i++);
    ms--;
  }
}
//void delay_ms(uint8_t ms) {
//  uint16_t delay_count = F_CPU / 17500;
//  volatile uint16_t i;
//  
//  while (ms != 0) {
//    for (i=0; i != delay_count; i++);
//    ms--;
//  }
//}

unsigned int analogRead() {
  unsigned int low, high;
  
  ADCSRA |= (1 << ADEN);          // Analog-Digital enable bit
  ADCSRA |= (1 << ADSC);          // Discard first conversion

  while (ADCSRA & (1 << ADSC));  // wait until conversion is done

  ADCSRA |= (1 << ADSC);         // start single conversion

  while (ADCSRA & (1 << ADSC))  // wait until conversion is done

  ADCSRA &= ~(1<<ADEN);             // shut down the ADC
  
  //----------Show ADCH Byte in PIEZZO variable brightness indicator---------
	low = ADCL;
  high = ADCH;
  
  return (high << 8) | low;
}

int value;
int last_value;

#define THRESHOLD 3

unsigned int motion() {
  int motion;
  value = analogRead();
  motion = value - last_value;
  if (motion < 0)
    motion = -motion;
  last_value = value;
  return (unsigned int) motion;
}

void analogInit() {
  // Analog read initialization.
  ADCSRA |= (1 << ADEN) |          // Analog-Digital enable bit
            (1 << ADPS1) |         // set prescaler to 8    (clock / 8)
            (1 << ADPS0);          // set prescaler to 8    (clock / 8)

  ADMUX |= // (1 << ADLAR) |         // AD result store in (more significant bit in ADCH)
            (1 << MUX1) | (1 << MUX0);           // Choose AD input ADC3 (BP 3)
}

#define TIME_STEP 100

void playSquare(unsigned int period, unsigned int times)
{
  period /= 2;
  while (times--) {
    output_high(PORTB, PIEZZO);
    delay_ms(period);
    output_low(PORTB, PIEZZO);
    delay_ms(period);
  }
}

int main(void)
{
  unsigned int m;
  analogInit();

  set_output(DDRB, PIEZZO);              // Set output direction on PIEZZO
    
  output_low(PORTB, PIEZZO);
  
  motion(); // call one time to initialize the values
  
  for (;;)
  {
      if (TIME_STEP)
        delay_ms(TIME_STEP);
      
      m = motion();
      if (m > THRESHOLD) {
        playSquare(10, 10);
      }
  }
  
  return 0;
}
