プリミティブ関数定義

 階層構造で機能を実現したいので、基本となる関数(プリミティブ関数)
 を定義します。


I/O初期化

 ポート4、A、9、Bの初期値、入出力方向等を設定します。   void user_initialize(void)   {    /* PORT 4 */    P4DR = MASKFF ; /* disable all */    P4DDR = MASKFF ; /* all outputs */    /* PORT 9 */    PADR = 0 ;    PADDR = MASKFF ; /* all outputs */    /* PORT 9 */    P9DR = 0 ;    P9DDR = 0x03 ;    /* P90,P91 outputs others are inputs */    /* PORT B */    PBDR = 0xca ;    PBDDR = MASKCF ; /* PB5,PB4 inputs , others are outputs */    /* initialize timers */    init_timer0();    /* initialize SCI */    init_SCI0( br14400 );    init_SCI1( br57600 );    /* */    x_flags.DR = 0 ;    pre_ah = 0 ;    /* clear SCI buffer */    *(sbuf+0) = 0 ; sindex = 0 ;    /* system parameters */    /*    2^0 uncompressed 1 / compressed 0    2^1 gray scale 1 8bits / 0 2bits(binary)    2^2 size 1 160 x 128 / 0 80 x 64    2^3 preview 1 / snapshot 0    */    sysparam = 0x03 ; /* sysparam = 0x07 ; */    init_ring();    pwm_cnt = left_duty = right_duty = 0 ;    dcount = 0 ;   }

タイマー初期化

 c328にコマンドを送信し、応答があるまでは若干時間が必要です。  その時間を待つには、タイマー・カウンタを利用します。  タイマー・カウンタを初期化する関数を定義します。   void init_timer0(void)   {    /* stop timer */    ITU.TSTR.BIT.STR0 = OFF ;    /* TOER : Timer Output Enable Register 7 **** -> 0 6 **** -> 0 5 EXB4 -> 0 4 EXA4 -> 0 3 EB3 -> 0 2 EB4 -> 0 1 EA4 -> 0 0 EA3 -> 0    */    ITU.TOER.BYTE = 0 ;    /* TIOR : Timer I/O Control Register 7 **** -> 0 6 IOB2 -> 0 GRB is not output compare match register 5 IOB1 -> 0 4 IOB0 -> 0 3 **** -> 0 2 IOA2 -> 0 GRA is not output compare match register 1 IOA1 -> 0 0 IOA0 -> 0    */    ITU0.TIOR.BYTE = 0 ;    /* TCR : Timer Control Register 7 **** -> 0 6 CCLR1 -> 0 clear TCNT if GRA = TCNT 5 CCLR0 -> 1 4 CKEG1 -> 0 rising edge 3 CKEG0 -> 0 2 TPSC2 -> 0 φ利用 1 TPSC1 -> 0 0 TPSC0 -> 0    */    ITU0.TCR.BYTE = 0x20 ;    /* TIER : Timer Interrupt Enable Register 7 **** -> 0 6 *** -> 0 5 *** -> 0 4 *** -> 0 3 *** -> 0 2 OVIE -> 0 1 IMIEB -> 0 0 IMIEA -> 1 select compare match interrupt    */    ITU0.TIER.BIT.IMIEA = ON ;    /* reference */    ITU0.GRA = ITU0_AREG ;    ITU0.GRB = MASKFFFF ;    /* counter */    ITU0.TCNT = 0 ;    /* start timer */    ITU.TSTR.BIT.STR0 = ON ;   }  タイマー割込みが発生した場合の処理を記述します。  関数delay_msのために、1msごとにカウンタをディクリメントします。  PWMのDUTY比率を指定するため、変数をインクリメントし、指定値と比較  することで、出力論理値を決定します。   void int_imia0(void)   {    UBYTE dummy ;    /* clear flag */    dummy = ITU0.TSR.BIT.IMFA ;    ITU0.TSR.BIT.IMFA = OFF ;    /* judge */    if ( TTRG ) {    /* decrement counter */    wcnt-- ;    if ( wcnt == 0 ) {    TTRG = OFF ;    TFLAG = ON ;    }    }    /* pwm handling */    pwm_cnt++ ;    if ( pwm_cnt == 100 ) { pwm_cnt = 0 ; }    LMOTOR = RMOTOR = OFF ;    if ( pwm_cnt < left_duty ) { LMOTOR = ON ; }    if ( pwm_cnt < right_duty ) { RMOTOR = ON ; }    PB.DR.BIT.B2 = LMOTOR ;    PB.DR.BIT.B0 = RMOTOR ;   }

