目次

画像処理下準備1

 SCCBによるカメラの初期設定ができたので、FPGAに
 入れる画像処理回路に必要となるVHDLコードを用意します。

 FPGAは、mugen2012を動かしたSpratan3を使います。

 Spratan3には、デュアルポートSRAMが内蔵されている
 ので、FIFOなしカメラから転送された、画像データを
 保存します。

 XilinxのISEには、VHDLコードのテンプレートが用意
 されているので、18kビットのデュアルポートSRAMに
 データを書込み、読出す処理で、動作をテストします。

 VHDLコードから抽出した信号名は、次のように
 なっていました。



 FPGA内部での同期に、クロックを利用します。
 デュアルポートというので、A、Bの2つのポート
 がありますが、個別に動作させられます。

 データは、18ビットの入力、出力が基本ですが
 パリティとデータに分けて扱います。

 パリティと言っても、データ中の1の個数に関連した
 情報を扱うのではなく、単純にデータへの付加情報と
 して扱います。

 パリティは1ビットであっても、バスで扱う仕様に
 なっています。今回は、16ビットで1データを扱い
 2ビットパリティ、16ビットデータにします。

 デュアルポートなので、Aポート、Bポートに分けて
 次のように扱います。

 書込み、読出しには制御信号が必要になりますが
 WEが対応します。他に、SSRがありますが、この
 信号は、メモリデータを全セットかリセットする
 同期処理をしたい場合に使います。

 仕様で決めた内容を、信号に反映させると以下。

 テストであっても、実処理に近い内容で動作させ
 たいので、次のように仕様を決めました。

 上の仕様をまとめると、次の動作確認ブロック図になります。



 デュアルポートSRAMのAポートから、1ワード
 データを書込むために、シーケンサを用意します。



 トリガーを捕捉後、アドレスとデータを変えながら
 Aポートから、SRAM内部にデータを書込みます。

  process (nRESET,iSCLK)
  begin
      if ( nRESET = '0' ) then
        iASTATE <= "000" ;
        iAADR   <= (others => '0') ;
      elsif rising_edge(iSCLK) then
        case conv_integer(iASTATE) is
          -- wait trigger
          when 0 => if ( iATRG = '1' ) then
                      iASTATE <= "001" ; 
                      iAADR   <= (others => '0') ;
                    else
                      iASTATE <= "000" ;
                    end if ;
          -- judge 
          when 1 => if ( iAADR(10) = '1' ) then
                      iASTATE <= "100" ; 
                    else
                      iASTATE <= "011" ;
                    end if ;
          -- generate data
          when 3 => iASTATE <= "111" ;
                    iADAT( 7 downto 0) <= iAADR( 7 downto 0) ;
                    if ( iAADR(0) = '1' ) then
                      iADAT(15 downto 8) <= X"55" ;
                    else
                      iADAT(15 downto 8) <= X"AA" ;
                    end if ;
          -- enable AWE
          when 7 => iASTATE <= "110" ; 
          -- address counter increment
          when 6 => iASTATE <= "001" ; 
                    iAADR   <= iAADR + '1' ;
          -- return first state
          when 4 => iASTATE <= "000" ; 
          when others => 
                    iASTATE <= "000" ;
        end case ;
      end if ;
  end process ;
  iAWE <= '1' when ( iASTATE = "111" ) else '0' ;

 デュアルポートSRAMのBポートから、1ワード
 データを読出すために、シーケンサを用意します。



 トリガーを捕捉後、アドレスとデータを変えながら
 Bポートから、SRAM内部のデータを読込みます。

  process (nRESET,iSCLK)
  begin
      if ( nRESET = '0' ) then
        iBSTATE <= "00" ;
        iBADR   <= (others => '0') ;
      elsif rising_edge(iSCLK) then
        case conv_integer(iBSTATE) is
          -- wait trigger
          when 0 => if ( iBTRG = '1' ) then
                      iBSTATE <= "01" ;
                    elsif ( iBADRC = '1' ) then
                      iBSTATE <= "10" ;
                      iBADR   <= (others => '0') ;
                    elsif ( iBADRI = '1' ) then
                      iBSTATE <= "10" ;
                      iBADR   <= iBADR + '1' ;
                    else
                      iBSTATE <= "00" ;
                    end if ;
          -- enable BOE
          when 1 => iBSTATE <= "11" ; 
          -- get data	
          when 3 => iBSTATE <= "10" ; 
          -- return first state
          when 2 => iBSTATE <= "00" ; 
          when others => 
                    iBSTATE <= "00" ;
        end case ;
      end if ;
  end process ;

 デュアルポートSRAMの処理をまとめると、以下と
 なります。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

