目次

カメラ動作確認

 FIFO付カメラで撮影した画像を、カラー液晶で
 表示し、動作確認します。

 カラー液晶は、Nokiaの128x128(6100)を使います。



 コネクタは10ピンですが、非常に小さいので
 専用コネクタを使い、外部に引き出します。



 コネクタ上の各ピンは、以下。
  1. Vcc
  2. nRESET
  3. DATA
  4. CLK
  5. nCS
  6. Vcc
  7. (no connect)
  8. GND
  9. VLED-
  10. VLED+
 外部から見ると、カラー液晶は、メモリに見える  仕様です。  SPI相当のインタフェースで、アドレス、データを  外部電子回路から与えて対応します。  SPIは、8ビットのデータ転送ですが、この液晶の  インタフェースは、9ビット転送です。  さらに、受信ピンのみがあるだけ。  バックライト用に、VLED-/VLED+を使います。  (5V以上の電圧がかかるようにします。)  この2本は、電源電圧とは異なるので、別ワイヤーで  接続できるようにします。  このカメラをFPGAに接続できるようにします。  SCCBによるカメラの初期設定はマイコンに任せ  画像データ受信は、FPGAに担当させます。  テストに利用した基板は、ARMのADuC7026、FPGAは  Spartan3の50kゲートを使います。  FIFOなしカメラを利用し、FPGAで画像データを  取得するためのVHDLコードは、以下。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity camtst is generic ( TOPX : integer := 4 ; XMAX : integer := 12 ; TOPY : integer := 17 ; YMAX : integer := 80000 ; TOPZ : integer := 9 ; ZMAX : integer := 499 ; LCNT_MAX : integer := 120 ; PCNT_MAX : integer := 160 --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- camera PCLK : in std_logic ; VSYNC : in std_logic ; HREF : in std_logic ; GDAT : in std_logic_vector( 7 downto 0) ; -- monitor MFINDEX : out std_logic_vector( 9 downto 0) ; MOUT : out std_logic_vector( 1 downto 0) ; MGDAT : out std_logic_vector(15 downto 0) --; ); end camtst ; architecture Behavioral of camtst is -- component clock generator component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; -- clock signal iSCLK : std_logic ; -- camera state machine signal iVS_SFT : std_logic_vector(2 downto 0) ; signal iVSTRG : std_logic ; signal iPCLK_SFT : std_logic_vector(2 downto 0) ; signal iPTRG : std_logic ; signal iHREF : std_logic ; signal iLCNT : integer range 0 to LCNT_MAX ; signal iPCNT : integer range 0 to PCNT_MAX ; signal iCSTATE : std_logic_vector(3 downto 0) ; signal iFINDEX : integer range 0 to 924 ; signal iGDAT : std_logic_vector(15 downto 0) ; signal iMOUT : std_logic_vector(1 downto 0) ; begin -- component clock generator (48MHz/80000 = 600Hz) CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,CLOCK,iSCLK); -- input iHREF <= HREF ; -- output MOUT <= not iMOUT ; MGDAT <= not iGDAT ; MFINDEX <= not conv_std_logic_vector(iFINDEX,10); -- trigger process (nRESET,iSCLK) begin if ( nRESET = '0' ) then iVS_SFT <= "000" ; elsif rising_edge(iSCLK) then iVS_SFT <= iVS_SFT(1 downto 0) & VSYNC ; end if ; end process ; iVSTRG <= '1' when ( iVS_SFT = "011" or iVS_SFT = "001" ) else '0' ; --PCLK process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iPCLK_SFT <= "000" ; elsif rising_edge(CLOCK) then iPCLK_SFT <= iPCLK_SFT(1 downto 0) & PCLK ; end if ; end process ; iPTRG <= '1' when ( iPCLK_SFT = "011" or iPCLK_SFT = "001" ) else '0' ; -- camera sequencer process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iCSTATE <= "0000" ; iLCNT <= 0 ; iPCNT <= 0 ; iFINDEX <= 0 ; elsif rising_edge(CLOCK) then case conv_integer(iCSTATE) is -- wait trigger when 0 => if ( iVSTRG = '1' ) then iCSTATE <= "0001" ; iLCNT <= 0 ; iPCNT <= 0 ; iFINDEX <= 0 ; else iCSTATE <= "0000" ; end if ; -- judge line max when 1 => if ( iLCNT = LCNT_MAX ) then iCSTATE <= "1000" ; iLCNT <= 0 ; else iCSTATE <= "0011" ; end if ; -- judge pixel max when 3 => if ( iPCNT = PCNT_MAX ) then iCSTATE <= "1100" ; iPCNT <= 0 ; iLCNT <= iLCNT + 1 ; else iCSTATE <= "0111" ; end if ; -- get upper data when 7 => if ( iPTRG = '1' and iHREF = '1' ) then iCSTATE <= "1111" ; iGDAT(15 downto 8) <= GDAT ; else iCSTATE <= "0111" ; end if ; -- get lower data when 15 => if ( iPTRG = '1' and iHREF = '1' ) then iCSTATE <= "1110" ; iGDAT(7 downto 0) <= GDAT ; else iCSTATE <= "1111" ; end if ; -- store when 14 => iCSTATE <= "0011" ; if ( 13 < iPCNT and iPCNT < 147 ) then if ( iLCNT = 8 or iLCNT = 16 or iLCNT = 24 or iLCNT = 32 or iLCNT = 40 or iLCNT = 48 or iLCNT = 56 ) then -- iFINDEX <= iFINDEX + 1 ; end if ; end if ; iPCNT <= iPCNT + 1 ; -- pixel loop when 12 => iCSTATE <= "0001" ; -- return first state when 8 => iCSTATE <= "0000" ; -- default when others => iCSTATE <= "0000" ; end case ; end if ; end process ; iMOUT(0) <= '1' when ( iCSTATE(2 downto 0) = "111" ) else '0' ; iMOUT(1) <= '1' when ( iCSTATE = "1110" or iCSTATE = "1100" ) else '0' ; end Behavioral;  VSYNC、PCLKの立上がりエッジをつかまえて  シーケンサを動かします。  シーケンサから、フレームメモリ、LCDにデータ転送します。  1ライン=160ピクセル分を132ピクセルにし、フレーム  バッファには、0〜59のうちの7ライン分を格納します。  QQVGA(160x120)でカメラ動作を確認するため  ARMのADuC7026用ファームウエアは、以下です。 #include <ADuC7026.h> #define OFF 0 #define ON OFF+1 /* data definitions */ typedef unsigned char UBYTE ; typedef signed char SBYTE ; typedef unsigned short UWORD ; typedef signed short SWORD ; typedef unsigned long ULONG ; typedef signed long SLONG ; void IRQ_Handler(void) __irq; void init_usr(void); #define MASKFF 0xFF #define MASK0F 0x0F #define MASK80 0x80 #define MASK40 0x40 #define MASK20 0x20 #define MASK10 0x10 #define MASK08 0x08 #define MASK04 0x04 #define MASK02 0x02 #define MASK01 0x01 #define MASKF0 0xF0 #define SCCB_ID_WR 0x42 #define SCCB_ID_RD 0x43 #define S_SCL 23 #define S_SDA 22 #define S_WEN 21 #define S_RRST 20 #define S_OE 18 #define S_RCLK 17 #define S_VS 2 ULONG timcnt ; UBYTE lcnt ; UBYTE pcnt ; UWORD gtmp ; #define MAX_LCNT 120 #define MAX_PCNT 160 #define PCNT_FIRST 13 #define PCNT_LAST 147 void rs_putchar(UBYTE x); void crlf(void); void rs_puts(UBYTE *x); void show_help(void); void init_cam(void); void put_sccb_start(void); void put_sccb_stop(void); void put_sccb_data(UBYTE x); UBYTE get_sccb_data(void); UBYTE load_cam(UBYTE adr); void send_cam(UBYTE adr,UBYTE dat); void delay_ms(UWORD x); void delay_100us(UWORD x); UBYTE gdat(void); void set_rclk(UBYTE x); void set_oe(UBYTE x); void set_rrst(UBYTE x); void out_gdat(UBYTE col,UBYTE lin,UWORD x); void init_pla(void); void ca_handler(void); UBYTE is_valid_line(UBYTE x); /* global variables */ volatile UBYTE uflag ; volatile UBYTE sbuf[8] ; volatile UBYTE sindex ; volatile UBYTE cmd ; volatile UBYTE asc_hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; volatile UBYTE state ; volatile UBYTE cstate ; volatile UWORD vscnt ; volatile UBYTE strg ; volatile UBYTE vtrg ; volatile UBYTE ptrg ; volatile UWORD fbuf[924] ; volatile UBYTE findex ; #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ #define REG_BLUE 0x01 /* blue gain */ #define REG_RED 0x02 /* red gain */ #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ #define REG_COM1 0x04 /* Control 1 */ #define COM1_CCIR656 0x40 /* CCIR656 enable */ #define REG_BAVE 0x05 /* U/B Average level */ #define REG_GbAVE 0x06 /* Y/Gb Average level */ #define REG_AECHH 0x07 /* AEC MS 5 bits */ #define REG_RAVE 0x08 /* V/R Average level */ #define REG_COM2 0x09 /* Control 2 */ #define COM2_SSLEEP 0x10 /* Soft sleep mode */ #define REG_PID 0x0a /* Product ID MSB */ #define REG_VER 0x0b /* Product ID LSB */ #define REG_COM3 0x0c /* Control 3 */ #define COM3_SWAP 0x40 /* Byte swap */ #define COM3_SCALEEN 0x08 /* Enable scaling */ #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ #define REG_COM4 0x0d /* Control 4 */ #define REG_COM5 0x0e /* All "reserved" */ #define REG_COM6 0x0f /* Control 6 */ #define REG_AECH 0x10 /* More bits of AEC value */ #define REG_CLKRC 0x11 /* Clocl control */ #define CLK_EXT 0x40 /* Use external clock directly */ #define CLK_SCALE 0x3f /* Mask for internal clock scale */ #define REG_COM7 0x12 /* Control 7 */ #define COM7_RESET 0x80 /* Register reset */ #define COM7_FMT_MASK 0x38 #define COM7_FMT_VGA 0x00 #define COM7_FMT_CIF 0x20 /* CIF format */ #define COM7_FMT_QVGA 0x10 /* QVGA format */ #define COM7_FMT_QCIF 0x08 /* QCIF format */ #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ #define COM7_YUV 0x00 /* YUV */ #define COM7_BAYER 0x01 /* Bayer format */ #define COM7_PBAYER 0x05 /* "Processed bayer" */ #define REG_COM8 0x13 /* Control 8 */ #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ #define COM8_BFILT 0x20 /* Band filter enable */ #define COM8_AGC 0x04 /* Auto gain enable */ #define COM8_AWB 0x02 /* White balance enable */ #define COM8_AEC 0x01 /* Auto exposure enable */ #define REG_COM9 0x14 /* Control 9 - gain ceiling */ #define REG_COM10 0x15 /* Control 10 */ #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ #define COM10_HREF_REV 0x08 /* Reverse HREF */ #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ #define COM10_VS_NEG 0x02 /* VSYNC negative */ #define COM10_HS_NEG 0x01 /* HSYNC negative */ #define REG_HSTART 0x17 /* Horiz start high bits */ #define REG_HSTOP 0x18 /* Horiz stop high bits */ #define REG_VSTART 0x19 /* Vert start high bits */ #define REG_VSTOP 0x1a /* Vert stop high bits */ #define REG_PSHFT 0x1b /* Pixel delay after HREF */ #define REG_MIDH 0x1c /* Manuf. ID high */ #define REG_MIDL 0x1d /* Manuf. ID low */ #define REG_MVFP 0x1e /* Mirror / vflip */ #define MVFP_MIRROR 0x20 /* Mirror image */ #define MVFP_FLIP 0x10 /* Vertical flip */ #define REG_AEW 0x24 /* AGC upper limit */ #define REG_AEB 0x25 /* AGC lower limit */ #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ #define REG_HSYST 0x30 /* HSYNC rising edge delay */ #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ #define REG_HREF 0x32 /* HREF pieces */ #define REG_TSLB 0x3a /* lots of stuff */ #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ #define REG_COM11 0x3b /* Control 11 */ #define COM11_NIGHT 0x80 /* NIght mode enable */ #define COM11_NMFR 0x60 /* Two bit NM frame rate */ #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ #define COM11_50HZ 0x08 /* Manual 50Hz select */ #define COM11_EXP 0x02 #define REG_COM12 0x3c /* Control 12 */ #define COM12_HREF 0x80 /* HREF always */ #define REG_COM13 0x3d /* Control 13 */ #define COM13_GAMMA 0x80 /* Gamma enable */ #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ #define REG_COM14 0x3e /* Control 14 */ #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ #define REG_EDGE 0x3f /* Edge enhancement factor */ #define REG_COM15 0x40 /* Control 15 */ #define COM15_R10F0 0x00 /* Data range 10 to F0 */ #define COM15_R01FE 0x80 /* 01 to FE */ #define COM15_R00FF 0xc0 /* 00 to FF */ #define COM15_RGB565 0x10 /* RGB565 output */ #define COM15_RGB555 0x30 /* RGB555 output */ #define REG_COM16 0x41 /* Control 16 */ #define COM16_AWBGAIN 0x08 /* AWB gain enable */ #define REG_COM17 0x42 /* Control 17 */ #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ #define COM17_CBAR 0x08 /* DSP Color bar */ #define REG_RGB444 0x8c /* RGB 444 control */ #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ #define R444_RGBX 0x01 /* Empty nibble at end */ #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ int main(void) { /* initialize user */ init_usr(); /* show message */ rs_puts("Hello"); crlf(); /* endless loop */ while(ON) { /* command interrpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* judge */ cmd = *(sbuf+0) ; if ( cmd == '?' ) { show_help(); } /* initialize CAMERA */ if ( cmd == 'I' ) { crlf(); init_cam() ; } /* take shot */ if ( cmd == 'S' ) { strg = ON ; } } /* get graphic data from camera */ ca_handler(); } /* dummy return */ return (0); } void IRQ_Handler(void) __irq { volatile UBYTE ch ; /* judge UART receive interruption */ if ( (IRQSTA & UART_BIT) == UART_BIT ) { /* judge */ if ( COMSTA0 & 1 ) { /* clear flag */ ch = COMRX ; *(sbuf+sindex) = ch ; sindex++ ; if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } } /* judge timer0 interruption (100us) */ if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) { /* clear timer0 interrupt flag */ T0CLRI = 0xff ; /* increment */ timcnt++ ; /* judge */ if ( (timcnt & 0x3ff) == 0 ) { GP4DAT ^= (1 << 23); } } /* judge timer1 interruption (100Hz) */ if ( (IRQSTA & GP_TIMER_BIT) == GP_TIMER_BIT ) { /* clear timer0 interrupt flag */ T1CLRI = 0xff ; /* increment */ vscnt++ ; /* 600Hz handling */ if ( vscnt == 600 ) { vscnt = 0 ; /* get vsync signal */ GP3DAT ^= (1 << 23) ; } } /* judge PLA0 interruption (exteranl interruption) */ if ( (IRQSTA & PLA_IRQ0_BIT) == PLA_IRQ0_BIT ) { vtrg = OFF ; /* enable */ if ( strg == ON ) { /* set flag */ vtrg = ON ; } /* get vsync signal Debug */ GP3DAT ^= (1 << 22) ; } /* judge PLA1 interruption (exteranl interruption) */ if ( (IRQSTA & PLA_IRQ1_BIT) == PLA_IRQ1_BIT ) { ptrg = OFF ; /* enable */ if ( strg == ON ) { /* set flag */ ptrg = ON ; } /* get PCLK signal Debug */ GP3DAT ^= (1 << 21) ; } } void init_usr(void) { /* select clock 41.78MHz initialized in start up routine */ PLLKEY1 = 0xaa ; PLLCON = 0x01 ; PLLKEY2 = 0x55 ; /* power control initialized in start up routine */ /* clear flag */ uflag = OFF ; strg = OFF ; vtrg = OFF ; ptrg = OFF ; /* clear counter */ timcnt = 0 ; sindex = 0 ; state = 0 ; cstate = 0 ; vscnt = 0 ; /* initialize UART */ { /* set baud rate 38400 bps CD = 0 DL = 0x11 */ COMCON0 = 0x80 ; /* select COMDIV1 and COMDIV0 */ COMDIV0 = 0x22 ; //COMDIV0 = 0x44 ; COMDIV1 = 0x00 ; /* set conditions */ COMCON0 = 0x03 ; /* select COMRX and COMTX , 8bit data , 1 stop bit , no parity */ /* enable interrupt */ COMIEN0 = 0x01 ; /* ERBFI */ } /* P0 */ { /* */ GP0DAT = 0xFF3C0000 ; } /* P1 */ { /* GP1.4 (PLA IN) use UART */ GP1CON = 0x03030011 ; /* */ GP1DAT = 0x2E000000 ; } /* P2 */ { /* all bits input */ GP2DAT = 0x00000000 ; } /* P3 */ { GP3DAT = 0xffff0000 ; } /* P4 */ { GP4DAT = 0xff000000 ; } /* initialize timer 0 (100us) */ { T0LD = 4178 ; /* (41.78MHz / 1) / 10kHz */ T0CON = 0xc0 ; /* enable , cyclic , 1/1 */ } /* initialize timer 1 (600Hz) */ { T1LD = 4352 ; /* (41.78MHz / 16) / 600Hz */ T1CON = 0xc4 ; /* enable , cyclic , 1/16 */ } /* initialize PLA */ init_pla(); /* enable timer 0 interrupt , timer 1 interrupt and UART interrupt */ IRQEN = RTOS_TIMER_BIT | GP_TIMER_BIT | UART_BIT | PLA_IRQ0_BIT ; } /* UART putchar */ void rs_putchar(UBYTE x) { /* ? transmmit buffer empty */ while( (COMSTA0 & 0x40) == 0 ) ; /* set value */ COMTX = x ; } /* carriage return and line feed */ void crlf(void) { rs_putchar('\r'); rs_putchar('\n'); } /* UART puts */ void rs_puts(UBYTE *x) { while ( *x != '\0' ) { rs_putchar( *x ) ; x++ ; } } /* show help */ void show_help(void) { rs_puts("? help") ; crlf(); rs_puts("I initialize camera"); crlf(); rs_puts("S shot picture") ; crlf(); } void put_sccb_start(void) { /* both high level */ GP0DAT |= ((1 << S_SCL) | (1 << S_SDA)) ; /* SCL = ON ; SDA = ON */ delay_100us(3); /* 0 -> SDA */ GP0DAT &= ~(1 << S_SDA) ; /* SCL = ON ; SDA = OFF */ delay_100us(3); /* 0 -> SCL */ GP0DAT &= ~(1 << S_SCL) ; /* SCL = OFF ; SDA = OFF */ delay_100us(3); } void put_sccb_stop(void) { /* both high level */ GP0DAT |= (1 << S_SCL) ; /* SCL = ON ; SDA = ? */ delay_100us(3); /* 0 -> SDA */ GP0DAT &= ~(1 << S_SDA) ; /* SCL = ON ; SDA = OFF */ delay_100us(3); /* both high level */ GP0DAT |= (1 << S_SDA) ; /* SCL = ON ; SDA = ON */ delay_100us(3); } void put_sccb_data(UBYTE x) { UBYTE tmp ; UBYTE i ; /* load raw data */ tmp = x ; /* transfer data with write code */ for ( i = 0 ; i < 8 ; i++ ) { /* send bit datum */ GP0DAT &= ~(1 << S_SDA) ; if ( tmp & MASK80 ) { GP0DAT |= (1 << S_SDA) ; } delay_ms(1) ; /* 1 -> SCL */ GP0DAT |= (1 << S_SCL) ; delay_100us(5) ; /* shift */ tmp <<= 1 ; /* 0 -> SCL */ GP0DAT &= ~(1 << S_SCL) ; delay_100us(5) ; } /* data low */ GP0DAT &= ~(1 << S_SDA) ; delay_100us(5) ; /* change input */ GP0DAT &= ~(1 << 30) ; delay_100us(5) ; /* 1 -> SCL */ GP0DAT |= (1 << S_SCL) ; delay_100us(5) ; /* get acknowledge */ tmp = OFF ; if ( (GP0DAT & MASK40) == MASK40 ) { tmp = ON ; } /* 0 -> SCL */ GP0DAT &= ~(1 << S_SCL) ; delay_100us(5) ; /* change output */ GP0DAT |= (1 << 30) ; } UBYTE get_sccb_data(void) { UBYTE result ; UBYTE i ; UBYTE tmp ; /* change inupt */ GP0DAT &= ~(1 << 30) ; /* default */ result = 0 ; /* loop */ for ( i = 0 ; i < 8 ; i++ ) { /* shift */ result <<= 1 ; /* 1 -> SCL */ GP0DAT |= (1 << S_SCL) ; delay_100us(5) ; /* get bit datum */ if ( (GP0DAT & MASK40) == MASK40 ) { result |= ON ; } /* 0 -> SCL */ GP0DAT &= ~(1 << S_SCL) ; delay_100us(5) ; } /* 1 -> SCL */ GP0DAT |= (1 << S_SCL) ; delay_100us(5) ; /* get acknowledge */ tmp = OFF ; if ( (GP0DAT & MASK40) == MASK40 ) { tmp = ON ; } /* 0 -> SCL */ GP0DAT &= ~(1 << S_SCL) ; delay_100us(5) ; /* change output */ GP0DAT |= (1 << 30) ; return result ; } void send_cam(UBYTE adr,UBYTE dat) { /* start conditon */ put_sccb_start() ; /* send ID */ put_sccb_data(SCCB_ID_WR); /* send address */ put_sccb_data(adr); /* send parameter */ put_sccb_data(dat); /* stop condition */ put_sccb_stop(); /* delay */ delay_100us(5); } UBYTE load_cam(UBYTE adr) { UBYTE result ; /* start conditon */ put_sccb_start() ; /* send ID (write) */ put_sccb_data(SCCB_ID_WR); /* send address */ put_sccb_data(adr); /* stop condition */ put_sccb_stop(); /* start conditon */ put_sccb_start() ; /* send ID (read) */ put_sccb_data(SCCB_ID_RD); /* get parameter */ result = get_sccb_data(); /* stop condition */ put_sccb_stop(); return result ; } void delay_100us(UWORD x) { ULONG last ; /* calculate */ last = timcnt + x ; /* wait */ while ( timcnt < last ) ; } void delay_ms(UWORD x) { ULONG last ; /* calculate */ last = timcnt + 10 * x ; /* wait */ while ( timcnt < last ) ; } void init_cam(void) { send_cam(REG_COM7,COM7_RESET); //0x12:COM7(Reset,QCIF,Cbar,RGBformat) delay_ms(200); //200ms rs_puts("Complete reset"); crlf(); send_cam(REG_COM7,COM7_RGB | COM7_RGB); //0x12:COM7 , 0x0C) //RGB send_cam(REG_RGB444,R444_ENABLE | R444_RGBX); //0x8c:RGB 444 control send_cam(REG_COM1,0x40); //0x04:COM1(CCIR656,AEC) //0) //0x40) send_cam(REG_COM15,COM15_R01FE|COM15_RGB565); //0x40:COM15 send_cam(REG_COM9, 0x38); //0x14:COM9=max AGC gain ceiling, Freeze AGC/AEC //c(0x3d,0xc3) //(REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2) //0x3d:COM13 send_cam(REG_HAECC7,0x94); //0xaa:Hist AEC/AGC control 7 c(0xAA,0x94) //AEC algorithm send_cam(REG_TSLB,0x04); //0x3a:Neg,UVval,YUYV,window TSLB_YLAST) //0x04) //0x0C) //0x80) //0x00) //0x04) send_cam(0x20,0x0f); //ADCCTR0, A/D range&ref, mu0102 send_cam(REG_COM8,0x9a); //mu0103 send_cam(0x10,0x01); //mu0103 /* CLKRC */ send_cam(0x11,0x80); /* COM1 */ send_cam(0x3b,0x0a); /* disable night mode */ /* TSLB */ send_cam(0x3a,0x04); /* COM7 */ send_cam(0x12,0x04); /* RGB444 */ send_cam(0x8c,0x02); /* COM15 */ send_cam(0x40,0xd0); /* HSTART */ send_cam(0x17,0x16); /* HSTOP */ send_cam(0x18,0x04); /* HREF */ send_cam(0x32,0x24); /* VSTRT */ send_cam(0x19,0x02); /* VSTOP */ send_cam(0x1a,0x7a); /* VREF */ send_cam(0x03,0x0a); /* COM10 */ //send_cam(0x15,0x02); /* COM3 */ send_cam(0x0c,0x04); /* COM4 */ send_cam(0x3e,0x1a); /* SCALING_DCWCTR */ send_cam(0x72,0x22); /* SCALING_PCLK_DIV */ send_cam(0x73,0xf2); rs_puts("Exit initialize"); crlf(); } UBYTE gdat(void) { UBYTE result ; /* get graphic data */ result = GP2DAT & MASKFF ; return result ; } void set_rclk(UBYTE x) { if ( x ) { GP0DAT |= (1 << S_RCLK) ; } else { GP0DAT &= ~(1 << S_RCLK) ; } } void set_oe(UBYTE x) { if ( x ) { GP0DAT &= ~(1 << S_OE) ; } else { GP0DAT |= (1 << S_OE) ; } } void set_rrst(UBYTE x) { if ( x ) { GP0DAT &= ~(1 << S_RRST) ; } else { GP0DAT |= (1 << S_RRST) ; } } void out_gdat(UBYTE col,UBYTE lin,UWORD x) { UWORD tmp ; /* clear upper nibble */ tmp = x & 0x0fff ; /* judge */ if ( col > 131 ) return ; if ( lin > 120 ) return ; /* send data to LCD*/ } void init_pla(void) { /* VSYNC */ /* initialize element block #0 */ PLAELM0 = 0x549 ; /* NOT B and A */ PLAELM4 = 0x34 ; /* select GP1.4 , B */ PLAELM5 = 0x458 ; /* select E4 , A */ /* initialize element block #1 */ PLAELM6 = 0x035 ; /* P1.6 toss */ PLAELM7 = 0x659 ; /* E6 toss */ PLAELM8 = 0x058 ; /* get E6 and regist */ PLAELM9 = 0x034 ; /* get E9 and regist */ PLAELM15 = 0x025 ; /* not E8 and E9 */ /* select clock */ PLACLK = 0x35 ; /* HCLK , Timer1 overflow */ /* interrupt enable */ PLAIRQ = 0x1f10 ; /* element 15 H , element 1 H element 0 H */ } void ca_handler(void) { UBYTE res ; UBYTE href ; /* get HREF */ res = GP1DAT & MASKFF ; href = OFF ; if ( (res & MASK40) == MASK40 ) { href = ON ; } /* state machine */ switch (cstate) { /* wait trigger */ case 0 : cstate = 0 ; /* stay */ if ( vtrg == ON ) { vtrg = OFF ; lcnt = 0 ; /* clear line counter */ pcnt = 0 ; /* clear pixel counter */ findex = 0 ; /* clear frame index */ /* next state */ cstate = 1 ; } break ; /* judge end of line */ case 1 : cstate = 2 ; /* stay */ if ( lcnt == MAX_LCNT ) { lcnt = 0 ; /* clear line counter */ /* next */ cstate = 7 ; } break ; /* judge end of pixel */ case 2 : cstate = 3 ; /* next */ if ( pcnt == MAX_PCNT ) { /* next state */ cstate = 6 ; } break ; /* get upper byte */ case 3 : cstate = 3 ; /* stay */ if ( (ptrg & href) == ON ) { /* clear trigger flag */ ptrg = OFF ; /* get data and shift */ gtmp = gdat() ; gtmp <<= 8 ; /* next state */ cstate = 4 ; } break ; /* get lower byte */ case 4 : cstate = 4 ; /* stay */ if ( (ptrg & href) == ON ) { /* clear trigger flag */ ptrg = OFF ; /* get data */ gtmp |= gdat() ; /* next */ cstate = 5 ; } break ; /* store data */ case 5 : cstate = 2 ; /* next */ /* judge range */ if ( pcnt > PCNT_FIRST && pcnt < PCNT_LAST ) { /* juge valid line */ if ( is_valid_line(lcnt) == ON ) { *(fbuf+findex) = gtmp ; /* frame buffer index increment */ findex++ ; } } /* pixel counter increment */ pcnt++ ; break ; /* return line judgement */ case 6 : cstate = 1 ; /* next */ /* line counter increment */ lcnt++ ; /* clear pixel counter */ pcnt = 0 ; break ; /* return first state */ case 7 : cstate = 0 ; /* next */ strg = OFF ; break ; /* */ default : cstate = 0 ; break ; } } UBYTE is_valid_line(UBYTE x) { UBYTE result ; /* judge */ switch ( x ) { case 8 : case 16 : case 24 : case 32 : case 40 : case 48 : case 56 : result = ON ; break ; default : result = OFF ; break ; } return result ; } (under construction)
目次

inserted by FC2 system