目次
前
次
プロセッサファームウエア
複数のプロセッサを利用するので、プロセッサごとに
ファームウエアを作成します。
ACTUATOR
ACTUATORは、BRAINからの指示でPWM波形を生成します。
ジェネラルフローは、次のように定義します。
I/O初期化では、リストの項目を指定します。
- ポートB初期設定
- ポートD初期設定
- 内蔵通信モジュール初期化
- 内蔵通信タイマーモジュール初期化
- 内部変数初期値設定
BRAINから送られる、パラメータを含んだコマンドを処理する目的で
ループの中にコマンドインタプリタを含ませます。
コマンドインタプリタを起動するため、フラグ(SFLAG)を使います。
フラグがセットされたなら、受信バッファ中のコマンドとパラメータ
を処理します。
受信割込みは、バッファへ受信文字を保存し、デリミタに
より、フラグをセットします。デリミタは\rとします。
タイマー割込みでは、カウンタと内部変数値を比較し
出力論理値を確定します。
周期動作のために、カウンタを更新し、指定値でゼロに戻します。
カウンタをゼロにすると同時に、DUTY比用カウンタを更新します。
ACTUATORソースコード
#include <avr/io.h>
#include <avr/iotn2313.h>
#include <avr/interrupt.h>
#define FOSC 4000000
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD)-1
#define OFF 0
#define ON OFF+1
#define BUFSIZE 8
#define RMOTOR 0
#define LMOTOR 1
#define SERVO 2
#define LED 3
#define PMAX 200
#define SERVO_MID 15
#define LED_MAX 180
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
volatile UBYTE sflag ;
volatile UBYTE lflag ;
volatile UBYTE sbuf[BUFSIZE] ;
volatile UBYTE sindex;
volatile UBYTE bport;
volatile UBYTE pcnt;
volatile UBYTE duty[5] ;
volatile UBYTE dutyx[4] ;
volatile UBYTE cmd ;
volatile UBYTE pduty;
volatile UBYTE chx ;
volatile UBYTE outv[2] ;
volatile UBYTE lcnt ;
volatile UBYTE msg_f[] = "Hi !" ;
volatile UBYTE msg_h[] = "?:help" ;
volatile UBYTE msg_d[] = "D:set ratio" ;
volatile UBYTE msg_s[] = "S:show ratio" ;
#define NO 0
#define YES NO+1
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void user_initialize(void);
void command_interpret(void);
void rs_putchar(UBYTE x);
void rs_crlf(void);
void rs_putstr(UBYTE *x);
UBYTE get_decimal(UBYTE x);
/*------*/
/* main */
/*------*/
int main(void)
{
/* disable interrupt */
cli();
/* initialize port and variables */
user_initialize();
/* enable interrupt */
sei();
/* rs_putstr((UBYTE *)msg_f ); */
/* endless loop */
while ( ON ) {
/* SCI handling */
if ( sflag ) {
sflag = OFF ;
/* serial communication process */
command_interpret();
}
/* monitor led */
if ( lflag ) {
lflag = OFF ;
lcnt++ ;
PORTD |= (1 << 6) ;
if ( lcnt & 1 ) { PORTD &= ~(1 << 6) ; }
}
}
/* dummy */
return 0 ;
}
#/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
UWORD tmp ;
/* PORT B */
PORTB = 0b00000000 ; /* 00000000 */
DDRB = 0b11111111 ; /* oooooooo */
/* PORT D */
PORTD = 0b00000000 ; /* 00000000 */
DDRD = 0b11111110 ; /* oooooooi */
/* */
sflag = OFF ;
/* initialize serial */
{
/* set Baud Rate Registers */
tmp = MYUBRR ;
UBRRH = (UBYTE)(tmp >> 8) ;
UBRRL = (UBYTE)(tmp & MASKFF) ;
/* Enable receive interrupt , receive module and transmit module */
UCSRB = (1 << RXCIE) | (1 << TXEN) | (1 << RXEN) ;
/* 8 bits , 1 stop , non parity */
UCSRC = (3 << UCSZ0);
}
/* clear index */
sindex = 0 ;
/* */
lflag = OFF ;
/* initialize timer1 */
{
/* clear counter */
TCNT1 = 0 ;
/* initialize counter */
OCR1A = 49;
OCR1B = 99;
/* set prescaler (/8) */
/* select clock and prescaler (generate 10kHz) */
TCCR1B = (1 << WGM12) | (1 << CS11) ;
/* Enable interrupt */
TIMSK = (1 << OCIE1A) ;
}
/* */
pcnt = 0 ;
lcnt = 0 ;
/* initialize duty */
*(duty+RMOTOR) = 0 ;
*(duty+LMOTOR) = 0 ;
*(duty+SERVO) = SERVO_MID ;
*(duty+LED) = LED_MAX;
/* initialize duty (interrupt) */
*(dutyx+RMOTOR) = 0 ;
*(dutyx+LMOTOR) = 0 ;
*(dutyx+SERVO) = SERVO_MID ;
*(dutyx+LED) = LED_MAX;
}
/* command interpriter */
void command_interpret(void)
{
UBYTE i ;
/* get command character */
cmd = *(sbuf+0) ;
/* set duty */
if ( cmd == 'D' ) {
/* get duty */
*(duty+4) = get_decimal( *(sbuf+1) );
*(duty+4) *= 10 ;
*(duty+4) += get_decimal( *(sbuf+2) );
/* get channel number */
chx = get_decimal( *(sbuf+3) );
/* judge */
if ( chx != SERVO ) { *(duty+4) <<= 1 ; }
/* store */
*(duty+chx) = *(duty+4) ;
}
/* show duty ratio */
if ( cmd == 'S' ) {
for ( i = 0 ; i < 4 ; i++ ) {
/* get duty */
*(duty+4) = *(duty+i) ;
/* ajust */
if ( i != SERVO ) { *(duty+4) >>= 1 ; }
/* generate code */
*(outv+0) = *(duty+4) / 10 + '0' ;
*(outv+1) = *(duty+4) % 10 + '0' ;
/* transfer code */
rs_putchar( *(outv+0) );
rs_putchar( *(outv+1) );
rs_crlf();
}
}
/* help */
if ( cmd == '?' ) {
rs_putstr((UBYTE *)msg_h );
rs_putstr((UBYTE *)msg_d );
rs_putstr((UBYTE *)msg_s );
}
/* new line */
rs_crlf();
}
/* UART receive interrupt */
ISR(USART_RX_vect)
{
volatile UBYTE ch ;
if ( bit_is_clear(UCSRA,FE) ) {
/* get 1 charactoer */
ch = UDR ;
/* store */
*(sbuf+sindex) = ch ;
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sflag = ON ;
sindex = 0 ;
}
}
}
void rs_putchar(UBYTE x)
{
while ( !(UCSRA & (1 << UDRE)) ) ;
UDR = x ;
}
void rs_crlf(void)
{
rs_putchar('\r');
rs_putchar('\n');
}
void rs_putstr(UBYTE *x)
{
/* send charactor one by one */
while ( *x != '\0' ) {
rs_putchar( *x ) ;
/* pointer increment */
x++ ;
}
rs_crlf();
}
/* Timer1 interrupt */
ISR(TIMER1_COMPA_vect)
{
/* initialize */
bport = 0 ;
/* judge */
if ( pcnt <= *(dutyx+RMOTOR) ) { bport |= 1 ; }
if ( pcnt <= *(dutyx+LMOTOR) ) { bport |= 2 ; }
if ( pcnt <= *(dutyx+SERVO) ) { bport |= 4 ; }
if ( pcnt <= *(dutyx+LED) ) { bport |= 8 ; }
/* set */
PORTB = bport ;
/* increment */
pcnt++ ;
if ( pcnt == PMAX ) {
pcnt = 0 ;
/* update */
*(dutyx+RMOTOR) = *(duty+RMOTOR) ;
*(dutyx+LMOTOR) = *(duty+LMOTOR) ;
*(dutyx+SERVO) = *(duty+SERVO) ;
*(dutyx+LED) = *(duty+LED) ;
/* monitor */
lflag = ON ;
}
}
UBYTE get_decimal(UBYTE x)
{
UBYTE result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
return result;
}
ACTUATORテストデバッグ
ACTUATORが指定したパルスを出力しているかをテストします。
OSにWindowsXPを持ったパーソナルコンピュータからTeraTermで
ACTUATORにコマンドを送信します。
送信コマンドとパラメータで、指定チャネルの出力波形が変わる
ので、マルチメータでDUTY比を測定します。
これは、単体テストですが、マルチプロセッサで動作する場合
BRAINからコマンドを与えます。
今回利用したLOGIC CONVERTERは、トランジスタを利用した簡易版
です。回路図は、次のようになります。
NPNトランジスタは、小信号タイプであれば、何でもOKです。
廃品種になった2SC1815、2SC945などの大量購入すると\10にも
満たないトランジスタで充分です。
SENSOR DATA LATCH(SDL)
SENSOR DATA LATCH(SDL)は、SENSORが与える、2つの4ビット値を
結合して8ビットにします。
データ、上下位置指定を与えて、外部割込みで値を入力します。
入力値のビット4、ビット5を右に2ビットシフトし、全体が
4ビットになるように操作します。
SENSOR DATA LATCH(SDL)ソースコード
#include <avr/io.h>
#include <avr/iotn2313.h>
#include <avr/interrupt.h>
#define OFF 0
#define ON OFF+1
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
volatile UBYTE eflag ;
volatile UBYTE dh ;
volatile UBYTE dl ;
volatile UBYTE bport;
#define NO 0
#define YES NO+1
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
/*------*/
/* main */
/*------*/
int main(void)
{
UBYTE tmp ;
/* disable interrupt */
cli();
/* initialize port and variables */
/* PORT B */
DDRB = 0b11111111 ; /* oooooooo */
PORTB = 0b00000000 ; /* 00000000 */
/* PORT D */
DDRD = 0b00000000 ; /* iiiiiiii */
PORTD = 0b00000000 ; /* 00000000 */
/* */
eflag = OFF ;
/* enable INT0 */
MCUCR = (1 << ISC01) ;
/* enable INT0 (global) */
GIMSK = (1 << INT0) ;
/* enable interrupt */
sei();
/* endless loop */
while ( ON ) {
if ( eflag == OFF ) continue ;
eflag = OFF ;
/* get data */
tmp = PIND ;
/* generate code */
dl = ((tmp >> 2) & 12) | (tmp & 3) ;
dh = (dl << 4) & MASKF0 ;
/* judge */
if ( tmp & 8 ) {
bport = (bport & MASK0F) | dh ;
} else {
bport = (bport & MASKF0) | dl ;
}
PORTB = bport ;
}
/* dummy */
return 0 ;
}
/* EXTERNAL */
ISR(INT0_vect)
{
eflag = ON ;
}
SENSOR DATA LATCH(SDL)テストデバッグ
SDLが仕様を満たしているかをテストします。
8ビットのデータをON/OFFできるスイッチボードと8個のLEDがあるLEDボードを
利用します。
スイッチは、SDLの入力と次のように接続します。
- SW7 (nothing)
- SW6 (nothing)
- SW5 Din3
- SW4 Din2
- SW3 SEL
- SW2 LT
- SW1 Din1
- SW0 Din0
スイッチボードとは、10ピンケーブルで接続します。
SW3(SEL)をONかOFFにしてSW2(LT)をクリックします。
スイッチ操作とLEDの点灯で、ファームウエアが仕様通りに
動作しているのかを確認します。
SW3(SEL)=ON
(SW5,SW4,SW1,SW0)=(H,H,H,H)でSW2クリック 上4ビットのLED=(点、点、点、点)
(SW5,SW4,SW1,SW0)=(H,H,H,L)でSW2クリック 上4ビットのLED=(点、点、点、消)
(SW5,SW4,SW1,SW0)=(H,H,L,L)でSW2クリック 上4ビットのLED=(点、点、消、消)
(SW5,SW4,SW1,SW0)=(H,L,L,L)でSW2クリック 上4ビットのLED=(点、消、消、消)
(SW5,SW4,SW1,SW0)=(L,L,L,L)でSW2クリック 上4ビットのLED=(消、消、消、消)
SW3(SEL)=OFF
(SW5,SW4,SW1,SW0)=(H,H,H,H)でSW2クリック 下4ビットのLED=(点、点、点、点)
(SW5,SW4,SW1,SW0)=(H,H,H,L)でSW2クリック 下4ビットのLED=(点、点、点、消)
(SW5,SW4,SW1,SW0)=(H,H,L,L)でSW2クリック 下4ビットのLED=(点、点、消、消)
(SW5,SW4,SW1,SW0)=(H,L,L,L)でSW2クリック 下4ビットのLED=(点、消、消、消)
(SW5,SW4,SW1,SW0)=(L,L,L,L)でSW2クリック 下4ビットのLED=(消、消、消、消)
SENSOR
SENSORには、次の機能を持たせます。
- カメラ制御
- センサーデータ生成
- BRAINとのインタフェース
3機能のうち、カメラ制御、センサーデータ生成は、これまでの章で
説明したので、BRAINとのインタフェースを考えます。
BRAINとSENSORは、SPIとパラレルインタフェースを利用すると
考えましたが、極力配線を減らすため、SPIだけとします。
SPIは、シリアルインタフェースバスなので、通信プロトコルを
決めなければなりません。
今回は、次のように物理仕様を規定しました。
- BRAINをmaster、SENSORをslaveに設定
- 2回の8ビットデータ交換で1アクセスとする
- 8ビットは、最上位ビット(MSB)から転送
- ビット転送速度は、8MHz
- BRAINは7種のコマンドで、データ交換
コマンドは、以下とします。
- SPI_0(0x01) 1ラインセンサーデータ指定
- SPI_1(0x02) 60ラインセンサーデータ指定
- SPI_I(0x03) 付加情報取得
- SPI_C(0x04) カメラ撮影+センサーデータ計算
- SPI_A(0x05) センサーデータインデックス初期化
- SPI_D(0x06) センサーデータ取得(インデックス更新付き)
- SPI_S(0x07) ステータス取得
付加情報は、次の4種とします。
- 60ラインか1ラインのどちらの指定(1:0 0:60)
- センサーデータ中にクランク(1:あり 0:なし)
- センサーデータ中に右レーンチェンジ指定(1:あり 0:なし)
- センサーデータ中に左レーンチェンジ指定(1:あり 0:なし)
ステータスは、カメラ撮影に関連情報とします。
- BUSYかIDLE(1:BUSY 0:IDLE)
- カメラとの通信確立(1:確立済み 0:確立なし)
- カメラの初期化(1:設定 0:未設定)
- スレショールド取得(1:取得済み 0:未取得)
プロトコルを決めたので、ソースコードを記述します。
SENSORソースコード
#include <avr/io.h>
#include <avr/interrupt.h>
#define FOSC 16000000
#define BAUD 57600
#define MYUBRR (FOSC/16/BAUD)-1
#define OFF 0
#define ON OFF+1
#define BUFSIZE 8
#define SPI_0 0x01
#define SPI_1 0x02
#define SPI_I 0x03
#define SPI_C 0x04
#define SPI_A 0x05
#define SPI_D 0x06
#define SPI_S 0x07
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef unsigned long ULONG ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
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 BFLAG x_flags.BIT.B1
#define CFLAG x_flags.BIT.B2
#define ZFLAG x_flags.BIT.B3
#define GFLAG x_flags.BIT.B4
#define DFLAG x_flags.BIT.B7
volatile FLAGSP s_flags ;
#define SBUSY s_flags.BIT.B0
#define SESTABLISH s_flags.BIT.B1
#define SINITIALIZE s_flags.BIT.B2
#define STHRESOLD s_flags.BIT.B3
#define SZFLAG s_flags.BIT.B4
#define SCRANK s_flags.BIT.B5
#define SLANERIGHT s_flags.BIT.B6
#define SLANELEFT s_flags.BIT.B7
#define RING_BSIZE 256
typedef struct {
UBYTE data[RING_BSIZE];
UWORD capacity;
UWORD rdp;
UWORD wrp;
} RINGP ;
volatile RINGP rings;
volatile UBYTE sbuf[BUFSIZE] ;
volatile UBYTE sindex;
volatile UBYTE spicmd ;
volatile UBYTE spicnt ;
#define DAT_MAX 480
#define LINE_MAX 60
volatile UBYTE dummy[12];
volatile UBYTE gdat[DAT_MAX] ;
volatile UBYTE senx[LINE_MAX] ;
volatile UBYTE gindex ;
volatile UBYTE threshold ;
volatile ULONG tickcount ;
#define NO 0
#define YES NO+1
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void user_initialize(void);
void rs_putchar(UBYTE x);
void spi_interpret(void);
UBYTE establish_c328(void);
void send_c328(UBYTE x,UWORD p0,UWORD p1);
void send_sync(void);
void send_ack(UBYTE x);
void send_init(void);
void send_snapshot(void);
void send_get_img(void);
void delay_ms(UBYTE x);
void put_ring(UBYTE x);
UBYTE get_ring(void);
UWORD get_ring_cap(void);
void init_ring(void);
UBYTE init_c328(void);
UBYTE get_c328(void);
UBYTE generate_threshold(void);
UBYTE is_middle(UWORD x);
UBYTE is_edge(UWORD x);
/*------*/
/* main */
/*------*/
int main(void)
{
/* disable interrupt */
cli();
/* initialize port and variables */
user_initialize();
/* enable interrupt */
sei();
/* establish communication bitween c328 and mega328 */
SESTABLISH = establish_c328() ;
/* initialzie c328 (dummy shot) */
SINITIALIZE = init_c328() ;
/* generate threshold (dummy shot) */
STHRESOLD = generate_threshold() ;
/* initialzie c328 */
SINITIALIZE = init_c328() ;
/* generate threshold */
STHRESOLD = generate_threshold() ;
/* endless loop */
while ( ON ) {
/* SPI */
if ( SFLAG == ON ) {
SFLAG = OFF ;
/* serial communication process */
spi_interpret();
}
}
/* dummy */
return 0 ;
}
#/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
UWORD tmp ;
/* PORT B */
PORTB = 0b00000000 ; /* 00000000 */
DDRB = 0b00001011 ; /* iiiioioo */
/* PORT C */
PORTC = 0b00000000 ; /* 00000000 */
DDRC = 0b00111111 ; /* iioooooo */
/* PORT D */
PORTD = 0b00000000 ; /* 00000000 */
DDRD = 0b11111110 ; /* oooooooi */
/* */
x_flags.DR = 0 ;
s_flags.DR = 0 ;
gindex = 0 ;
spicnt = 0 ;
tickcount = 0 ;
/* initialize timer1 */
{
/* clear counter */
TCNT1 = 0 ;
/* set compare value */
OCR1A = 1999 ;
OCR1B = 3200 ;
/* prescaler /8 => 2MHz */
TCCR1B = (1 << WGM12) | (1 << CS11) ;
/* enable compare match */
TIMSK1 = (1 << OCIE1A) ;
}
/* initialize SPI */
{
/* Interrupt , MSB first , SLAVE , fosc/2 = 8MHz */
SPCR = 0b11100000 ;
SPSR = 0b00000000 ;
}
/* clear index */
sindex = 0 ;
/* clear buffer */
*(sbuf+0) = 0 ;
/* initialize serial */
{
/* set Baud Rate Registers */
tmp = MYUBRR ;
UBRR0H = (UBYTE)((tmp >> 8) & MASKFF) ;
UBRR0L = (UBYTE)(tmp & MASKFF) ;
/* Enable receive interrupt , receive module and transmit module */
UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0) ;
/* 8 bits , 1 stop bit , no parity */
UCSR0C = (3 << UCSZ00);
}
/* */
init_ring();
}
/* UART receive interrupt */
ISR(USART_RX_vect)
{
volatile UBYTE ch ;
if ( !(UCSR0B & (1 << FE0)) ) {
/* get 1 charactoer */
ch = UDR0 ;
/* store */
put_ring( ch );
}
}
void rs_putchar(UBYTE x)
{
while ( !(UCSR0A & (1 << UDRE0)) ) {}
UDR0 = x ;
}
/* SPI receive interrupt */
ISR(SPI_STC_vect)
{
/* counter increment */
spicnt++ ;
spicnt &= 1 ;
/* get data */
spicmd = SPDR ;
/* set flag */
SFLAG = ON ;
}
#define SEL_BIT 5
#define LT_BIT 4
#define FLG_BIT 3
#define KEEP_INDEX 30
#define MASK0F 0x0f
void spi_interpret(void)
{
/* judge */
if ( spicnt == 0 ) return ;
/* set mode */
if ( spicmd == SPI_0 ) {
ZFLAG = ON ;
SZFLAG = ZFLAG ;
}
if ( spicmd == SPI_1 ) {
ZFLAG = OFF ;
SZFLAG = ZFLAG ;
}
/* get additional information */
if ( spicmd == SPI_I ) { SPDR = (s_flags.DR >> 4) & MASK0F ; }
/* get image */
if ( spicmd == SPI_C ) { GFLAG = get_c328(); }
/* clear address */
if ( spicmd == SPI_A ) { gindex = 0 ; }
/* show data */
if ( spicmd == SPI_D ) {
/* concrete index */
if ( ZFLAG ) { gindex = KEEP_INDEX ; }
/* get data */
SPDR = *(senx+gindex);
/* increment */
gindex++ ;
}
/* status */
if ( spicmd == SPI_S ) { SPDR = s_flags.DR & MASK0F ; }
}
UBYTE establish_c328(void)
{
UWORD i ;
UWORD length ;
UBYTE result ;
UBYTE gflag ;
UBYTE yflag0 ;
UBYTE yflag1 ;
/* default */
gflag = OFF ;
yflag0 = OFF ;
yflag1 = OFF ;
/* if ( DFLAG ) { rs_puts_txd1((UBYTE *)" _SYNC") ; } */
/* flush */
length = get_ring_cap() ;
if ( length ) {
for ( i = 0 ; i < length ; i++ ) { result = get_ring() ; }
}
/* looping */
for ( i = 0 ; i < 60 ; i++ ) {
/* send SYNC command */
send_sync();
/* wait */
delay_ms( 10 ) ;
/* judge */
if ( get_ring_cap() < 12 ) continue ;
/* get data from buffer */
length = get_ring_cap() ;
for ( i = 0 ; i < length ; i++ ) {
if ( i > 11 ) { result = get_ring() ; }
else { *(dummy+i) = get_ring() ; }
}
/* */
gflag = ON ;
if ( gflag ) break ;
}
/* judge */
if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x0D ) { yflag0 = ON ; }
if ( *(dummy+7) == 0x0D && *(dummy+8) == 0x00 ) { yflag1 = ON ; }
/* send ACK */
result = gflag & yflag0 & yflag1 ;
if ( result ) {
send_ack( 0x0D ) ;
}
return result ;
}
void send_c328(UBYTE x,UWORD p0,UWORD p1)
{
rs_putchar( 0xAA );
rs_putchar( x );
rs_putchar( (UBYTE)((p0 >> 8) & MASKFF) );
rs_putchar( (UBYTE)(p0 & MASKFF) );
rs_putchar( (UBYTE)((p1 >> 8) & MASKFF) );
rs_putchar( (UBYTE)(p1 & MASKFF) );
}
void send_sync(void)
{
send_c328(0x0D,0x0000,0x0000);
}
void send_ack(UBYTE x)
{
send_c328(0x0D,(x << 8) | 0x00,0x0000);
}
/* Timer1 interrupt */
ISR(TIMER1_COMPA_vect)
{
/* increment */
tickcount++ ;
}
void delay_ms(UBYTE x)
{
ULONG target ;
/* set target */
target = tickcount + (ULONG)x ;
/* wait */
while( target > tickcount ) ;
}
void put_ring(UBYTE x)
{
UWORD ptmp ;
/* store data */
rings.data[rings.wrp] = x ;
/* pointer increment */
ptmp = rings.wrp ;
ptmp++ ;
if ( ptmp == RING_BSIZE ) { rings.wrp = 0 ; }
/* capacity increment */
ptmp = rings.capacity ;
ptmp++ ;
rings.capacity = ptmp ;
}
UBYTE get_ring(void)
{
UWORD ptmp ;
UBYTE result ;
/* default */
result = 0 ;
/* judge */
ptmp = rings.rdp ;
if ( rings.capacity == 0 ) { return result ; }
/* read data */
result = rings.data[ptmp] ;
/* pointer increment */
ptmp++ ;
if ( ptmp == RING_BSIZE ) { rings.rdp = 0 ; }
/* capacity decrement */
ptmp = rings.capacity ;
if ( ptmp > 0 ) { rings.capacity = ptmp - 1 ; }
return result ;
}
UWORD get_ring_cap(void)
{
return rings.capacity ;
}
void init_ring(void)
{
/* clear capacity */
rings.capacity = 0 ;
/* initialize read pointer */
rings.rdp = 0 ;
/* initialize write pointer */
rings.wrp = 0 ;
}
UBYTE init_c328(void)
{
UWORD i ;
UWORD length ;
UBYTE yflag0 ;
UBYTE yflag1 ;
/* set BUSY */
BFLAG = ON ;
/* default */
yflag0 = OFF ;
/* send SYNC command */
send_init();
/* wait response */
delay_ms(20) ;
/* get data from buffer */
length = get_ring_cap() ;
for ( i = 0 ; i < 6 ; i++ ) { *(dummy+i) = get_ring() ; }
if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x01 ) { yflag0 = ON ; }
/* send snap shot */
send_snapshot();
/* wait response */
delay_ms(20) ;
/* get data from buffer */
length = get_ring_cap() ;
for ( i = 6 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
if ( *(dummy+7) == 0x0E && *(dummy+8) == 0x05 ) { yflag1 = ON ; }
/* reset BUSY */
BFLAG = OFF ;
return yflag1 & yflag0 ;
}
void send_init(void)
{
send_c328(0x01,0x0003,0x0100);
}
void send_snapshot(void)
{
send_c328( 0x05 , 0x0100 , 0x0000 );
}
void send_get_img(void)
{
send_c328(0x04,0x0100,0x0000);
}
UBYTE get_c328(void)
{
UWORD i ;
UWORD j ;
ULONG length ;
UBYTE k ;
UBYTE resx ;
UBYTE result ;
UBYTE yflag0 ;
UBYTE yflag1 ;
/* set BUSY */
BFLAG = ON ;
/* set status */
SBUSY = ON ;
/* sweap */
length = get_ring_cap();
if ( length ) {
for ( i = 0 ; i < (UWORD)length ; i++ ) { result = get_ring() ;}
}
/* send get picture command */
send_get_img();
/* wait */
while ( ON ) {
result = get_ring_cap() ;
if ( result >= 12 ) break ;
delay_ms(1);
}
/* copy */
for ( i = 0 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
/* judge */
yflag0 = OFF ;
yflag1 = OFF ;
if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x04 ) { yflag0 = ON ; }
if ( *(dummy+7) == 0x0A && *(dummy+8) == 0x01 ) { yflag1 = ON ; }
/* calculate size */
length = *(dummy+11) ; length <<= 8 ;
length += *(dummy+10) ; length <<= 8 ;
length += *(dummy+9 ) ;
if ( length > 32767 ) {
/* flush */
length = get_ring_cap();
for ( i = 0 ; i < length ; i++ ) { result = get_ring(); }
return OFF ;
}
/* get image data */
k = 0 ;
resx = 0 ;
for ( i = 0 ; i < (UWORD)length ; i++ ) {
/* wait receive graphic data */
while ( get_ring_cap() <= 0 ) ;
/* get 1 pixel */
result = get_ring();
/* judge */
if ( result > threshold ) { resx++ ; }
/* block summuation */
j = i % 10 ;
if ( j == 9 ) {
/* store summuation */
*(gdat+k) = resx ;
/* clear block summuation */
resx = 0 ;
/* pointer increment */
k++ ;
}
}
/* send ACK */
send_ack( 0x0A );
/* generate sensor data */
SCRANK = OFF ;
SLANERIGHT = OFF ;
SLANELEFT = OFF ;
for ( i = 0 ; i < LINE_MAX ; i++ ) {
/* index */
j = (i << 3) ;
/* summuation */
resx = 0 ;
resx += *(gdat+j+0) ;
resx += *(gdat+j+1) ;
resx += *(gdat+j+2) ;
resx += *(gdat+j+3) ;
resx += *(gdat+j+4) ;
resx += *(gdat+j+5) ;
resx += *(gdat+j+6) ;
resx += *(gdat+j+7) ;
/* average */
resx >>= 3 ;
/* convert */
result = 0 ;
if ( *(gdat+j+0) > result ) { result |= 0x80 ; }
if ( *(gdat+j+1) > result ) { result |= 0x40 ; }
if ( *(gdat+j+2) > result ) { result |= 0x20 ; }
if ( *(gdat+j+3) > result ) { result |= 0x10 ; }
if ( *(gdat+j+4) > result ) { result |= 0x08 ; }
if ( *(gdat+j+5) > result ) { result |= 0x04 ; }
if ( *(gdat+j+6) > result ) { result |= 0x02 ; }
if ( *(gdat+j+7) > result ) { result |= 0x01 ; }
/* reverse store */
*(senx+59-i) = result ;
/* judge CRANK */
if ( result == 0xff ) { SCRANK = ON ; }
if ( result == 0xf0 || result == 0xf8 ) { SLANELEFT = ON ; }
if ( result == 0x0f || result == 0x1f ) { SLANERIGHT = ON ; }
}
/* */
BFLAG = OFF ;
/* reset status */
SBUSY = OFF ;
return ON ;
}
UBYTE generate_threshold(void)
{
UWORD i ;
ULONG length ;
UBYTE resx ;
UBYTE resy ;
UBYTE result ;
UBYTE yflag0 ;
UBYTE yflag1 ;
/* set BUSY */
BFLAG = ON ;
/* set status */
SBUSY = ON ;
/* sweap */
length = get_ring_cap();
if ( length ) {
for ( i = 0 ; i< (UWORD)length ; i++ ) { result = get_ring() ;}
}
/* send get picture command */
send_get_img();
/* wait */
while ( ON ) {
result = get_ring_cap() ;
if ( result >= 12 ) break ;
delay_ms(1);
}
/* copy */
for ( i = 0 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
/* judge */
yflag0 = OFF ;
yflag1 = OFF ;
if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x04 ) { yflag0 = ON ; }
if ( *(dummy+7) == 0x0A && *(dummy+8) == 0x01 ) { yflag1 = ON ; }
/* calculate size */
length = *(dummy+11) ; length <<= 8 ;
length += *(dummy+10) ; length <<= 8 ;
length += *(dummy+9 ) ;
if ( length > 32767 ) {
/* flush */
length = get_ring_cap();
for ( i = 0 ; i < length ; i++ ) { result = get_ring(); }
return OFF ;
}
/* get image data */
resx = 0 ;
resy = 0 ;
for ( i = 0 ; i < (UWORD)length ; i++ ) {
/* wait receive graphic data */
while ( get_ring_cap() <= 0 ) ;
/* get 1 pixel */
result = get_ring();
/* judge */
if ( is_middle(i) ) { resx += result ; }
if ( is_edge(i) ) { resy += result ; }
/* calculate threshold and store it */
if ( i == 4799 ) {
resx >>= 3 ;
resy >>= 3 ;
threshold = ((resx+resy) >> 1) ;
}
}
/* send ACK */
send_ack( 0x0A );
/* */
BFLAG = OFF ;
/* reset status */
SBUSY = OFF ;
return ON ;
}
UBYTE is_middle(UWORD x)
{
UBYTE result ;
result = OFF ;
if ( x == 1159 ) { result = ON ; }
if ( x == 1160 ) { result = ON ; }
if ( x == 2359 ) { result = ON ; }
if ( x == 2360 ) { result = ON ; }
if ( x == 3559 ) { result = ON ; }
if ( x == 3540 ) { result = ON ; }
if ( x == 4759 ) { result = ON ; }
if ( x == 4760 ) { result = ON ; }
return result ;
}
UBYTE is_edge(UWORD x)
{
UBYTE result ;
result = OFF ;
if ( x == 1120 ) { result = ON ; }
if ( x == 1179 ) { result = ON ; }
if ( x == 2320 ) { result = ON ; }
if ( x == 2399 ) { result = ON ; }
if ( x == 3520 ) { result = ON ; }
if ( x == 3599 ) { result = ON ; }
if ( x == 4720 ) { result = ON ; }
if ( x == 4799 ) { result = ON ; }
return result ;
}
SENSORテストデバッグ
SENSORをテストするために、STM8Sを利用せずに、ATmega328の
予備ボードを使いました。
SENSORとATmega328をSPIで接続し、さらにATmega328をパーソナル
コンピュータと接続し、TeraTermでコマンドを与えてSPI接続が
うまくいっているかを検証します。
BRAIN
under construction
BRAINソースコード
under construction
BRAINテストデバッグ
under construction
目次
前
次