目次

モード別走行テスト

 MCRのコースは、直線、曲線、クランク、レーンチェンジで
 構成されています。



 デジタル回路やファームウエアを設計、開発する場合、毎回
 全コースを用意できるほど場所がないので、モードに分けて
 テストしたいと考えていました。

 DIPスイッチを利用しても、いろいろな状態を設定して
 走行させるには、パラメータ設定だけで疲れてしまい
 ますし、効率も悪いのは目に見えてます。

 マイコンやFPGAのデジタル回路に接続できて、パラメータ
 設定ができるようなシステムができないかと悩んでました。

 Z80で利用できるOSに、CP/M80がありました。

 他の研究で、EEPROMに入れたBootloaderを読込み、CP/Mの
 システムをSDカードから入力して起動する機構を作成して
 いました。

 下のEEPROMは、2kバイト容量ですが、モード指定や
 パラメータを入れておくのには、充分な容量です。



 MCR_VCマシンのシステム開発では、PersonalComputerを
 利用するので、PCからEEPROMに必要なパラメータを設定
 し、移動メカのマイコンやFPGAで読出してテストする
 方式を利用してみます。

 4時間くらいでできるようにしたいので、PCとEEPROMの間に
 マイコン基板を挟んで、EEPROMに必要な情報を転送できる
 ようにします。



 MCR_VCマシンのマイコンやFPGAには、電源投入後にEEPROMの
 情報を読出して使えるようなカラクリを用意します。



 MCR_VCマシンでは、特定ボタンを押しながら電源を入れると
 テストモードで走行できるカラクリを入れます。

 ここまで考えたなら、PCからEEPROMへのパラメータ設定と
 マイコンやFPGAが、EEPROMから情報を取得するカラクリを
 作っていきます。