entity sramtst is
  generic (
    TOPX : integer := 5 ; 
    XMAX : integer := 24 ;
    TOPY : integer := 14 ; 
    YMAX : integer := 10000 --;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- trigger 
    ATRG   : in  std_logic ;
    BTRG   : in  std_logic ;
    BADRC  : in  std_logic ;
    BADRI  : in  std_logic ;
    -- port B data
    BDAT  : out std_logic_vector(15 downto 0) ;
    -- port B data dummy
    BDATD  : out std_logic_vector( 1 downto 0) ;
    MDOUTA : out std_logic_vector(17 downto 0) --;
  );
end sramtst ;

architecture Behavioral of sramtst 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 ;
  -- internal clock
  signal iSCLK : std_logic ;
  signal iTCLK : std_logic ;
  -- SRAM
  signal iDOA   : std_logic_vector(15 downto 0); -- Port A 16-bit Data Output
  signal iBDAT  : std_logic_vector(15 downto 0); -- Port B 16-bit Data Output
  signal iDOPA  : std_logic_vector( 1 downto 0); -- Port A 2-bit Parity Output
  signal iDOPB  : std_logic_vector( 1 downto 0); -- Port B 2-bit Parity Output
  signal iBADR  : std_logic_vector( 9 downto 0); -- Port B 10-bit Address Input
  signal iCLKA  : std_logic                    ; -- Port A Clock
  signal iCLKB  : std_logic                    ; -- Port B Clock
  signal iADAT  : std_logic_vector(15 downto 0); -- Port A 16-bit Data Input
  signal iAWE   : std_logic                    ; -- Port A Write Enable Input
  -- trigger
  signal iATRG_SFT  : std_logic_vector(2 downto 0) ;
  signal iATRG      : std_logic ;
  signal iBTRG_SFT  : std_logic_vector(2 downto 0) ;
  signal iBTRG      : std_logic ;
  signal iBADRC_SFT : std_logic_vector(2 downto 0);
  signal iBADRC     : std_logic ;
  signal iBADRI_SFT : std_logic_vector(2 downto 0);
  signal iBADRI     : std_logic ;
  -- address and data (port A)
  signal iAADR   : std_logic_vector(10 downto 0);
  signal iASTATE : std_logic_vector( 2 downto 0);
  -- address (port B)
  signal iBSTATE : std_logic_vector( 1 downto 0);
