/***********************************************************************/ /* */ /* CMOS-EYE SH2 線化画像処理サンプルプログラム */ /* Target :SH7144F(インターフェイス誌2006.6月号付録ボード) */ /* FILE :CMOS_EYE_SH2_Line.c */ /* Since :2006.8.29 */ /* Environment :HEW Ver 4.00(インターフェイス誌付録CD-ROMの環境) */ /* (c)AsakusaGiken Co., LTD. T.Ishii */ /* */ /***********************************************************************/ /* ピンアサイン (CMOS-EYE - SH) A0 PC0 A1 PC1 A2 PC2 A3 PC3 A4 PC4 A5 PC5 A6 PC6 A7 PC7 A8 PC10 A9 PC11 A10 PC12 A11 PC11 A12 PC12 A13 PC13 A14 PC14 A15 PC15 A16 PB0 A17 PB1 A18 PB6 D0 PD0 D1 PD1 D2 PD2 D3 PD3 D4 PD4 D5 PD5 D6 PD6 D7 PD7 M0 PB7 M1 PB8 M2 PB9 CE PA10 WE PA12 OE PA14 ST PB4 BSY PB5 (CMOS-EYEのシリアル端子 - SH2(シリアルのチャンネル3)) *CMOS-EYEシリアル命令及び、AGB65シリーズを動かす用 TX PE11/RXD3 RX PE12/TXD3 (オシロ - SH2) *TESTは処理時間測定用、オシロスコープで波形を計測 TEST PA2 (PC - SH) *プログラム転送用(RXD1/TXD1でPGをダウンロードするようだ) *さらに、RXD1/TXD1とRXD0/TXD0はボード上のRS232CコンバータICにつながっているので使用しない。 *ココは接続するのではなく、基板上ですでにつながってるので使えないという意味 RX PE11/RXD1 TX PE12/TXD1 LED PE15 */ /*-----------------------------------------------*/ /* ヘッダファイルインクルード */ /*-----------------------------------------------*/ #include "iodefine.h" /* IO名称定義 */ /*-----------------------------------------------*/ /* 名称定義 */ /*-----------------------------------------------*/ /*---ピン---*/ #define ADDR0_15 PC.DR.WORD /* アドレスバス */ #define ADDR16 PB.DR.BIT.B0 #define ADDR17 PB.DR.BIT.B1 #define ADDR18 PB.DR.BIT.B6 #define DATA PD.DR.BYTE.LL /* データバス */ #define M0 PB.DR.BIT.B7 /* 撮影モード設定端子 */ #define M1 PB.DR.BIT.B8 #define M2 PB.DR.BIT.B9 #define CE PA.DR.BIT.B10 /* SRAMコントロール端子 */ #define WE PA.DR.BIT.B12 #define OE PA.DR.BIT.B14 #define ST PB.DR.BIT.B4 /* シャッター端子(通常はHIGHにしておく) */ #define BSY PB.DR.BIT.B5 /* ビジー端子 */ #define TEST PA.DR.BIT.B2 /* 時間測定用端子(必須ではない) */ //#define RX PE.DRL.BIT.B11 //#define TX PE.DRL.BIT.B12 #define LED PE.DRL.BIT.B15 /* LED(基板に点いてるもの) */ /*---IO方向---*/ #define DATA_DIR PFC.PDIORL.BYTE.L /* データバス方向 */ #define INPUT 0 #define ALL_INPUT 0x00 #define OUTPUT 1 #define ALL_OUTPUT 0xFF /*---その他---*/ #define LOW 0 #define HIGH 1 #define LED_ON 0 #define LED_OFF 1 /*-----------------------------------------------*/ /* アドレスセット関数 */ /*-----------------------------------------------*/ void set_address(unsigned int myAddr) { ADDR0_15 = myAddr & 0x0000FFFF; ADDR16 = (myAddr & 0x00010000) >> 16; ADDR17 = (myAddr & 0x00020000) >> 17; ADDR18 = (myAddr & 0x00040000) >> 18; } /*-----------------------------------------------*/ /* IO初期化関数 */ /*-----------------------------------------------*/ void init_io(void) { /*---タイマ設定(MTU0を使用、ウェイト関数で使う)---*/ MST.CR2.BIT._MTU = 0; /* MTUのスタンバイ解除 */ MTU0.TCR.BIT.TPSC = 3; /* プリスケーラ設定 0:1/1 1:1/4 2:1/16 3:1/64 */ /*---IO方向---*/ PFC.PCIOR.WORD = 0xFFFF; /* PC0-15(アドレス下位)を出力へ */ PFC.PBIOR.BIT.B0 = 1; /* PB0(アドレス)を出力へ */ PFC.PBIOR.BIT.B1 = 1; /* PB1(アドレス)を出力へ */ PFC.PBIOR.BIT.B6 = 1; /* PB6(アドレス)を出力へ */ DATA_DIR = ALL_INPUT; /* データバスを入力へ(とりあえず) */ PFC.PBIOR.BIT.B7 = 1; /* PB7(M0)を出力へ */ PFC.PBIOR.BIT.B8 = 1; /* PB8(M1)を出力へ */ PFC.PBIOR.BIT.B9 = 1; /* PB9(M2)を出力へ */ PFC.PAIORL.BIT.B10 = 1; /* PA10(CE)を出力へ */ PFC.PAIORL.BIT.B12 = 1; /* PA12(WE)を出力へ */ PFC.PAIORL.BIT.B14 = 1; /* PA14(OE)を出力へ */ PFC.PBIOR.BIT.B4 = 1; /* PB4(ST)を出力へ */ PFC.PBIOR.BIT.B5 = 0; /* PB5(BSY)を入力へ */ PFC.PAIORL.BIT.B2 = 1; /* PA2(TEST)を出力へ */ PFC.PEIORL.BIT.B15 = 1; /* PE15(LED)を出力へ */ /*---シリアル設定(チャンネル3)---*/ /* SCI3.SSR.BIT.TDREが1のときSCI3.TDRに値をセットすると送信 */ MST.CR1.BIT._SCI3 = 0; /* SCI3のスタンバイ解除 */ PFC.PECRL1.BIT.PE11MD = 3; /* PE11端子をGPIO->RXへ設定 */ PFC.PECRL1.BIT.PE12MD = 3; /* PE12端子をGPIO->TXへ設定 */ SCI3.SMR.BYTE = 0x00; /* 通信設定(8bit,non-pari,stop1) */ SCI3.BRR = 77; /* ボーレート設定(9600bps@24MHz) */ SCI3.SCR.BIT.RE = 1; /* SCI3受信有効(使わないけど一応) */ SCI3.SCR.BIT.TE = 1; /* SCI3送信有効 */ /*---初期値---*/ set_address(0); M0 = LOW; M1 = LOW; M2 = LOW; CE = HIGH; WE = HIGH; OE = HIGH; ST = HIGH; TEST = LOW; LED = LED_OFF; } /*-----------------------------------------------*/ /* msウェイト */ /*-----------------------------------------------*/ /* 大分適当に作っているので正確でないです。*/ /* 正確なのを作りたい場合はコンペアマッチとか割り込みとか使って自作して下さい */ void wait_ms(int ms_time) { int i; MTU.TSTR.BIT.CST0 = 1; /* タイマMTU0スタート */ for (i=0; i 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; /* 相対アドレスを0(320x240の場合はlong型でないとNG)*/ CE = LOW; /* SRAMを有効 */ for (cnt=0; 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; /* データバスを入力へ(出力衝突回避) */ CE = HIGH; /* SRAMを無効 */ } /*-----------------------------------------------*/ /* 周囲8ピクセルデータ格納関数 */ /*-----------------------------------------------*/ void getPix8(unsigned char* myP, unsigned int myAddr, int xSize) { myP[0] = getPixData(myAddr + 1); /*右*/ myP[1] = getPixData(myAddr + 1 - xSize); /*右上*/ myP[2] = getPixData(myAddr - xSize); /*上*/ myP[3] = getPixData(myAddr - 1 - xSize); /*左上*/ myP[4] = getPixData(myAddr - 1); /*左*/ myP[5] = getPixData(myAddr - 1 + xSize); /*左下*/ myP[6] = getPixData(myAddr + xSize); /*下*/ myP[7] = getPixData(myAddr + 1 + xSize); /*右下*/ } /*-----------------------------------------------*/ /* 連結数計算関数 */ /*-----------------------------------------------*/ /* 現在位置が黒で、一個前が白なら連結数+1(反時計周り、右上から始める)*/ int connect(unsigned char* myP) { int i,result; myP[8] = myP[0]; /* 最後の参照は一番目なので一個追加して一番目をコピー */ result = 0; for (i=1; i<9; i++){ /* 二番目の配列からスタートして8回ループ */ if (myP[i] == 0 && myP[i-1] == 255) result++; /* 連結数判定 */ } return result; } /*-----------------------------------------------*/ /* 画面コピー */ /*-----------------------------------------------*/ void copy(unsigned int fmAddr, unsigned int toAddr, int mySize) { int cnt; unsigned char tempData; for (cnt=0; cnt= 2 && sum <= 5){ /* 周囲黒が2-5個の場合 */ if (connect(pa) == 1 && connect(pb) == 1){ /* 対象と結果両領域とも連結数が1か? */ con_flg = 1; /* 対象発見が有ったか?フラグ 最後まで1だったら有り */ for (cnt=1; cnt<5; cnt++){ /* 上3つと左の4箇所を調査 */ if (b[cnt] == 255){ /* 今までで白になっていて、 */ tempData = a[cnt]; a[cnt] = 255; /* 「そこ」を白にしてみて、 */ if (connect(pa) != 1){ /* 連結数=1かどうか? */ con_flg = 0; /* 白にできない場合、フラグを0へ */ } a[cnt] = tempData; /* 調査後は「そこ」元にもどす。 */ } } /* 4箇所調査end */ if (con_flg == 1){ /* 対象が有ったら白をセット */ myData = 255; find++; } } /* 両方連結数1か?end */ } /* 周囲黒が2-5 end */ DATA_DIR = ALL_OUTPUT; /* 結果書き込み */ setPixData(workAddr + adPointer, myData); DATA_DIR = ALL_INPUT; } /*自ピクセルが黒か?end*/ } /*xループend*/ } /*yループend*/ DATA_DIR = ALL_OUTPUT; copy(workAddr, stAddr, mySize); /* 結果画像を次の元画像へ(結果をコピー) */ } /*対象発見?end*/ DATA_DIR = ALL_INPUT; /* 後処理 */ CE = HIGH; } /*************************************************/ /* */ /* main関数 */ /* */ /*************************************************/ void main(void) { int cnt; unsigned char snd_data[5]; unsigned char* p; unsigned int picAddr; int diff,x,y,length; /* ---IO初期化--- */ init_io(); /* ---LED3回点滅--- */ for (cnt=0; cnt<3; cnt++){ LED = LED_ON; wait_ms(100); LED = LED_OFF; wait_ms(100); } /*---CMOS-EYEが起動するまで待つ---*/ wait_ms(3000); /*---画像モード設定---*/ M0 = LOW; /*80x60白黒モード*/ M1 = LOW; M2 = LOW; wait_ms(200); /*設定終了まで待つ*/ /*-----------------------------*/ /* メインループ */ /*-----------------------------*/ diff = 50; /*誤差*/ x = 80; /*画面幅*/ y = 60; /*画面縦*/ length = 4800; /*画面サイズ*/ picAddr = 0; /*撮影開始アドレス*/ set_address(picAddr); /*アドレスを指定*/ shatter(); /*撮影*/ twoValue(picAddr, 4800, length, 80, 5); /* しきい値80、幅5でニ値化(結果は4800番地-) */ CE = LOW; DATA_DIR = ALL_OUTPUT; copy(4800,19200,length); DATA_DIR = ALL_INPUT; CE = HIGH; TEST = HIGH; /*時間計測開始*/ Thinning(4800, 9600,length, x, y); /* 4800番地の二値化画像を細線化(作業領域は9600番地) */ TEST = LOW; /*時間計測修了*/ while(1); /*終了*/ }