PCからEEPROMへのパラメータ設定

 EEPROMに、AT93C86を利用します。  電源電圧が3Vから5Vの範囲で利用できるのと  アクセスが4ピンでFPGAでインタフェースする  のが簡単と判断して選定しました。  6ピンコネクタを利用して、マイコンやデジタル回路に  接続できるようにします。  マイコンにはArduinoを利用し、PCとはシリアルインタフェースで  接続します。EEPROMは、電源の他にArduinoのポートC(D14からD17)  を使い、接続します。  Arduinoのスケッチは、以下。 #include <MsTimer2.h> #define OFF 0 #define ON OFF+1 #define CS_BIT 3 #define SK_BIT 2 #define DI_BIT 1 #define DO_BIT 0 #define BSIZE 8 #define LED_BIT 5 #define MASK0F 0x0f #define MASKF0 0xf0 #define MASKFF 0xff #define LAST 256 byte uflag ; word gadr; word gdat; char sbuf[BSIZE] ; byte sindex ; char cmd ; byte state ; void rs_putchar(char x) { Serial.write( x ); } void rs_puts(char *ptr) { while ( *ptr ) { rs_putchar( *ptr ); ptr++ ; } } void crlf() { rs_putchar('\r'); rs_putchar('\n'); } void show_help() { rs_puts("? help"); crlf(); rs_puts("E put data to EEPROM"); crlf(); rs_puts("e show EEPROM contents"); crlf(); } byte get_hex(char x) { byte result ; /* default */ result = 0 ; /* convert */ 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 ; } char asc_hex(byte x) { char result ; /* default */ result = '0' ; /* judge */ if ( x < 10 ) { result += x ; } else { result = x - 10 + 'A' ; } return result ; } void mcs(byte x) { if ( x ) { PORTC |= (1 << CS_BIT) ; } else { PORTC &= ~(1 << CS_BIT) ; } } void msk(byte x) { if ( x ) { PORTC |= (1 << SK_BIT) ; } else { PORTC &= ~(1 << SK_BIT) ; } delayMicroseconds(1); } void mdi(byte x) { if ( x ) { PORTC |= (1 << DI_BIT) ; } else { PORTC &= ~(1 << DI_BIT) ; } } byte mdo() { return( PINC & ON ); } void enable_write(byte x) { word canda ; word cnt ; /* generate code */ canda = 0x2000 ; if ( x ) { canda = 0x2600 ; } /* enable CS */ mcs(ON); /* send */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); } void put_mem(word xadr,byte xdat) { word canda ; byte cnt ; /* enable write mode */ enable_write(ON); /* generate code */ canda = (0x2800 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* send data */ for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( xdat & 0x80 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ xdat <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); /* 10ms */ while ( mdo() != ON ) ; /* disable write mode */ enable_write(OFF); } byte get_mem(word xadr) { word canda ; byte cnt ; byte result ; /* generate code */ canda = (0x3000 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* get data */ result = 0 ; for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* SK : H */ msk(ON) ; /* shift */ result <<= 1 ; /* SK : L */ msk(OFF); /* get data */ if ( mdo() == ON ) { result |= ON ; } } /* disable CS */ mcs(OFF); return result ; } void show_mem(byte x) { word cnt ; word madr ; byte tmp ; char msg[4] ; /* check block number */ if ( x > 7 ) return ; /* generate address */ madr = (x << 8) ; /* repeat */ *(msg+2) = ' ' ; *(msg+3) = '\0' ; for ( cnt = 0 ; cnt < LAST ; cnt++ ) { /* get data */ tmp = get_mem(madr); /* update address */ madr++ ; /* convert */ *(msg+0) = asc_hex( (tmp >> 4) & MASK0F ) ; *(msg+1) = asc_hex( tmp & MASK0F ) ; /* show */ rs_puts( msg ); /* new line */ if ( (cnt & 15) == 15 ) { crlf(); } } } void update_trigger() { if ( state & ON ) { PORTB |= (1 << LED_BIT) ; } else { PORTB &= ~(1 << LED_BIT) ; } /* update */ state++ ; } void setup() { /* initialize serial port*/ Serial.begin(9600); sindex = 0 ; /* initialize PORT values */ PORTB = 0x00 ; PORTC = 0x01 ; PORTD = 0x01 ; /* initialize PORT directions */ DDRB = 0xff ; DDRC = 0xfe ; DDRD = 0xfe ; /* clear flags */ uflag = OFF ; /* LED handling */ state = 0 ; MsTimer2::set(200,update_trigger); /* enable */ MsTimer2::start(); } void loop() { /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* new line */ crlf(); /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help() ; } /* set EEPROM */ if ( cmd == 'E' ) { /* get address */ gadr = 0 ; gadr <<= 4 ; gadr |= get_hex( *(sbuf+1) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+2) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+3) ); /* get data */ gdat = 0 ; gdat <<= 4 ; gdat |= get_hex( *(sbuf+4) ); gdat <<= 4 ; gdat |= get_hex( *(sbuf+5) ); /* store */ put_mem( gadr , gdat ); } /* show EEPROM contents */ if ( cmd == 'e' ) { /* get block number */ gdat = get_hex( *(sbuf+1) ); /* show */ show_mem( gdat ); } } } void serialEvent() { char ch; if ( Serial.available() > 0 ) { /* get 1 charactor */ ch = Serial.read(); /* store */ sbuf[sindex] = ch ; /* increment */ sindex++ ; /* judge */ if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } }  コマンドは、3種用意しています。  ? ヘルプ  E アドレス、データを16進数で指定し設定  e ブロックを指定して、256バイト分表示  データ転送速度、データ長、ストップビット等はArduinoの  デフォルト値に合わせています。  EEPROMに格納する情報は、最大で2048バイト分ありますが  16バイトから32バイトあればよいと考えています。  ArudinoにEEPROMカセットを接続して、動作確認してみます。  シリアルインタフェースで接続して、ヘルプで確認。  0ページエリアの内容を確認。  アドレス0x000にデータ0xabをライトで、0ページエリアの  内容確認。  EEPROMカセットにアクセスできていることを確認できました。  モード別にテストするとして、各モードに必要となる情報をリスト。  NORMAL   モードを指定するために1バイト利用します。    アドレス0に0を設定。   左右あるいは前後のモータのDUTY比(0->99)を指定します。    アドレス1に左(前)のDUTY比を設定。    アドレス2に右(後)のDUTY比を設定。  CRANK   モードを指定するために1バイト利用します。    アドレス0に1を設定。   左右あるいは前後のモータのDUTY比(0->99)を指定します。    アドレス1に左(前)のDUTY比を設定。    アドレス2に右(後)のDUTY比を設定。   CRANKでは、白線を検出しているので、その情報が必要です。    アドレス3に白線の情報(ALL_WHITE = 1)を設定します。  LANE   モードを指定するために1バイト利用します。    アドレス0に2を設定。   左右あるいは前後のモータのDUTY比(0->99)を指定します。    アドレス1に左(前)のDUTY比を設定。    アドレス2に右(後)のDUTY比を設定。   LANEでは、片側白線を検出しているので、その情報が必要です。    アドレス3に白線の情報(LEFT_WHITE = 2 , RIGHT_WHITE = 3)    を設定します。  ここまでで、4バイトの情報があればよいとわかります。