begin
  -- component
  CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iSCLK); -- 1MHz
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iSCLK,iTCLK); -- 100Hz

  -- output
  BDAT <= not iBDAT ;

  -- dummy output
  BDATD  <= not iDOPB ;
  MDOUTA <= not (iDOPA & iDOA) ;

  -- SRAM
  RAMB16_S18_S18_inst : RAMB16_S18_S18
  generic map (
    INIT_A  => X"00000", --  Value of output RAM registers on Port A at startup
    INIT_B  => X"00000", --  Value of output RAM registers on Port B at startup
    SRVAL_A => X"00000", --  Port A ouput value upon SSR assertion
    SRVAL_B => X"00000", --  Port B ouput value upon SSR assertion
    WRITE_MODE_A => "WRITE_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
    WRITE_MODE_B => "WRITE_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
    SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL" 
    -- The follosing INIT_xx declarations specify the intiial contents of the RAM
    -- Address 0 to 255
    INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 256 to 511
    INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 512 to 767
    INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 768 to 1023
    INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
    INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- The next set of INITP_xx are for the parity bits
    -- Address 0 to 255
    INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 256 to 511
    INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 512 to 767
    INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
    -- Address 768 to 1023
    INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
    INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000"
  )
  port map (
    DOA   => iDOA,    -- Port A 16-bit Data Output
    DOB   => iBDAT,   -- Port B 16-bit Data Output
    DOPA  => iDOPA,   -- Port A 2-bit Parity Output
    DOPB  => iDOPB,   -- Port B 2-bit Parity Output
    ADDRA => iAADR(9 downto 0), -- Port A 10-bit Address Input
    ADDRB => iBADR,   -- Port B 10-bit Address Input
    CLKA  => iCLKA,   -- Port A Clock
    CLKB  => iCLKB,   -- Port B Clock
    DIA   => iADAT,   -- Port A 16-bit Data Input
    DIB   => X"FFFF", -- Port B 16-bit Data Input
    DIPA  => "11",    -- Port A 2-bit parity Input
    DIPB  => "11",    -- Port-B 2-bit parity Input
    ENA   => '1',     -- Port A RAM Enable Input
    ENB   => '1',     -- PortB RAM Enable Input
    SSRA  => '0',     -- Port A Synchronous Set/Reset Input
    SSRB  => '0',     -- Port B Synchronous Set/Reset Input
    WEA   => iAWE,    -- Port A Write Enable Input
    WEB   => '0'      -- Port B Write Enable Input
  );

  -- trigger
  process (nRESET,iTCLK)
  begin
    if ( nRESET = '0' ) then
      iATRG_SFT  <= "000" ;
      iBTRG_SFT  <= "000" ;
      iBADRC_SFT <= "000" ;
      iBADRI_SFT <= "000" ;
    elsif rising_edge(iTCLK) then
      iATRG_SFT  <= iATRG_SFT(1 downto 0) & ATRG ;
      iBTRG_SFT  <= iBTRG_SFT(1 downto 0) & BTRG ;
      iBADRC_SFT <= iBADRC_SFT(1 downto 0) & BADRC ;
      iBADRI_SFT <= iBADRI_SFT(1 downto 0) & BADRI ;
    end if ;
  end process ;
  iATRG  <= '1' when ( iATRG_SFT = "011" or iATRG_SFT = "001" ) else '0' ;
  iBTRG  <= '1' when ( iBTRG_SFT = "011" or iBTRG_SFT = "001" ) else '0' ;
  iBADRC <= '1' when ( iBADRC_SFT = "011" or iBADRC_SFT = "001" ) else '0' ;
  iBADRI <= '1' when ( iBADRI_SFT = "011" or iBADRI_SFT = "001" ) else '0' ;

  iCLKA <= iSCLK ;
  iCLKB <= iSCLK ;

  -- sequencer B
  process (nRESET,iSCLK)
  begin
      if ( nRESET = '0' ) then
        iBSTATE <= "00" ;
        iBADR <= (others => '0') ;
      elsif rising_edge(iSCLK) then
        case conv_integer(iBSTATE) is
          -- wait trigger
          when 0 => if ( iBTRG = '1' ) then
                      iBSTATE <= "01" ;
                    elsif ( iBADRC = '1' ) then
                      iBSTATE <= "10" ;
                      iBADR   <= (others => '0') ;
                    elsif ( iBADRI = '1' ) then
                      iBSTATE <= "10" ;
                      iBADR   <= iBADR + '1' ;
                    else
                      iBSTATE <= "00" ;
                    end if ;
          -- enable BOE
          when 1 => iBSTATE <= "11" ; 
          -- get data	
          when 3 => iBSTATE <= "10" ; 
          -- return first state
          when 2 => iBSTATE <= "00" ; 
          when others => 
                    iBSTATE <= "00" ;
        end case ;
      end if ;
  end process ;

  -- sequencer A
  process (nRESET,iSCLK)
  begin
      if ( nRESET = '0' ) then
        iASTATE <= "000" ;
        iAADR   <= (others => '0') ;
      elsif rising_edge(iSCLK) then
        case conv_integer(iASTATE) is
          -- wait trigger
          when 0 => if ( iATRG = '1' ) then
                      iASTATE <= "001" ; 
                      iAADR   <= (others => '0') ;
                    else
                      iASTATE <= "000" ;
                    end if ;
          -- judge 
          when 1 => if ( iAADR(10) = '1' ) then
                      iASTATE <= "100" ;
                    else
                      iASTATE <= "011" ;
                    end if ;
          -- generate data
          when 3 => iASTATE <= "111" ;
                    iADAT( 7 downto 0) <= iAADR( 7 downto 0) ;
                    if ( iAADR(0) = '1' ) then
                      iADAT(15 downto 8) <= X"55" ;
                    else
                      iADAT(15 downto 8) <= X"AA" ;
                    end if ;
          -- enable AWE
          when 7 => iASTATE <= "110" ; 
          -- address counter increment
          when 6 => iASTATE <= "001" ; 
                    iAADR   <= iAADR + '1' ;
          -- return first state
          when 4 => iASTATE <= "000" ; 
          when others => 
                    iASTATE <= "000" ;
        end case ;
      end if ;
  end process ;
  iAWE <= '1' when ( iASTATE = "111" ) else '0' ;

end Behavioral;

 動作を確認するために、マイコンを利用した
 環境を使いました。



 シリアルインタフェースを扱うファームウエアは
 以下です。

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sfr_defs.h>

#define MASKFF 0xff

