library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use work.RS232.all; use work.I2C; use work.SCCB; entity CamControl is Port ( clk : in std_logic; -- serial port rs232RX : in std_logic; rs232TX : out std_logic; -- camera pins RSTB : out std_logic := '0'; -- reset (active low) PWDN : out std_logic; -- power down (power down = high) SCL : out std_logic; -- I2C clock SDA : inout std_ulogic; -- I2C i/o reset : out std_logic := '0' -- data capture reset ); end CamControl; architecture arch of CamControl is -- serial port: signal rxRequest : std_logic := '0'; signal rxRequestBuf : std_logic := '0'; signal rxGrant : std_logic := '0'; signal rxData : std_logic_vector(7 downto 0); signal txRequest : std_logic := '0'; signal txGrant : std_logic := '0'; signal txGrantBuf : std_logic := '0'; signal txData : std_logic_vector(7 downto 0); -- SPI port: signal SCCBdata : SCCB.tSCCBdata := SCCB.tSCCBdata_Default; signal SCCBdone : boolean := False; signal cmd : I2C.tByte; signal byteIDAddr : I2C.tByte; signal byteSubAddr : I2C.tByte; signal byteData : I2C.tByte; signal clkDiv : std_logic; type SerState is (CmdRecv, CmdRecv_Gra, CmdRecv_Fin, IDAddrRecv, IDAddrRecv_Gra, IDAddrRecv_Fin, SubAddrRecv, SubAddrRecv_Gra, SubAddrRecv_Fin, DataRecv, DataRecv_Gra, DataRecv_Fin, Reset_0, Reset_1, SccbWrite, SccbRead, SccbRead_2 ); constant CmdSccbWrite : I2C.tByte := x"01"; constant CmdSccbRead : I2C.tByte := x"02"; constant CmdSetReset : I2C.tByte := x"03"; constant CmdUnsetReset : I2C.tByte := x"04"; begin PWDN <= '0'; -- serial port: RS232_rx_Inst : RS232_rx port map ( Clock => clk, Rxd => rs232RX, Request => rxRequest, Grant => rxGrant, Data => rxData, CfgSpeed => "0100", CfgParity => '0', CfgParityType => '0' --Debug => led ); RS232_tx_Inst : RS232_tx port map ( Clock => clk, Txd => rs232TX, Request => txRequest, Grant => txGrant, Data => txData, CfgSpeed => "0100", CfgParity => '0', CfgParityType => '0' ); -- scale down clock for I2C (-> output clock = I2Cclk*8 = 10kHz*8 < 400kHz*8 process(clk) variable cnt : integer range 1 to 625 := 1; begin if clk'event and clk='1' then cnt := cnt + 1; if cnt = 625 then clkDiv <= not ClkDiv; cnt := 1; end if; end if; end process; -- I2C & main program process(clkDiv) variable state : SerState; variable state2 : integer range 0 to 100 := 0; variable ans : boolean := False; variable ansByte : I2C.tByte; begin if clkDiv'event and clkDiv='1' then -- init SPI I2C.initMaster(SCCBdata.I2Cdata, SCL, SDA); -- sample incoming handshake signals rxRequestBuf <= rxRequest; txGrantBuf <= txGrant; case state is when CmdRecv => -- receive serial byte (mode) reset <= '0'; if rxRequestBuf='1' then cmd <= rxData; state := CmdRecv_Gra; -- reset camera capture reset <= '1'; end if; when CmdRecv_Gra => -- grant rxGrant <= '1'; state := CmdRecv_Fin; when CmdRecv_Fin => -- wait for handshake done if rxRequestBuf='0' then rxGrant <= '0'; --report "cmd: " & str(cmd); -- select option if cmd = CmdSccbWrite then -- 0x01 = "3 phase write" state := IDAddrRecv; elsif cmd = CmdSccbRead then -- 0x02 = "2 phase write + 2 phase read" state := IDAddrRecv; report "--> read cmd"; elsif cmd = CmdSetReset then -- 0x03 = "reset to 0" (resetted) state := Reset_0; elsif cmd = CmdUnsetReset then -- 0x04 = "reset to 1" (operating) state := Reset_1; else state := CmdRecv; end if; end if; when IDAddrRecv => -- receive ID Addr if rxRequestBuf='1' then byteIDAddr <= rxData; state := IDAddrRecv_Gra; end if; when IDAddrRecv_Gra => -- grant rxGrant <= '1'; state := IDAddrRecv_Fin; when IDAddrRecv_Fin => -- wait for handshake done if rxRequestBuf='0' then rxGrant <= '0'; state := SubAddrRecv; --report "data: " & str(byteOut); report "got id addr"; end if; when SubAddrRecv => -- receive Sub Addr if rxRequestBuf='1' then byteSubAddr <= rxData; state := SubAddrRecv_Gra; end if; when SubAddrRecv_Gra => -- grant rxGrant <= '1'; state := SubAddrRecv_Fin; when SubAddrRecv_Fin => -- wait for handshake done if rxRequestBuf='0' then rxGrant <= '0'; if cmd = CmdSccbRead then state := SccbRead; else state := DataRecv; end if; --report "data: " & str(byteOut); report "got sub addr"; end if; when DataRecv => -- receive Sub Addr if rxRequestBuf='1' then byteData <= rxData; state := DataRecv_Gra; end if; when DataRecv_Gra => -- grant rxGrant <= '1'; state := DataRecv_Fin; when DataRecv_Fin => -- wait for handshake done if rxRequestBuf='0' then rxGrant <= '0'; state := SccbWrite; --report "data: " & str(byteOut); end if; -- **** Reset **** when Reset_0 => RSTB <= '0'; state := CmdRecv; when Reset_1 => RSTB <= '1'; state := CmdRecv; -- **** Write Mode **** when SccbWrite => if not SCCBdone then SCCB.Sccb3PhaseWriteCycle(SCCBdata, SCL, SDA, byteIDAddr, byteSubAddr, byteData, SCCBdone); else SCCBdone <= False; state := CmdRecv; end if; -- **** Read Mode **** when SccbRead => report "read step 1"; if not SCCBdone then SCCB.Sccb2PhaseWriteCycle(SCCBdata, SCL, SDA, byteIDAddr, byteSubAddr, SCCBdone); else SCCBdone <= False; state := SccbRead_2; byteIDAddr <= byteIDAddr + x"01"; report "read 1 done"; end if; when SccbRead_2 => report "read step 2"; if not SCCBdone then SCCB.Sccb2PhaseReadCycle(SCCBdata, SCL, SDA, byteIDAddr, byteData, SCCBdone); else SCCBdone <= False; state := CmdRecv; ansByte := byteData; ans := True; report "read 2 done"; end if; when others => null; end case; -- send back "answer" byte if ans=True then case state2 is when 0 => -- setup data txData <= ansByte; state2 := state2 + 1; when 1 => -- request transmission txRequest <= '1'; state2 := state2 + 1; when 2 => -- wait until done if txGrantBuf='1' then txRequest <= '0'; state2 := 0; --led(7) <= '1'; ans := False; end if; when others => null; end case; end if; end if; end process; end arch;