
/**********************************************************/
/*                                                        */
/*  CMOS-EYE ATmega128二値化サンプルプログラム            */
/*  Target Board:BestTechnorogy BTC068                    */
/*  Environment:GDL1.7.4.0                                */
/*  Since:2006.9.12                                       */
/*  (c) AsakusaGiken Co., LTD.  T.Ishii                   */
/*                                                        */
/**********************************************************/

/*-----------------------------------------------------------------------------------
ピンアサイン

(CMOS-EYE - ATmega128)
A0  PA0
A1  PA1
A2  PA2
A3  PA3
A4  PA4
A5  PA5
A6  PA6
A7  PA7
A8  PC0
A9  PC1
A10 PC2
A11 PC3
A12 PC4
A13 PC5
A14 PC6
A15 PC7
A16 PG0
A17 PG1
A18 PG2
D0  PF0
D1  PF1
D2  PF2
D3  PF3
D4  PF4
D5  PF5
D6  PF6
D7  PF7
M0  PE5
M1  PE6
M2  PE7
CE  PE2
WE  PE3
OE  PE4
ST  PB0
BSY PB1
RX  PD3/TXD1 *CMOS-EYEシリアル命令用
TX  PD2/RXD1

(BTC068上ですでに配線されているもの)
LED PB7      *BTC068上のLED

(オシロ<-ATmega128)
TEST  PB2    *TESTは処理時間測定用、オシロスコープで波形を計測


------------------------------------------------------------------------------------------*/

/*-----------------------------------------------*/
/* ヘッダファイルインクルード                    */
/*-----------------------------------------------*/
#include <avr/io.h>     /* ATmega128の内部I/O定義をインクルード(GDL付属のヘッダファイル) */
#include <rs.h>             // USART通信ライブラリ
#include <stdlib.h>
#include <avr/interrupt.h>  // 割り込み関連
char txb[100],rxb[100];

/*-----------------------------------------------*/
/* 名称定義                                      */
/*-----------------------------------------------*/
/*---ピン---*/
#define ADDR1 PORTA
#define ADDR2 PORTC
#define ADDR3 PORTG
#define DATA_IN PINF
#define DATA_OUT PORTF
#define M0 PE5
#define M1 PE6
#define M2 PE7
#define CE PE2
#define WE PE3
#define OE PE4
#define ST PB0
#define BSY PB1
#define RX PD3
#define TX PD2
#define LED PB7
#define TEST PB2
/*---IO方向---*/
#define DATA_DIR DDRF
//#define INPUT 0
#define ALL_INPUT 0x00
//#define OUTPUT 1
#define ALL_OUTPUT 0xFF
/*---その他---*/
#define LOW 0
#define HIGH 1

/*-----------------------------------------------*/
/* グローバル変数                                */
/*-----------------------------------------------*/
int R,G,B;                  /*色平均値格納変数*/
unsigned char pix9[9];      /*周囲８ピクセルデータ格納配列*/


/*-----------------------------------------------*/
/* アドレスセット                                */
/*-----------------------------------------------*/
void set_address(long myAddr)
{
  /*引数は19ビット以上必要なのでlong 型(32ビット)*/
  ADDR1 = (unsigned char)(0x000000FF & myAddr);
  ADDR2 = (unsigned char)((0x0000FF00 & myAddr)>>8);
  ADDR3 = (unsigned char)((0x00070000 & myAddr)>>16);
}


/*-----------------------------------------------*/
/* 設定 (M0-M2,CE,WE,OEのみ)                     */
/*-----------------------------------------------*/
void set_high(unsigned char myPin)
{
  PORTE |= (1<<myPin);
}
void set_low(unsigned char myPin)
{
  PORTE &= ~(1<<myPin);
}

/*-----------------------------------------------*/
/* 設定 (STのみ)                                 */
/*-----------------------------------------------*/
void set_ST_low(void)
{
  PORTB &= ~(1<<ST);
}
void set_ST_high(void)
{
  PORTB |= (1<<ST);
}

/*-----------------------------------------------*/
/* 設定 (TESTのみ)                               */
/*-----------------------------------------------*/
void set_TEST_low(void)
{
  PORTB &= ~(1<<TEST);
}
void set_TEST_high(void)
{
  PORTB |= (1<<TEST);
}

