目次

システム拡張

 タイマー割込みと受信割込みを利用し、PLCを実現する
 C言語のコードを開発しました。

 このPLCは、最低限の動作しかできません。
 最近のPLCには、ほぼ標準で備わっている次の機能が
 ありません。

 シミュレータでは、これらの機能は実現できています。
 マイコンのファームウエアにも、これらの機能を組込み
 ます。


RTOS(Real Time Operating System)利用

 これまでのファームウエアは、タイマー割込みと受信割込みで  PLCの機能を実現してきました。  新たに機能を付加するには、ソースコードをすべて理解する  必要があります。それは、時間もかかり、面倒な作業です。  RTOS(Real Time Operating System)のUSO(Unvoiced Shadow Operating system)  を利用し、機能追加、削減が簡単にできるようにします。  必要な機能を考え、タスクに分割してみます。  これらの6タスクで、PLCの機能は実現できます。  どこで機能拡張を担当するのかを検討していくと、  次のようになります。  タスク3は、入力と入力メモリ間の転送処理を担当します。  このタスクに、入力メモリの内容表示の機能を追加すると  機能拡張ができます。  タスク4は、スキャン処理を担当しています。  スキャン処理を全ラインで実現するのではなく、1ライン  ごとにステップ動作させるようにすれば、機能拡張できます。  タスク5は、出力と出力メモリ間の転送処理を担当します。  このタスクに、出力メモリの内容表示の機能を追加すると  機能拡張ができます。  タスクに分割すると、このように機能拡張が簡単になります。  通信処理で利用するコマンドを考えます。  これまでに、2つのコマンドを定義して使っています。  付け加えるコマンドを考えます。  入力と入力メモリの内容を表示するように指定する  コマンドを考えます。入力の内容を表示するか否か  を指定するコマンドをIとします。   I1{enter}で、入力と入力メモリの内容表示開始   I0{enter}で、入力と入力メモリの内容表示停止  ステップ動作するかどうかを指定するコマンドを考えます。  このコマンドをPとします。   P1{enter}で、ステップ動作指定   P0{enter}で、ステップ動作停止  ステップ動作の場合は、1行ごとにラダー情報を実現  するので、実行する行の番号を増やすコマンドが必要  になります。  このコマンドをNとします。   N{enter}で、実行ラダー行の番号を+1する  出力と出力メモリの内容を表示するように指定する  コマンドを考えます。出力の内容を表示するか否か  を指定するコマンドをOとします。   O1{enter}で、出力と出力メモリの内容表示開始   O0{enter}で、出力と出力メモリの内容表示停止  コマンドをまとめます。  各タスクを定義します。  通信処理(タスク0)   コマンドをひとつ、ひとつ実装していきます。   ファームウエアとして定義した内容があるので   それを参考にしながら、動作を記述していきます。 if ( mode == IDLE ) { if ( SFLAG == ON ) { /* clear flag */ SFLAG = OFF ; /* get command */ cmd = *(rbuf+0) ; /* set circuit infomation */ if ( cmd == 'S' ) { /* get address */ cadr = get_ad(OFF) ; /* get data */ cdat = get_ad(ON) ; /* save */ put_dat_eeprom( cadr , cdat ); } /* get circuit infomation */ if ( cmd == 'L' ) { *(xdat+2) = 0 ; for ( rom_address = 0 ; rom_address < 512 ; rom_address++ ) { tmp = read_eeprom( rom_address ) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } } } } 「Sコマンド EEPROMアドレスを指定し、16ビットデータ設定」は   タスク1に処理をまとめたので、このコマンドであれば、タスク1   をシステムコールを利用して、SUSPENDからREADYにします。   一応、必要な情報は、ここで取得しておきます。 if ( cmd == 'S' ) { /* get address */ cadr = get_ad(OFF) ; /* get data */ cdat = get_ad(ON) ; /* wake up */ rsm_tsk( TSK_ID1 ) ; } 「Lコマンド EEPROMから全ラダー情報を出力」はタスク2   に処理をまとめたので、このコマンドであれば、タスク2を   システムコールを利用して、SUSPENDからREADYにします。 if ( cmd == 'L' ) { rsm_tsk( TSK_ID2 ) ; } 「Iコマンド 入力と入力メモリの内容表示指定」は   タスク3が処理するとしたので、フラグを利用して   表示するか否かを指定します。 if ( cmd == 'I' ) { IFLAG = OFF ; if ( *(rbuf+1) == '1' ) { IFLAG = ON ; } } 「Pコマンド ステップ動作指定」は、タスク4が処理する   としたので、フラグを利用して動作を指定します。   フラグをセットした場合に、ラダー行を指す変数pcntを用意   して0クリアします。 if ( cmd == 'P' ) { PFLAG = OFF ; if ( *(rbuf+1) == '1' ) { PFLAG = ON ; pcnt = 0 ; } } 「Nコマンド 処理対象の行番号を増やす」は、実際の動作を   タスク4が処理するとしたので、変数pcntの値を+2。   EEPROMは、1バイトごとにアドレスがついているので、ラダー   の1行が16ビットなので+2とします。 if ( cmd == 'N' ) { pcnt += 2 ; } 「Oコマンド 出力と出力メモリの内容表示指定」は、   実際の動作をタスク5が処理するとしたので、フラグ   を利用して動作指定します。 if ( cmd == 'O' ) { OFLAG = OFF ; if ( *(rbuf+1) == '1' ) { OFLAG = ON ; } } 全コマンドの処理を決めたので、タスクとして定義します。 void tsk0_proc(void) { volatile UBYTE cmd ; /* check flag */ if ( SFLAG == OFF ) return ; /* clear flag */ SFLAG = OFF ; /* get command */ cmd = *(rbuf+0) ; /* judge */ if ( cmd == 'S' ) { /* get address */ cadr = get_ad(OFF) ; /* get data */ cdat = get_ad(ON) ; /* wake up */ rsm_tsk( TSK_ID1 ) ; } if ( cmd == 'L' ) { rsm_tsk( TSK_ID2 ) ; } if ( cmd == 'I' ) { IFLAG = OFF ; if ( *(rbuf+1) == '1' ) { IFLAG = ON ; } } if ( cmd == 'P' ) { PFLAG = OFF ; if ( *(rbuf+1) == '1' ) { PFLAG = ON ; pcnt = 0 ; } } if ( cmd == 'N' ) { pcnt += 2 ; } if ( cmd == 'O' ) { OFLAG = OFF ; if ( *(rbuf+1) == '1' ) { OFLAG = ON ; } } }  EEPROMにデータ設定(タスク1)   このタスクでは、EEPROMにデータを保存します。   必要な情報は、タスク0が設定してあるので、それらを   利用して、データ保存します。   一度処理すると、次にREADYにされるまで、システムコール   を利用して、自分自身でSUSPENDにします。   SUSPENDにします。 void tsk1_proc(void) { /* save */ put_dat_eeprom( cadr , cdat ); /* sleep */ slp_tsk(); }  EEPROMの内容表示(タスク2)   EEPROMには、情報が格納されているとして内容を   すべて転送します。一度処理すると、次にREADYに されるまで、システムコールを利用して、自分自身 でSUSPENDにします。 void tsk2_proc(void) { UBYTE tmp; UBYTE xdat[3]; /* set delimiter */ *(xdat+2) = 0 ; for ( rom_address = 0 ; rom_address < 512 ; rom_address++ ) { tmp = read_eeprom( rom_address ) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } /* sleep */ slp_tsk(); }  入力からデータを取得し、入力メモリに展開(タスク3)   ファームウエアとして定義した内容があるので   それを基にして、動作を付加します。 void get_input_information(void) { /* send latch trigger */ PORTB |= (1 << ITRG); PORTB &= ~(1 << ITRG); /* enable nOEA */ PORTB &= ~(1 << OEA); /* get lower data */ *(memory+0) = PINA ; /* disable nOEA */ PORTB |= (1 << OEA); /* enable nOEB */ PORTB &= ~(1 << OEB); /* get upper data */ *(memory+1) = PINA ; /* disable nOEB */ PORTB |= (1 << OEB); }   フラグがセットされていれば、変数memoryの内容を通信回線に出力します。 void tsk3_proc(void) { UBYTE xdat[3]; UBYTE tmp ; /* send latch trigger */ PORTB |= (1 << ITRG); PORTB &= ~(1 << ITRG); /* enable nOEA */ PORTB &= ~(1 << OEA); /* get lower data */ *(memory+0) = PINA ; /* disable nOEA */ PORTB |= (1 << OEA); /* enable nOEB */ PORTB &= ~(1 << OEB); /* get upper data */ *(memory+1) = PINA ; /* disable nOEB */ PORTB |= (1 << OEB); /* show input memory */ if ( IFLAG == ON ) { *(xdat+2) = 0 ; tmp = *(memory+0) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); tmp = *(memory+1) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } }  スキャン処理(タスク4)   スキャン処理は、2つのモードを考えなければなりません。   ステップ実行と一気に実行するのどちらかになります。   ステップ実行するか否かは、フラグPFLAGで判断します。 void tsk4_proc(void) { if ( PFLAG == ON ) { } else { } }   ステップ動作を実行する関数を定義して、その関数を   どう呼び出すのかを変えます。ステップ動作の関数を   定義します。 void doStep(UWORD radr) { /* get circuit infomation from EEPROM */ operand = get_circuit_infomation( radr ); /* get operational code */ opcode = (UBYTE)(operand >> 12); operand &= 0x0fff ; q = ((operand & 0xff) >> 3); r = ((operand & 0xff) & 0x07); /* END instruction */ if ( opcode == OP_END ) return ; /* LD LDN instruction */ if ( opcode == OP_LD || opcode == OP_LDN ) { push( reg ); reg = *(memory+q); reg >>= r; reg &= 1 ; /* inverse */ if ( opcode == OP_LDN ) { reg ^= 1 ; } } /* OP_AND OP_ANDN OP_OR OP_ORN instruction */ if ( opcode == OP_AND || opcode == OP_ANDN || opcode == OP_OR || opcode == OP_ORN ) { regx = *(memory+q); regx >>= r; regx &= 1; /* inverse */ if ( opcode == OP_ANDN || opcode == OP_ORN ) { regx ^= 1 ; } /* AND ANDN instruction */ if ( opcode == OP_AND || opcode == OP_ANDN ) { reg &= regx ; } /* OR ORN instruction */ if ( opcode == OP_OR || opcode == OP_ORN ) { reg |= regx ; } } /* OP_ANDB OP_ORB instruction */ if ( opcode == OP_ANDB || opcode == OP_ORB ) { regx = pull(); /* block AND */ if ( opcode == OP_ANDB ) { reg &= regx ; } /* block OR */ if ( opcode == OP_ORB ) { reg |= regx ; } } /* OP_OUT instruction */ if ( opcode == OP_OUT ) { /* shift bit data */ reg <<= r ; /* clear target bit */ *(memory+q) ^= ~(1 << r); /* store target bit */ *(memory+q) |= reg ; } } }   ステップ動作では、関数doStepに変数pcntを渡します。 void tsk4_proc(void) { if ( PFLAG == ON ) { doStep(pcnt); } else { } }   ステップ動作でなければ、変数iを使い、EEPROMに   格納されている内容をすべて実行します。 void tsk4_proc(void) { UWORD i; if ( PFLAG == ON ) { doStep(pcnt); } else { for ( i = 0 ; i < 512 ; i += 2 ) { doStep(i); } } }  出力メモリから、出力へデータ転送(タスク5)   ファームウエアとして定義した内容があるので   それを基にして、動作を付加します。 void update_output(void) { /* output lower data */ PORTC = *(memory+2) ; /* send latch pulse */ PORTB |= (1 << OTRGA) ; PORTB &= ~(1 << OTRGA) ; /* output upper data */ PORTC = *(memory+3) ; /* latch upper data */ PORTB |= (1 << OTRGB) ; PORTB &= ~(1 << OTRGB) ; }   フラグがセットされていれば、変数memoryの内容を通信回線に出力します。 void tsk5_proc(void) { UBYTE xdat[3]; UBYTE tmp ; /* output lower data */ PORTC = *(memory+2) ; /* send latch pulse */ PORTB |= (1 << OTRGA) ; PORTB &= ~(1 << OTRGA) ; /* output upper data */ PORTC = *(memory+3) ; /* latch upper data */ PORTB |= (1 << OTRGB) ; PORTB &= ~(1 << OTRGB) ; /* show output memory */ if ( OFLAG == ON ) { *(xdat+2) = 0 ; tmp = *(memory+2) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); tmp = *(memory+3) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } }

