/***
  電子おもちゃ設計論最終課題『ホパンキラー』
  
  CPU: AT90S4433 4MHz
  Compiler: AVR-GCC(WinAVR) 3.4.1
  Date: 2005/07/11
  Author: Sho Hashimoto
  WebSite: http://web.sfc.keio.ac.jp/~t03792sh/
  ***/

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

#define TRUE 1
#define FALSE 0
#define NULL '\0'
#define DIST 200 // 距離 最近:390 最遠:80（部屋の明るさで変わる）

#define sbi(PORT,BIT) PORT|=_BV(BIT) // PORTの指定BITに1をセット
#define cbi(PORT,BIT) PORT&=~_BV(BIT) // PORTの指定BITをクリア

#define LED_SET() sbi(PORTB,PB0) // LED点灯
#define LED_CLR() cbi(PORTB,PB0) // LED消灯
#define HILED_SET() sbi(PORTD,PD4) // 高輝度LED点灯
#define HILED_CLR() cbi(PORTD,PD4) // 高輝度LED消灯
#define BEEP_SET() sbi(PORTD,PD3) // ブザーON
#define BEEP_CLR() cbi(PORTD,PD3) // ブザーOFF
#define PSD_V_SET() sbi(PORTB,PB2) // 距離センサ電源ON
#define PSD_V_CLR() cbi(PORTB,PB2); // 距離センサ電源OFF

/* No Operation */
void nop(int count){
  int i;
  for(i = 0; i < count*100; i++){
  }
}

/* webCamで撮影 */
void photo(void){
  sbi(PORTB,PB1);
  nop(30);
  cbi(PORTB,PB1);
  nop(180); // あまり連写撮影するとPC落ちるので
}

/* PORT設定  */
void port_init(void){
  DDRB = 0b00000111;
  DDRC = 0xff;
  cbi(DDRC,PC0);
  DDRD = 0b00011000;
}

/* UART設定 */
void uart_init(void){
  UCSRB = (1<<TXEN)|(1<<RXEN)|(1<<RXCIE); // 送信許可、受信許可、受信割り込み許可
  UBRR = 25; // ボーレート設定(4MHzの時は9600bps)
}

/* UARTで文字列を送る */
void uart_send_str(char *str){
  while(*str != NULL){
    loop_until_bit_is_set(UCSRA,UDRE); // 送信データレジスタ空きまで待機
    UDR = *str++; // 1文字送信、1文字進む
  }
}

/* intの桁数を返す */
char getDigit(int n){
  char i;
  i = 0;
  while(n>0){
    n /= 10;
    i++;
  }
  return i;
}

/* int->String変換 */
char *intToStr(int n, char *buf){ // 変換する数、作業領域
  int i, digit;
  digit = getDigit(n); // 桁数
  for(i = digit-1; i >= 0; i--){ // intは最大5桁
    buf[i] = n%10+'0';
    n /= 10;
  }
  buf[digit] = '\n'; // 行末改行
  return buf;
}

/* ADConverter設定 */
void adc_init(void){
  ADCSR = _BV(ADEN)|_BV(ADSC)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
  // A/D変換許可、1回目変換開始(調整)、分周率64
}

/* ADConverter(10bit)の指定ピンから読み込む  */
int adc_load(char pin){
  int ad;
  ADMUX = pin; // AD変換入力ピン
  cbi(ADCSR,ADIF); // 変換完了フラグクリア
  sbi(ADCSR,ADSC); // 変換開始
  loop_until_bit_is_set(ADCSR,ADIF); // ADIF(変換中は0)が0の間ループ
  ad = ADCL; // A/D値下位8bit取得
  return ad += (ADCH<<8); // A/D値上位2bit取得
  
}

int main(void){
  port_init(); // PORT設定
  uart_init(); // UART設定
  adc_init(); // ADConverter設定
  PSD_V_SET(); // 距離センサ起動
 
  LED_SET(); // 確認電源LED

  int ad;
  for(;;){
    ad = adc_load(PC0); // ADC0から距離センサの値取得
    if(ad>DIST){ // 近ければ
      HILED_SET(); // 高輝度LED
      BEEP_SET(); // ブザー鳴らす
      photo(); // 写真撮る
    }
    else{ // 遠ければ
      HILED_CLR();
      BEEP_CLR();
    }
    char buf[6];
    uart_send_str(intToStr(ad,buf)); // A/D値を文字列として送信（デバッグ用）
    nop(80); // ちょっと停止
  }
  
}