移動メカのEEPROMからのパラメータ取得

 各モードのテストに必要な情報が4バイトとわかったので  マイコンやFPGAで、そのパラメータを取得する処理を定義  します。  ボタンの組み合わせで、情報取得して動くのか、センサー情報  を利用して動き出すかを切り分けて処理します。  パワーオンしてから、スイッチの状態を見てEEPROMから  パラメータを入力する処理にすればよさそうです。  シーケンスは、以下。
  1. パワーオン
  2. スイッチ状態取得
  3. スイッチ状態により、EEPROMからパラメータ取得
  4. レジスタにパラメータ設定
  5. パラメータごとの処理に分岐
 スイッチは、2ビットのDIPスイッチを利用します。  2ビットのDIPスイッチなので、組合せは4通りあり  コードで処理指定します。  2ビットで、すべてのモードをテストできるので  EEPROMには、4バイトx3=12バイトのパラメータ  を格納します。  アドレスとパラメータの関係は、以下としました。 0x00 00(NORMAL MODE) 0x01 ??(NORMAL MODE LEFT DUTY RATIO) 0x02 ??(NORMAL MODE RIGHT DUTY RATIO) 0x03 00(WHITE LINE) : 0x10 01(CRANK MODE) 0x11 ??(CRANK MODE LEFT DUTY RATIO) 0x12 ??(CRANK MODE RIGHT DUTY RATIO) 0x13 01(WHITE LINE) : 0x20 02(LANE MODE) 0x21 ??(LANE MODE LEFT DUTY RATIO) 0x22 ??(LANE MODE RIGHT DUTY RATIO) 0x23 02 or 03(WHITE LINE)  4バイトのパラメータで処理できますが、必要パラメータ数が  増えたときのことを考え、8バイトごとにしておきます。  パワーオンで、スイッチ状態を読み込み、指定された  アドレスからの8バイトをリード後、各変数に値設定  する処理を定義します。  Arduinoで動作を確認します。パワーオンでスイッチの状態を  読込んで、端末に各パラメータを表示します。 #define OFF 0 #define ON OFF+1 #define CS_BIT 3 #define SK_BIT 2 #define DI_BIT 1 #define DO_BIT 0 #define BSIZE 8 #define MASK0F 0x0f #define MASKF0 0xf0 #define MASKFF 0xff #define LAST 256 #define MD_NONE 0 #define MD_CRANK 1 #define MD_LANE 2 #define MD_NORMAL 3 volatile byte uflag ; volatile word gadr; volatile word gdat; volatile char sbuf[BSIZE] ; volatile byte sindex ; volatile char cmd ; volatile byte xmode ; volatile byte mflag ; volatile byte param[4] ; void rs_putchar(char x) { Serial.write( x ); } void rs_puts(char *ptr) { while ( *ptr ) { rs_putchar( *ptr ); ptr++ ; } } void crlf() { rs_putchar('\r'); rs_putchar('\n'); } void show_help() { rs_puts("? help"); crlf(); rs_puts("E put data to EEPROM"); crlf(); rs_puts("e show EEPROM contents"); crlf(); } byte get_hex(char x) { byte result ; /* default */ result = 0 ; /* convert */ 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 ; } char asc_hex(byte x) { char result ; /* default */ result = '0' ; /* judge */ if ( x < 10 ) { result += x ; } else { result = x - 10 + 'A' ; } return result ; } void mcs(byte x) { if ( x ) { PORTC |= (1 << CS_BIT) ; } else { PORTC &= ~(1 << CS_BIT) ; } } void msk(byte x) { if ( x ) { PORTC |= (1 << SK_BIT) ; } else { PORTC &= ~(1 << SK_BIT) ; } delayMicroseconds(10); } void mdi(byte x) { if ( x ) { PORTC |= (1 << DI_BIT) ; } else { PORTC &= ~(1 << DI_BIT) ; } } byte mdo() { return( PINC & ON ); } void enable_write(byte x) { word canda ; word cnt ; /* generate code */ canda = 0x2000 ; if ( x ) { canda = 0x2600 ; } /* enable CS */ mcs(ON); /* send */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); } void put_mem(word xadr,byte xdat) { word canda ; byte cnt ; /* enable write mode */ enable_write(ON); /* generate code */ canda = (0x2800 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* send data */ for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( xdat & 0x80 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ xdat <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); /* 10ms */ delay(12); /* disable write mode */ enable_write(OFF); } byte get_mem(word xadr) { word canda ; byte cnt ; byte result ; /* generate code */ canda = (0x3000 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* get data */ result = 0 ; for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* SK : H */ msk(ON) ; /* shift */ result <<= 1 ; /* SK : L */ msk(OFF); /* get data */ if ( mdo() == ON ) { result |= ON ; } } /* disable CS */ mcs(OFF); return result ; } void show_mem(byte x) { word cnt ; word madr ; byte tmp ; char msg[4] ; /* check block number */ if ( x > 7 ) return ; /* generate address */ madr = (x << 8) ; /* repeat */ *(msg+2) = ' ' ; *(msg+3) = '\0' ; for ( cnt = 0 ; cnt < LAST ; cnt++ ) { /* get data */ tmp = get_mem(madr); /* update address */ madr++ ; /* convert */ *(msg+0) = asc_hex( (tmp >> 4) & MASK0F ) ; *(msg+1) = asc_hex( tmp & MASK0F ) ; /* show */ rs_puts( msg ); /* new line */ if ( (cnt & 15) == 15 ) { crlf(); } } } byte get_sw() { byte result ; /* get */ result = (PINB & MASK0F) & 0x03 ; return result ; } void get_params(byte kx) { byte idx ; /* set index */ idx = 0 ; if ( kx == MD_CRANK ) { idx = 0x10 ; } if ( kx == MD_LANE ) { idx = 0x20 ; } /* get parameters */ *(param+0) = get_mem(idx+0) ; *(param+1) = get_mem(idx+1) ; *(param+2) = get_mem(idx+2) ; *(param+3) = get_mem(idx+3) ; } void show_params() { char xmsg[3] ; /* mode */ if ( *(param+0) == 0 ) { rs_puts("NORMAL"); } if ( *(param+0) == MD_CRANK ) { rs_puts("CRANK"); } if ( *(param+0) == MD_LANE ) { rs_puts("LANE"); } crlf(); /* default */ *(xmsg+2) = '\0' ; /* duty ratio */ *(xmsg+0) = asc_hex( *(param+1) / 16 ) ; *(xmsg+1) = asc_hex( *(param+1) % 16 ) ; rs_puts("1st = "); rs_puts( xmsg ) ; crlf() ; *(xmsg+0) = asc_hex( *(param+2) / 16 ) ; *(xmsg+1) = asc_hex( *(param+2) % 16 ) ; rs_puts("2nd = "); rs_puts( xmsg ) ; crlf() ; /* sensor */ if ( *(param+3) == 0 ) { rs_puts("Nothing"); } if ( *(param+3) == 1 ) { rs_puts("ALL_WHITE"); } if ( *(param+3) == 2 ) { rs_puts("LEFT_WHITE"); } if ( *(param+3) == 3 ) { rs_puts("RIGHT_WHITE"); } crlf(); } void setup() { /* initialize serial port*/ Serial.begin(9600); sindex = 0 ; /* initialize PORT values */ PORTB = 0x0f ; PORTC = 0x01 ; PORTD = 0x01 ; /* initialize PORT directions */ DDRB = 0xf0 ; DDRC = 0xfe ; DDRD = 0xfe ; /* clear flags */ uflag = OFF ; mflag = ON ; /* get switch state */ xmode = get_sw() ; } void loop() { /* one short handling */ if ( mflag == ON ) { /* clear flag */ mflag = OFF ; /* none */ if ( xmode == MD_NONE ) { rs_puts("NONE"); } else { /* get parameters from EEPROM */ get_params( xmode ); /* show */ show_params(); } crlf(); } /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* new line */ crlf(); /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help() ; } /* set EEPROM */ if ( cmd == 'E' ) { /* get address */ gadr = 0 ; gadr <<= 4 ; gadr |= get_hex( *(sbuf+1) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+2) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+3) ); /* get data */ gdat = 0 ; gdat <<= 4 ; gdat |= get_hex( *(sbuf+4) ); gdat <<= 4 ; gdat |= get_hex( *(sbuf+5) ); /* store */ put_mem( gadr , gdat ); } /* show EEPROM contents */ if ( cmd == 'e' ) { /* get block number */ gdat = get_hex( *(sbuf+1) ); /* show */ show_mem( gdat ); } } } void serialEvent() { char ch; if ( Serial.available() > 0 ) { /* get 1 charactor */ ch = Serial.read(); /* store */ sbuf[sindex] = ch ; /* increment */ sindex++ ; /* judge */ if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } }  このスケッチの動作テストをしてみます。  TeraTermを動かし、ヘルプを表示。  EEPROMの内容を確認。  スイッチを(ON,ON)=(1,1)としたとき。  スイッチを(ON,ON)=(0,1)としたとき。  スイッチを(ON,ON)=(1,0)としたとき。  このスケッチで、間違いなく動作論理が正しいと  わかりました。  ただし、Arduinoのスケッチでは初期化処理で何か  やっているらしく、EEPROMの内容が破壊されること  がありました。  Arduinoを使わずに、FPGA内部にプロセッサを用意するか  専用デジタル回路を使って対応します。  よく考えてみると、ATmega168をArduinoではなく、単なる  AVRで利用すればよいでした。  その場合のコードは、以下。 #include <avr/io.h> #include <avr/interrupt.h> #define FOSC 16000000 #define BAUD 9600 #define MYUBRR (FOSC/16/BAUD)-1 #define OFF 0 #define ON OFF+1 #define CS_BIT 3 #define SK_BIT 2 #define DI_BIT 1 #define DO_BIT 0 #define BSIZE 8 #define MASK0F 0x0f #define MASKF0 0xf0 #define MASKFF 0xff #define BUFSIZE 8 #define LAST 256 typedef unsigned char UBYTE ; typedef unsigned short UWORD ; typedef unsigned long ULONG ; typedef signed char SBYTE ; typedef signed short SWORD ; volatile UBYTE sbuf[BUFSIZE] ; volatile UBYTE sindex; volatile UWORD tickcount ; volatile UBYTE uflag ; volatile UBYTE mflag ; volatile UBYTE xmode ; volatile UWORD gadr ; volatile UBYTE gdat ; volatile UBYTE cmd ; volatile UBYTE param[4] ; #define NO 0 #define YES NO+1 #define MD_NONE 0 #define MD_CRANK 1 #define MD_LANE 2 #define MD_NORMAL 3 /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); void command_interpret(void); void rs_putchar(UBYTE x); void crlf(void); void rs_puts(UBYTE *x); void show_help(void); UBYTE get_hex(char x); SBYTE asc_hex(UBYTE x); void mcs(UBYTE x); void msk(UBYTE x); void mdi(UBYTE x); UBYTE mdo(void); void enable_write(UBYTE x); void put_mem(UWORD xadr,UBYTE xdat); UBYTE get_mem(UWORD xadr); void show_mem(UBYTE x); UBYTE get_sw(void); void get_params(UBYTE kx); void show_params(void); void delay_ms(UWORD x); /*------*/ /* main */ /*------*/ int main(void) { /* initialize port and variables */ user_initialize(); /* enable interrupt */ sei(); /* endless loop */ while ( ON ) { /* one short handling */ if ( mflag == ON ) { /* clear flag */ mflag = OFF ; /* none */ if ( xmode == MD_NONE ) { rs_puts((UBYTE *)"NONE"); } else { /* get parameters from EEPROM */ get_params( xmode ); /* show */ show_params(); } crlf(); } /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* new line */ crlf(); /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help() ; } /* set EEPROM */ if ( cmd == 'E' ) { /* get address */ gadr = 0 ; gadr <<= 4 ; gadr |= get_hex( *(sbuf+1) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+2) ); gadr <<= 4 ; gadr |= get_hex( *(sbuf+3) ); /* get data */ gdat = 0 ; gdat <<= 4 ; gdat |= get_hex( *(sbuf+4) ); gdat <<= 4 ; gdat |= get_hex( *(sbuf+5) ); /* store */ put_mem( gadr , gdat ); } /* show EEPROM contents */ if ( cmd == 'e' ) { /* get block number */ gdat = get_hex( *(sbuf+1) ); /* show */ show_mem( gdat ); } } } /* dummy */ return 0 ; } #/*-----------------------*/ /* Insert user functions */ /*-----------------------*/ void user_initialize(void) { /* initialize PORT values */ PORTB = 0x0f ; PORTC = 0x01 ; PORTD = 0x01 ; /* initialize PORT directions */ DDRB = 0xf0 ; DDRC = 0xfe ; DDRD = 0xfe ; /* initialize serial */ { /* set Baud Rate Registers */ UBRR0H = MYUBRR / 256; UBRR0L = MYUBRR % 256 ; /* Enable receive interrupt , receive module and transmit module */ UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) ; /* select 8bits data length */ UCSR0C = (3 << 1) ; } /* clear index */ sindex = 0 ; /* initialize timer1 */ { /* clear counter */ TCNT1 = 0 ; /* initialize counter */ OCR1A = 1999; /* set prescaler (/8) select clock and prescaler (generate 2MHz) */ TCCR1B = (1 << WGM12) | (1 << CS11) ; /* Enable interrupt */ TIMSK1 = (1 << OCIE1A) ; } /* */ tickcount = 0 ; /* clear flags */ uflag = OFF ; mflag = ON ; /* get switch state */ xmode = get_sw() ; } /* UART receive interrupt */ ISR(USART_RX_vect) { volatile UBYTE ch ; /* get 1 charactoer */ ch = UDR0 ; /* store */ *(sbuf+sindex) = ch ; sindex++ ; /* judge */ if ( ch == '\r' ) { uflag = ON ; sindex = 0 ; } } void rs_putchar(UBYTE x) { while ( !( UCSR0A & (1 << UDRE0)) ) UDR0 = x ; } void crlf(void) { rs_putchar('\r'); rs_putchar('\n'); } void rs_puts(UBYTE *x) { /* send charactor one by one */ while ( *x != '\0' ) { rs_putchar( *x ) ; /* pointer increment */ x++ ; } crlf(); } void show_help() { rs_puts((UBYTE *)"? help"); crlf(); rs_puts((UBYTE *)"E put data to EEPROM"); crlf(); rs_puts((UBYTE *)"e show EEPROM contents"); crlf(); } UBYTE get_hex(char x) { UBYTE result ; /* default */ result = 0 ; /* convert */ 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 ; } SBYTE asc_hex(UBYTE x) { SBYTE result ; /* default */ result = '0' ; /* judge */ if ( x < 10 ) { result += x ; } else { result = x - 10 + 'A' ; } return result ; } void mcs(UBYTE x) { if ( x ) { PORTC |= (1 << CS_BIT) ; } else { PORTC &= ~(1 << CS_BIT) ; } } void msk(UBYTE x) { if ( x ) { PORTC |= (1 << SK_BIT) ; } else { PORTC &= ~(1 << SK_BIT) ; } delay_ms(1); } void mdi(UBYTE x) { if ( x ) { PORTC |= (1 << DI_BIT) ; } else { PORTC &= ~(1 << DI_BIT) ; } } UBYTE mdo(void) { UBYTE result ; result = PINC ; result &= ON ; return( result ); } void enable_write(UBYTE x) { UWORD canda ; UWORD cnt ; /* generate code */ canda = 0x2000 ; if ( x ) { canda = 0x2600 ; } /* enable CS */ mcs(ON); /* send */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); } void put_mem(UWORD xadr,UBYTE xdat) { UWORD canda ; UBYTE cnt ; /* enable write mode */ enable_write(ON); /* generate code */ canda = (0x2800 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* send data */ for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( xdat & 0x80 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ xdat <<= 1 ; /* SK : L */ msk(OFF); } /* disable CS */ mcs(OFF); /* 10ms */ delay_ms(10) ; /* disable write mode */ enable_write(OFF); } UBYTE get_mem(UWORD xadr) { UWORD canda ; UBYTE cnt ; UBYTE result ; /* generate code */ canda = (0x3000 | xadr) ; /* enable CS */ mcs(ON); /* send command and address */ for ( cnt = 0 ; cnt < 14 ; cnt++ ) { /* impress data */ mdi(OFF) ; if ( canda & 0x2000 ) { mdi(ON) ; } /* SK : H */ msk(ON) ; /* shift */ canda <<= 1 ; /* SK : L */ msk(OFF); } /* get data */ result = 0 ; for ( cnt = 0 ; cnt < 8 ; cnt++ ) { /* SK : H */ msk(ON) ; /* shift */ result <<= 1 ; /* SK : L */ msk(OFF); /* get data */ if ( mdo() == ON ) { result |= ON ; } } /* disable CS */ mcs(OFF); return result ; } void show_mem(UBYTE x) { UWORD cnt ; UWORD madr ; UBYTE tmp ; SBYTE msg[4] ; /* check block number */ if ( x > 7 ) return ; /* generate address */ madr = (x << 8) ; /* repeat */ *(msg+2) = ' ' ; *(msg+3) = '\0' ; for ( cnt = 0 ; cnt < LAST ; cnt++ ) { /* get data */ tmp = get_mem(madr); /* update address */ madr++ ; /* convert */ *(msg+0) = asc_hex( (tmp >> 4) & MASK0F ) ; *(msg+1) = asc_hex( tmp & MASK0F ) ; /* show */ rs_puts((UBYTE *)msg); /* new line */ if ( (cnt & 15) == 15 ) { crlf(); } } } UBYTE get_sw() { UBYTE result ; /* get */ result = (PINB & MASK0F) & 0x03 ; return result ; } void get_params(UBYTE kx) { UBYTE idx ; /* set index */ idx = 0 ; if ( kx == MD_CRANK ) { idx = 0x10 ; } if ( kx == MD_LANE ) { idx = 0x20 ; } /* get parameters */ *(param+0) = get_mem(idx+0) ; *(param+1) = get_mem(idx+1) ; *(param+2) = get_mem(idx+2) ; *(param+3) = get_mem(idx+3) ; } void show_params() { SBYTE xmsg[3] ; /* mode */ if ( *(param+0) == 0 ) { rs_puts((UBYTE *)"NORMAL"); } if ( *(param+0) == MD_CRANK ) { rs_puts((UBYTE *)"CRANK"); } if ( *(param+0) == MD_LANE ) { rs_puts((UBYTE *)"LANE"); } crlf(); /* default */ *(xmsg+2) = '\0' ; /* duty ratio */ *(xmsg+0) = asc_hex( *(param+1) / 16 ) ; *(xmsg+1) = asc_hex( *(param+1) % 16 ) ; rs_puts((UBYTE *)"1st = "); rs_puts((UBYTE *)xmsg) ; crlf() ; *(xmsg+0) = asc_hex( *(param+2) / 16 ) ; *(xmsg+1) = asc_hex( *(param+2) % 16 ) ; rs_puts((UBYTE *)"2nd = "); rs_puts((UBYTE *)xmsg) ; crlf() ; /* sensor */ if ( *(param+3) == 0 ) { rs_puts((UBYTE *)"Nothing"); } if ( *(param+3) == 1 ) { rs_puts((UBYTE *)"ALL_WHITE"); } if ( *(param+3) == 2 ) { rs_puts((UBYTE *)"LEFT_WHITE"); } if ( *(param+3) == 3 ) { rs_puts((UBYTE *)"RIGHT_WHITE"); } crlf(); } void delay_ms(UWORD x) { ULONG xlast ; xlast = tickcount + x ; while ( tickcount < xlast ) ; } /* Timer1 interrupt */ ISR(TIMER1_COMPA_vect) { /* increment */ tickcount++ ; }

目次

inserted by FC2 system