タスクの初期状態指定

 RTOSでは、タスクの初期状態を決めておかないと  すべてのタスクが一度に動き出します。  EEPROMに関連するタスクをSUSPENDにしておき  コマンドが与えられたときにだけ、動作する  ように設定します。  状態設定は、システムコールを利用して以下のようにします。 sta_tsk(TSK_ID0,TTS_READY); sta_tsk(TSK_ID1,TTS_SUSPEND); sta_tsk(TSK_ID2,TTS_SUSPEND); sta_tsk(TSK_ID3,TTS_READY); sta_tsk(TSK_ID4,TTS_READY); sta_tsk(TSK_ID5,TTS_READY);

全ソースコード

 RTOSのUSOを利用したPLCのCソースコードを次に示します。  システムクロック、I/O部分を変更すると、AVRではないマイ  コンに移植可能です。 #include <avr/io.h> #include <avr/io8535.h> #include <avr/interrupt.h> #define TSK_ID_MAX 6 #define TSK_ID0 0 #define TSK_ID1 1 #define TSK_ID2 2 #define TSK_ID3 3 #define TSK_ID4 4 #define TSK_ID5 5 typedef unsigned char UBYTE ; typedef unsigned short UWORD ; typedef signed char SBYTE ; typedef signed short SWORD ; typedef struct { void (*tsk)(void); UWORD wcount ; } TCBP ; typedef union { struct { unsigned char B0:1; unsigned char B1:1; unsigned char B2:1; unsigned char B3:1; unsigned char B4:1; unsigned char B5:1; unsigned char B6:1; unsigned char B7:1; } BIT ; unsigned char DR ; } FLAGSP ; volatile FLAGSP x_flags ; #define SFLAG x_flags.BIT.B0 #define IFLAG x_flags.BIT.B1 #define PFLAG x_flags.BIT.B2 #define NFLAG x_flags.BIT.B3 #define OFLAG x_flags.BIT.B4 #define MFLAG x_flags.BIT.B4 #define BUFSIZE 10 volatile UBYTE rbuf[BUFSIZE] ; volatile UBYTE rindex; UBYTE asc_cha[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} ; #define OFF 0 #define ON 1 #define IDLE 0 #define RUN IDLE+1 #define LED_OFF (PORTD |= 0x10) #define LED_ON (PORTD ^= 0xef) #define LOWER_LATCH 1 #define UPPER_LATCH 2 #define MASKFF 0xff #define MASK0F 0x0f volatile UBYTE msft ; volatile UBYTE memory[32] ; volatile UBYTE mshift ; volatile UWORD cadr ; volatile UWORD cdat ; volatile UBYTE stksft ; volatile UBYTE opcode ; volatile UBYTE operand; volatile UBYTE q ; volatile UBYTE r ; volatile UBYTE cmd ; volatile UWORD rom_address ; volatile UBYTE reg ; volatile UBYTE regx ; volatile UWORD pcnt ; #define TTS_SUSPEND 0 #define TTS_WAIT TTS_SUSPEND+1 #define TTS_READY TTS_SUSPEND+2 #define NO 0 #define YES 1 UBYTE ready ; UBYTE suspend; UBYTE vldtsk ; UBYTE run_tsk; TCBP tcb[TSK_ID_MAX]; /*------------------------*/ /* task function protoype */ /*------------------------*/ void tsk0_proc(void); void tsk1_proc(void); void tsk2_proc(void); void tsk3_proc(void); void tsk4_proc(void); void tsk5_proc(void); /*-----------------------*/ /* system call prototype */ /*-----------------------*/ void init_os(void); void cre_tsk(UBYTE tid,void (*tsk)(void)); void sta_tsk(UBYTE tid,UBYTE sta); void rsm_tsk(UBYTE tid); void sus_tsk(UBYTE tid); void slp_tsk(void); void wai_tsk(UWORD x); UBYTE is_tsk_ready(UBYTE tid); /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); #define ITRG 0 #define OEA 1 #define OEB 2 #define OEO 3 #define OTRGA 4 #define OTRGB 5 #define OP_END 0 #define OP_OUT 1 #define OP_LD 2 #define OP_LDN 3 #define OP_AND 4 #define OP_ANDN 5 #define OP_OR 6 #define OP_ORN 7 #define OP_ANDB 8 #define OP_ORB 9 void rs_putchar(UBYTE x); void rs_puts(UBYTE *x); void write_eeprom(UWORD adr,UBYTE dat); UBYTE read_eeprom(UWORD adr); void push(UBYTE x); UBYTE pull(void); UWORD get_circuit_infomation(UWORD x); void doStep(UWORD radr); void doScan(UWORD radr); UBYTE get_hex(UBYTE x); UWORD get_ad(UBYTE onoff); void put_dat_eeprom(UWORD adr,UWORD dat); /*------*/ /* main */ /*------*/ int main(void) { TCBP pcur_tsk ; /* disable interrupt */ cli(); /* initialize monitor */ init_os(); cre_tsk(TSK_ID0,tsk0_proc); cre_tsk(TSK_ID1,tsk1_proc); cre_tsk(TSK_ID2,tsk2_proc); cre_tsk(TSK_ID3,tsk3_proc); cre_tsk(TSK_ID4,tsk4_proc); cre_tsk(TSK_ID5,tsk5_proc); sta_tsk(TSK_ID0,TTS_READY); sta_tsk(TSK_ID1,TTS_SUSPEND); sta_tsk(TSK_ID2,TTS_SUSPEND); sta_tsk(TSK_ID3,TTS_READY); sta_tsk(TSK_ID4,TTS_READY); sta_tsk(TSK_ID5,TTS_READY); user_initialize(); /* enable interrupt */ sei(); /* loop */ run_tsk = TSK_ID0 ; while ( 1 ) { pcur_tsk = tcb[run_tsk] ; if ( is_tsk_ready( run_tsk ) == YES ) { (*(pcur_tsk.tsk))(); } run_tsk++; if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; } } /* dummy */ return 0 ; } /*----------------*/ /* task functions */ /*----------------*/ void tsk0_proc(void) { /* mode switch handling */ LED_OFF ; if ( MFLAG == ON ) { LED_ON ; } /* check flag */ if ( SFLAG == OFF ) return ; /* clear flag */ SFLAG = OFF ; /* get command */ cmd = *(rbuf+0) ; /* judge */ if ( cmd == 'S' ) { /* get address */ cadr = get_ad(OFF) ; /* get data */ cdat = get_ad(ON) ; /* wake up */ rsm_tsk( TSK_ID1 ) ; } if ( cmd == 'L' ) { rsm_tsk( TSK_ID2 ) ; } if ( cmd == 'I' ) { IFLAG = OFF ; if ( *(rbuf+1) == '1' ) { IFLAG = ON ; } } if ( cmd == 'P' ) { PFLAG = OFF ; if ( *(rbuf+1) == '1' ) { PFLAG = ON ; pcnt = 0 ; } } if ( cmd == 'N' ) { pcnt += 2 ; } if ( cmd == 'O' ) { OFLAG = OFF ; if ( *(rbuf+1) == '1' ) { OFLAG = ON ; } } } void tsk1_proc(void) { /* save */ put_dat_eeprom( cadr , cdat ); /* sleep */ slp_tsk(); } void tsk2_proc(void) { UBYTE tmp ; UBYTE xdat[3]; /* set delimiter */ *(xdat+2) = 0 ; for ( rom_address = 0 ; rom_address < 512 ; rom_address++ ) { tmp = read_eeprom( rom_address ) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } /* sleep */ slp_tsk(); } void tsk3_proc(void) { UBYTE xdat[3]; UBYTE tmp ; /* send latch trigger */ PORTB |= (1 << ITRG); PORTB &= ~(1 << ITRG); /* enable nOEA */ PORTB &= ~(1 << OEA); /* get lower data */ *(memory+0) = PINA ; /* disable nOEA */ PORTB |= (1 << OEA); /* enable nOEB */ PORTB &= ~(1 << OEB); /* get upper data */ *(memory+1) = PINA ; /* disable nOEB */ PORTB |= (1 << OEB); /* show input memory */ if ( IFLAG == ON ) { *(xdat+2) = 0 ; tmp = *(memory+0) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); tmp = *(memory+1) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } } void tsk4_proc(void) { UWORD i; if ( PFLAG == ON ) { doStep(pcnt); } else { for ( i = 0 ; i < 512 ; i += 2 ) { doStep(i); } } } void tsk5_proc(void) { UBYTE xdat[3]; UBYTE tmp ; /* output lower data */ PORTC = *(memory+2) ; /* send latch pulse */ PORTB |= (1 << OTRGA) ; PORTB &= ~(1 << OTRGA) ; /* output upper data */ PORTC = *(memory+3) ; /* latch upper data */ PORTB |= (1 << OTRGB) ; PORTB &= ~(1 << OTRGB) ; /* show output memory */ if ( OFLAG == ON ) { *(xdat+2) = 0 ; tmp = *(memory+2) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); tmp = *(memory+3) ; *(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ]; *(xdat+1) = asc_cha[ tmp & MASK0F ]; rs_puts( xdat ); } } /*------------------*/ /* system call body */ /*------------------*/ void init_os(void) { ready = vldtsk = 0 ; } void cre_tsk(UBYTE tid,void (*tsk)(void)) { if ( tid >= TSK_ID_MAX ) return ; vldtsk |= (1 << tid) ; tcb[tid].tsk = tsk; tcb[tid].wcount = 0; } void sta_tsk(UBYTE tid,UBYTE sta) { if ( tid >= TSK_ID_MAX ) return ; if ( sta == TTS_READY ) { ready |= (1 << tid); suspend &= ~(1 << tid); } if ( sta == TTS_WAIT ) { ready &= ~(1 << tid); suspend &= ~(1 << tid); } if ( sta == TTS_SUSPEND ) { ready &= ~(1 << tid); suspend |= (1 << tid); } } void rsm_tsk(UBYTE tid) { if ( tid >= TSK_ID_MAX ) return ; ready |= (1 << tid); suspend &= ~(1 << tid); } void sus_tsk(UBYTE tid) { if ( tid >= TSK_ID_MAX ) return ; ready &= ~(1 << tid); suspend |= (1 << tid); } void slp_tsk(void) { sus_tsk(run_tsk); } void wai_tsk(UWORD x) { ready &= ~(1 << run_tsk); suspend &= ~(1 << run_tsk); tcb[run_tsk].wcount = x ; } UBYTE is_tsk_ready(UBYTE tid) { return( (ready >> tid) & 1 ) ; } /*-----------------------------*/ /* timer handler */ /* call from timer interrupt */ /*-----------------------------*/ void timer_handler(void) { UBYTE tmp; UBYTE i ; tmp = (ready ^ vldtsk) ^ suspend ; for ( i = 0 ; i <= TSK_ID_MAX ; i++ ) { if ( tmp & 1 ) { tcb[i].wcount-- ; if ( tcb[i].wcount == 0 ) { rsm_tsk(i); } } tmp >>= 1 ; } } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ #define FOSC 8000000 #define BAUD 38400 #define MYUBRR (FOSC/16/BAUD)-1 void user_initialize(void) { volatile UBYTE i ; /* PORT A */ DDRA = 0b00000000 ; /* iiiiiiii */ PORTA = 0b00000000 ; /* 00000000 */ /* PORT B */ DDRB = 0b11111111 ; /* oooooooo */ PORTB = 0b00000000 ; /* 00000000 */ /* PORT C */ DDRC = 0b11111111 ; /* oooooooo */ PORTC = 0b00000000 ; /* 00000000 */ /* PORT D */ DDRD = 0b11110010 ; /* ooooiioi */ PORTD = 0b00010000 ; /* 00010000 */ /* initialize registers */ x_flags.DR = 0 ; for ( i = 0 ; i < 32 ; i++ ) { *(memory+i) = 0 ; } msft = 0 ; /* initialize serial */ { /* clear index */ rindex = 0 ; /* clear buffer */ *(rbuf+0) = 0 ; /* set Baud Rate Registers */ UBRR = MYUBRR ; /* Enable receive interrupt , receive module and transmit module */ UCR = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE); } /* initialize timer1 */ { /* clear timer/counter */ TCNT1 = 0 ; /* set counter */ OCR1A = 9999 ; /* Control Register 1 B */ TCCR1B = (1 << CS10) ; } /* Enable interrupt */ TIMSK |= (1 << OCIE1A) | (1 << TOIE0); } /* UART receive interrupt */ ISR(SIG_UART_RECV) { UBYTE ch ; /* get 1 charactoer */ ch = UDR ; /* store */ *(rbuf+rindex) = ch ; rindex++ ; /* judge */ if ( ch == '\r' ) { SFLAG = ON ; rindex = 0 ; } } /* timer1 interrupt */ ISR(SIG_OUTPUT_COMPARE1A) { /* clear timer/counter */ TCNT1 = 0 ; /* get switch data */ msft <<= 1 ; msft &= 0xfe ; if ( PIND & 0x20 ) { msft |= 1 ; } if ( msft == MASKFF ) { MFLAG = ON ; } else { MFLAG = OFF ; } /* handling */ timer_handler(); } void rs_putchar(UBYTE x) { while ( !(USR & (1 << UDRE)) ) {} UDR = x ; } void rs_puts(UBYTE *x) { while ( *x != '\0' ) { rs_putchar( *x ) ; x++ ; } rs_putchar('\r'); rs_putchar('\n'); } void write_eeprom(UWORD adr,UBYTE dat) { /* wait */ while ( EECR & (1 << EEWE) ) ; /* set address */ EEARH = (UBYTE)((adr >> 8) & MASKFF); EEARL = (UBYTE)(adr & MASKFF); /* set data */ EEDR = dat ; /* enable Master Write Enable */ EECR |= (1 << EEMWE) ; /* enable Write Enable */ EECR |= (1 << EEWE); } UBYTE read_eeprom(UWORD adr) { /* wait */ while ( EECR & (1 << EEWE) ) ; /* set address */ EEARH = (UBYTE)((adr >> 8) & MASKFF); EEARL = (UBYTE)(adr & MASKFF); /* enable Read Enable */ EECR |= (1 << EERE) ; return EEDR ; } void push(UBYTE x) { stksft <<= 1 ; stksft &= 0xfe ; stksft |= x ; } UBYTE pull(void) { volatile UBYTE tmp ; tmp = stksft ; stksft >>= 1 ; return(tmp & 1); } UWORD get_circuit_infomation(UWORD x) { volatile UBYTE dh; volatile UBYTE dl; volatile UWORD result ; /* get upper byte */ dh = read_eeprom( x ) ; /* get lower byte */ dl = read_eeprom( x+1 ) ; /* concatenate */ result = dh ; result <<= 8 ; result |= dl ; return result ; } void doStep(UWORD radr) { /* get circuit infomation from EEPROM */ operand = get_circuit_infomation( radr ); /* get operational code */ opcode = (UBYTE)(operand >> 12); operand &= 0x0fff ; q = ((operand & 0xff) >> 3); r = ((operand & 0xff) & 0x07); /* END instruction */ if ( opcode == OP_END ) return ; /* LD LDN instruction */ if ( opcode == OP_LD || opcode == OP_LDN ) { push( reg ); reg = *(memory+q); reg >>= r; reg &= 1 ; /* inverse */ if ( opcode == OP_LDN ) { reg ^= 1 ; } } /* OP_AND OP_ANDN OP_OR OP_ORN instruction */ if ( opcode == OP_AND || opcode == OP_ANDN || opcode == OP_OR || opcode == OP_ORN ) { regx = *(memory+q); regx >>= r; regx &= 1; /* inverse */ if ( opcode == OP_ANDN || opcode == OP_ORN ) { regx ^= 1 ; } /* AND ANDN instruction */ if ( opcode == OP_AND || opcode == OP_ANDN ) { reg &= regx ; } /* OR ORN instruction */ if ( opcode == OP_OR || opcode == OP_ORN ) { reg |= regx ; } } /* OP_ANDB OP_ORB instruction */ if ( opcode == OP_ANDB || opcode == OP_ORB ) { regx = pull(); /* block AND */ if ( opcode == OP_ANDB ) { reg &= regx ; } /* block OR */ if ( opcode == OP_ORB ) { reg |= regx ; } } /* OP_OUT instruction */ if ( opcode == OP_OUT ) { /* shift bit data */ reg <<= r ; /* clear target bit */ *(memory+q) ^= ~(1 << r); /* store target bit */ *(memory+q) |= reg ; } } UBYTE get_hex(UBYTE x) { volatile UBYTE result ; /* default */ result = 0 ; /* select */ 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 ; } UWORD get_ad(UBYTE onoff) { volatile UWORD result ; /* get first byte */ result = get_hex( *(rbuf+1) ); /* get second byte */ result = (result << 4) | get_hex( *(rbuf+2) ); /* get third byte */ result = (result << 4) | get_hex( *(rbuf+3) ); /* get fourth byte */ result = (result << 4) | get_hex( *(rbuf+4) ); /* compute data */ if ( onoff == ON ) { /* get first byte */ result = get_hex( *(rbuf+5) ); /* get second byte */ result = (result << 4) | get_hex( *(rbuf+6) ); /* get third byte */ result = (result << 4) | get_hex( *(rbuf+7) ); /* get fourth byte */ result = (result << 4) | get_hex( *(rbuf+8) ); } /* */ return result ; } void put_dat_eeprom(UWORD adr,UWORD dat) { volatile UBYTE dhl ; /* get upper data */ dhl = (UBYTE)((dat >> 8) & MASKFF) ; /* store */ write_eeprom( adr , dhl ); /* get lower data */ dhl = (UBYTE)(dat & MASKFF) ; /* store */ write_eeprom( adr+1 , dhl ); }
目次

inserted by FC2 system