目次
前
次
モード別走行テスト
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から
パラメータを入力する処理にすればよさそうです。
シーケンスは、以下。
- パワーオン
- スイッチ状態取得
- スイッチ状態により、EEPROMからパラメータ取得
- レジスタにパラメータ設定
- パラメータごとの処理に分岐
スイッチは、2ビットのDIPスイッチを利用します。
2ビットのDIPスイッチなので、組合せは4通りあり
コードで処理指定します。
- 00 EEPROMからパラメータ取得なし
- 01 CRANKテスト(EEPROMからパラメータ取得あり)
- 10 LANEテスト(EEPROMからパラメータ取得あり)
- 11 NORMALテスト(EEPROMからパラメータ取得あり)
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++ ;
}
目次
前
次