/*-----------------------------------------------*/
/* BSY状態                                       */
/*-----------------------------------------------*/
unsigned char busy(void)
{
  return (PINB & 0x02)>>BSY;
}

/*-----------------------------------------------*/
/* LED (LOWで点灯、HIGHで消灯)                   */
/*-----------------------------------------------*/
void LED_ON(void)
{
  PORTB &= ~(1<<LED);
}
void LED_OFF(void)
{
  PORTB |= (1<<LED);
}


/*-----------------------------------------------*/
/* IO初期化                                      */
/*-----------------------------------------------*/
void init_io(void)
{
  /*---アドレスバス---*/
  DDRA = ALL_OUTPUT;      /*PORTAを出力へ*/
  DDRC = ALL_OUTPUT;      /*PORTCを出力へ*/
  DDRG |= 0x07;           /*PG0-PG2を出力へ*/
  /*---データバス---*/
  DATA_DIR = ALL_INPUT;   /*データバスをとりあえず入力へ*/
  /*---シリアルポート(USART1)---*/
  UCSR1B = 0x18;          /*USART1のTX,TRを有効*/
  UCSR1C = 0x06;          /*データ長８ビット,非同期,ノンパリ,ストップビット１*/
  UBRR1L = 103;           /*9600bps@16MHz*/
  /*---コントロール線---*/
  DDRE = 0xFC;           /*PE2-PE7(M0-2,CE.OE.WE)を出力へ*/
  DDRB = 0x85;           /*PB0,2,7(ST,TEST,LED)を出力へ、他(BSY,他)を入力へ*/
  /*---初期値---*/
  set_address(0);
  set_low(M0);
  set_low(M1);
  set_low(M2);
  set_high(CE);
  set_high(WE);
  set_high(OE);
  set_ST_high();
}


/*-----------------------------------------------*/
/* msウェイト                                    */
/*-----------------------------------------------*/
void wait_ms(unsigned long num)
{
  unsigned long i;

  TCCR0 = 0x04;                   /* 1/64(@16<Hz)でカウント開始 */
  TCNT0 = 0;
  for (i = 0; i < num; i++) {
    while (TCNT0<250);            /* 1mS待ち */
    TCNT0 = 0;                    /* カウンタクリア */
  }
  TCCR0 = 0;                      /* カウンタ停止 */
}


/*-----------------------------------------------*/
/* SCI3からデータ送信関数                        */
/*-----------------------------------------------*/
/* 受け取った配列からtxLength数分だけ送信*/
void tx(unsigned char* myData, unsigned char txLength)
{
  unsigned char i;
  for (i=0; i<txLength; i++){
    while( (UCSR1A & (1<<UDRE1)) == 0); /*送信データがエンプティになるまで待つ*/
      UDR1 = myData[i];                 /*送信データをセット（この後、自動で送信される）*/
    }
}


/*-----------------------------------------------*/
/* １ピクセルデータ読み込み関数                  */
/*-----------------------------------------------*/
/*この関数前に、 set_low(CE); と DATA_DIR = ALL_INPUT; を実行する必要あり*/
/*gpAddr：読み取りアドレス*/
unsigned char getPixData(long gpAddr)
{
    unsigned char result;       /*結果一時保存用変数*/
    set_address(gpAddr);        /*アドレスセット*/
    set_low(OE);                /*OE=LOWでデータバスにデータが表れる*/
    result = DATA_IN;           /*データを変数へ保存*/
    set_high(OE);               /*読み込みが終わったらOEをHIGHに戻す*/
    return result;              /*結果をリターン*/
}


/*-----------------------------------------------*/
/* １ピクセルデータ書き込み関数                  */
/*-----------------------------------------------*/
/*この関数前に、 CE=LOW; と DATA_DIR = ALL_OUTPUT; を実行する必要あり*/
/*spAddr：書き込みアドレス spData:書き込みデータ*/
void setPixData(long spAddr, unsigned char spData)
{
    set_address(spAddr);        /*アドレスセット*/
    DATA_OUT = spData;          /*データバスに値を出力*/
    set_low(WE);                /*WEをLOWで書き込み*/
    set_high(WE);               /*終わったらHIGHに戻す*/
}