c328コマンド送信

 c328には、6バイトのコマンドを送信します。  コマンドごとに6バイトを、記述するのは面倒なので  必要なパラメータだけを指定する関数を使います。  6バイトのコマンドを送信する関数を定義します。   void send_command(void)   {    /* 0xAA */    rs_put_txd0( 0xAA ) ;    /* command */    rs_put_txd0( cmdp.param[0] );    /* parameters */    rs_put_txd0( cmdp.param[1] );    rs_put_txd0( cmdp.param[2] );    rs_put_txd0( cmdp.param[3] );    rs_put_txd0( cmdp.param[4] );   }  6バイトのコマンドをパラメータ設定するにあたり  最初の1バイトは固定なので、5バイトを0クリアする  関数を定義します。   void clear_command(void)   {    cmdp.param[0] = 0 ;    cmdp.param[1] = 0 ;    cmdp.param[2] = 0 ;    cmdp.param[3] = 0 ;    cmdp.param[4] = 0 ;   }  c328との通信を確立しなければ、コマンドを受け付けません。  SYNCを最大60回送信し、その間にACKを受信したかどうかを  論理値で返す関数を定義します。   UBYTE confirm_sync(void)   {    UBYTE i,tmp,doflag ;    /* default */    doflag = OFF ;    /* looping */    for ( i = 0 ; i < 60 ; i++ ) {    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" SYNC") ; }    /* send command */    send_sync();    /* wait */    delay_ms( 20 ) ;    /* judge */    if ( get_capacity() >= 12 ) {    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" Get Ack and Sync") ; }    doflag = ON ;    }    if ( doflag ) break ;    }    /* judge */    if ( doflag ) {    /* copy */    for ( i = 0 ; i < 12 ; i++ ) {    *(rbuf+i) = tmp = get_ring() ;    if ( DFLAG ) {    rs_put_txd1( get_hex( (tmp >> 4) & MASK0F ) );    rs_put_txd1( get_hex( tmp & MASK0F ) );    rs_put_txd1( ' ' );    }    }    i = 0 ;    if ( judge_response(0) == RES_ACK && *(rbuf+2) == 0x0D ) {    i++ ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" CONFIRM ACK") ; }    }    /* send ACK */    if ( judge_response(6) == RES_SYNC && *(rbuf+8) == 0x00 ) {    i++ ;    send_ack( 0x0D ) ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" SEND ACK") ; }    }    }    return doflag ;   }  パーソナルコンピュータをホストとして、マイクロコンピュータ内部に  c328をどう動かすのかを指定する変数を用意します。この変数へと値を  代入するためのラッパー関数を定義します。   UBYTE set_params(UBYTE x)   {    UBYTE i,doflag ;    /* clear */    clear_command();    /* send initial parameters */    cmdp.param[0] = 0x01 ;    /* color type    0x01 2-bit Gray Scale    0x02 4-bit Gray Scale    0x03 8-bit Gray Scale    0x05 12-bit Color    0x06 16-bit Color    0x07 JPEG    */    cmdp.param[2] = 0x01 ;    if ( x & 2 ) { cmdp.param[2] = 0x03 ; }    /* preview resolution    0x01 80 x 60    0x03 160 x 120    snap shot resolution    0x01 80 x 64    0x03 160 x 128    0x05 320 x 240    0x07 640 x 480    */    cmdp.param[3] = 0x01 ;    if ( x & 4 ) { cmdp.param[3] = 0x03 ; }    /* JPEG resolution    0x01 80 x 64    0x03 160 x 128    0x05 320 x 240    0x07 640 x 480    */    cmdp.param[4] = 0x03 ;    /* send command */    send_command();    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" SET PARAMETERS") ; }    /* wait */    while ( get_capacity() < 6 ) ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" exit PARAMETERS WAIT") ; }    /* copy */    for ( i = 0 ; i < 6 ; i++ ) { *(rbuf+i) = get_ring() ; }    /* judge */    doflag = ON ;    if ( judge_response(0) == RES_ACK && *(rbuf+2) == 1 ) {    doflag = OFF ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" confirm ACK") ; }    }    return doflag ;   }  SnapShotに必要なパラメータで指定する関数を定義します。   UBYTE set_snapshot(void)   {    UBYTE i,doflag ;    /* send command */    send_snapshot( sysparam );    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" SET SNAPSHOT") ; }    /* wait */    while ( get_capacity() < 6 ) ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" exit SNAPSHOT WAIT") ; }    /* copy */    for ( i = 0 ; i < 6 ; i++ ) { *(rbuf+i) = get_ring() ; }    /* judege */    doflag = ON ;    if ( judge_response(0) == RES_ACK && *(rbuf+2) == 5 ) {    doflag = OFF ;    if ( DFLAG ) { rs_puts_txd1((UBYTE *)" confirm ACK") ; }    }    return doflag ;   }  Syncに必要なパラメータを指定する関数を定義します。   void send_sync(void)   {    clear_command();    /* command */    cmdp.param[0] = 0x0D ;    /* send */    send_command() ;   }  Ackに必要なパラメータを指定する関数を定義します。   void send_ack(UBYTE x)   {    clear_command();    /* command */    cmdp.param[0] = 0x0E ; cmdp.param[1] = x ;    /* send */    send_command() ;   }  ShapShotに必要なパラメータを指定する関数を定義します。   void send_snapshot(UBYTE onoff)   {    clear_command();    /* command */    cmdp.param[0] = 0x05 ;    cmdp.param[1] = 0x00 ; /* compressed */    if ( onoff & 1 ) { cmdp.param[1] = 0x01 ; } /* uncompressed */    /* send */    send_command() ;   }  GetPictureに必要なパラメータを指定する関数を定義します。   void send_getpicture(UBYTE onoff)   {    clear_command();    /* command */    cmdp.param[0] = 0x04 ;    cmdp.param[1] = onoff ;    /* send */    send_command() ;   }

c328応答判断

 c328はコマンドに応答し、6バイトのコードを返信します。  6バイトの返信コードが、何であるかを判定します。  6バイトの最初は0xAA固定なので、続く16進コードが何かで  応答を判断します。   UBYTE judge_response(UBYTE x)   {    UBYTE result ;    /* set default */    result = RES_NONE ;    /* check command */    if ( *(rbuf+x) == 0xAA ) {    if ( *(rbuf+x+1) == 0x0A ) { result = RES_DATA ; }    if ( *(rbuf+x+1) == 0x0D ) { result = RES_SYNC ; }    if ( *(rbuf+x+1) == 0x0E ) { result = RES_ACK ; }    if ( *(rbuf+x+1) == 0x0F ) { result = RES_NAK ; }    }    return result ;   }
目次

inserted by FC2 system