#define OFF 0
#define ON  OFF+1

#define FOSC   12000000
#define BAUD   9600
#define MYUBRR (FOSC/16/BAUD)-1

#define BUFSIZE 4

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;
typedef   signed char  SBYTE ;
typedef   signed short SWORD ;

volatile UBYTE uflag ;

volatile UBYTE sbuf[BUFSIZE] ; 
volatile UBYTE sindex;

volatile UBYTE cnt ;
volatile UWORD cntx ;

volatile UBYTE cmd ;

const prog_char msg_h[] PROGMEM = "? help" ;
const prog_char msg_a[] PROGMEM = "A pulse" ;
const prog_char msg_b[] PROGMEM = "B pulse" ;
const prog_char msg_r[] PROGMEM = "R reset pulse" ;
const prog_char msg_i[] PROGMEM = "I increment pulse" ;

/*****************/
/* user function */
/*****************/
void  init_io(void);
void  usart_putchar(UBYTE x);
void  usart_puts(UBYTE *x);
void  crlf(void);
void  show_help(void);
UBYTE get_hex(UBYTE x);
void  send_pulse(UBYTE x);

#define CMD_A 0
#define CMD_B 1
#define CMD_R 2
#define CMD_I 3

/*------*/
/* main */
/*------*/
int main(void)
{
  /* initialize */
  init_io();
  /* enable interrupt */
  sei();
  /* endless loop */
  while ( ON ) {
    /* UART handling */
    if ( uflag == ON ) {
      /* clear flag */
      uflag = OFF ;
      /* get command */
      cmd = *(sbuf+0) ;
      /* command interpreter */
      if ( cmd == '?' ) { show_help() ; }
      if ( cmd == 'A' ) { send_pulse(CMD_A) ; }
      if ( cmd == 'B' ) { send_pulse(CMD_B) ; }
      if ( cmd == 'R' ) { send_pulse(CMD_R) ; }
      if ( cmd == 'I' ) { send_pulse(CMD_I) ; }
    }
  }
  /* dummy */
  return 0 ;
}

void init_io(void)
{
  /* set I/O initial values */
  PORTB = 0b00000000 ; /* 00000000 */
  PORTD = 0b11111101 ; /* pull up  */
  /* set I/O directions */
  DDRB = 0b11111111 ; /* all output */
  DDRD = 0b11111110 ; /* */
  /* clear registers */
  sindex = 0 ;
  cnt  = 0 ;
  cntx = 0 ;
  /* clear flags */
  uflag = OFF ;
  /* initialize UART */
  {
    /* set Baud Rate Registers */
    UBRRL = MYUBRR ;
    /* Enable receive interrupt , receive module and transmit module */
    UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN) ;
  }
}

void  usart_putchar(UBYTE x)
{
  while ( !(UCSRA & (1 << UDRE)) ) {}
  UDR = x ;
}

void  usart_puts(UBYTE *x)
{
  while ( *x != '\0' ) {
    usart_putchar( *x ) ;
    x++ ;
  }
  crlf();
}

void  crlf(void)
{
  usart_putchar('\r');
  usart_putchar('\n');
}

void show_help(void)
{
  char  msg[32];
  strcpy_P(msg,msg_h); usart_puts((UBYTE *)msg);
  strcpy_P(msg,msg_a); usart_puts((UBYTE *)msg);
  strcpy_P(msg,msg_b); usart_puts((UBYTE *)msg);
  strcpy_P(msg,msg_r); usart_puts((UBYTE *)msg);
  strcpy_P(msg,msg_i); usart_puts((UBYTE *)msg);
}

UBYTE get_hex(UBYTE x)
{
  UBYTE result ;
  /* default */
  result = 0 ;
  /* conversion */
  if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
  if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
  if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }

  return result ;
}

/* send pulse */
void  send_pulse(UBYTE x)
{
  volatile UBYTE i ;
  /* judge */
  if ( x > CMD_I ) return ;
  /* send H */
  PORTB |= (1 << x);
  /* delay */
  for ( i = 0 ; i < 128 ; i++ ) ;
  /* send L */
  PORTB &= ~(1 << x) ;
}

/* UART receive interrupt */
ISR(USART_RX_vect)
{
  volatile UBYTE ch ;
  /* get 1 charactoer */
  ch = UDR ;
  /* store */
  *(sbuf+sindex) = ch ;
  /* increment */
  sindex++ ;
  /* judge */
  if ( ch == '\r' ) {
    sindex = 0 ;
    uflag  = ON ;
  }
}


目次

inserted by FC2 system