/*-----------------------------------------------*/
/* 撮影関数                                      */
/*-----------------------------------------------*/
void shatter(void)
{
  LED_ON();
  while (busy() == LOW);         /*CMOS-EYEがBUSYなら待つ*/
    set_ST_low();                   /*シャッターを切る*/
    wait_ms(1);
    set_ST_high();
    wait_ms(1);                 /*撮影が開始されるまで少し待つ*/
    while (busy() == LOW);         /*撮影が終了するまで待つ(約70-100msかかる)*/
  LED_OFF();
}


/*-----------------------------------------------*/
/* 可変しきい値二値化                            */
/*-----------------------------------------------*/
void twoValue(long stAddr, long toAddr
              , int mySize, int threRef, int myDiff)
{
  int cnt;
  unsigned char data, myThre_hi,myThre_lo;      /* data:画素読み取り一時データ myThre:しきい値(Threshold)*/
  if (myDiff > threRef) myThre_lo = 0;                    /* しきい値下限値設定 */
  else myThre_lo = threRef - myDiff;
  if ( (threRef+myDiff) > 255) myThre_hi = 255;           /* しきい値上限値設定 */
  else myThre_hi = threRef + myDiff;
  data = 255;                                             /* 開始時は「前処理が白」に設定 */
  cnt = 0;                                                /* 相対アドレスを０(320x240の場合はlong型でないとNG)*/
  set_low(CE);                                            /* SRAMを有効 */
  for (cnt=0; cnt<mySize; cnt++){                         /* １画面分ループ */
    DATA_DIR = ALL_INPUT;                                   /* データバスを入力へ */
    if (data == 0) {                                        /* 前回処理結果が黒(0)だった場合 */
      if (getPixData(stAddr + cnt) > myThre_hi) data = 255;   /* しきい値=しきい値+許容値 */
      else data = 0;
    }else{                                                  /* 前回処理結果が白(255)だった場合 */
      if (getPixData(stAddr + cnt) > myThre_lo) data = 255;   /* しきい値=しきい値-許容値 */
      else data = 0;
    }
    DATA_DIR = ALL_OUTPUT;                                  /* データバスを出力へ */
    setPixData(toAddr + cnt, data);                         /* 結果（白か黒）を書き込み */
  }
  DATA_DIR = ALL_OUTPUT;                                  /* データバスを入力へ（出力衝突回避） */
  set_high(CE);                                           /* SRAMを無効 */
}


/*-----------------------------------------------*/
/* メイン                                        */
/*-----------------------------------------------*/
void main(void)
{
  unsigned char cnt;            /* ループカウント用変数 */
  unsigned char diff,x,y;
  unsigned long length,picAddr;

  /* ---IO初期化--- */
  init_io();

  /* ---LED３回点滅--- */
  for (cnt=0; cnt<3; cnt++){
    LED_ON();
    wait_ms(100);
    LED_OFF();
    wait_ms(100);
  }

  /* ---CMOS-EYEが立ち上がるまで待つ--- */
  wait_ms(3000);
  
  /*---画像モード設定---*/
  PORTE |= 0x1C;                /*80x60白黒モード*/
  wait_ms(200);                 /*設定終了まで待つ*/


  /*-----------------------------*/
  /*         メインループ        */
  /*-----------------------------*/
  diff = 50;                    /*誤差*/
  x = 80;                       /*画面幅*/
  y = 60;                       /*画面縦*/
  length = 4800;                /*画面サイズ*/
  picAddr = 0;                  /*撮影開始アドレス*/
  /*---5秒ごとにニ値化画像作成---*/
  while(1){                     /*無限ループ開始*/
    wait_ms(5000);
    set_address(picAddr);                   /*アドレスを指定*/
    shatter();                              /*撮影*/
    set_TEST_high();                        /*時間計測開始*/
    twoValue(picAddr, 4800, length, 80, 5); /* しきい値８０、幅５でニ値化(結果は4800番地-) */
    set_TEST_low();                      /*時間計測修了*/
  }

}

