답변 : Codevision에서 avr studio4 변환 질문입니다
페이지 정보
작성자 master 작성일18-12-21 00:42 조회3,769회 댓글0건본문
// MCU BASIC: https://www.basic4mcu.com
// DateTime : 2018-12-21 오전 12:47:32
// by Ok-Hyun Park
/*******************************************/
/*nwarm.c: 지렁이 게임*/
/*2008.6 by 고광현*/
/******************************************/
// warm.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 16000000UL // 16 MHz
#include <util/delay.h>
#include <stdlib.h>
//
#define SIZE 16 // 오목판(LDM)사이즈
#define LINE_ADDR PORTG // Line Address
#define RED_1 PORTA|=1 // Red LED Data PA0
#define RED_0 PORTA&=~1 // Red LED Data PA0
#define GREEN_1 PORTA|=2 // Green LED Data PA1
#define GREEN_0 PORTA&=~2 // Green LED Data PA1
#define ENABLE_1 PORTA|=4 // Output Enable PA2
#define ENABLE_0 PORTA&=~4 // Output Enable PA2
#define LATCH_1 PORTA|=8 // Latch PA3
#define LATCH_0 PORTA&=~8 // Latch PA3
#define CLOCK_1 PORTA|=0x10 // Clock PA4
#define CLOCK_0 PORTA&=~0x10 // Clock PA4
#define UP_SW (PINC&1) // Up 이동 스위치 PC0
#define DOWN_SW (PINC&2) // Down 이동 스위치 PC1
#define LEFT_SW (PINC&4) // Left 이동 스위치 PC2
#define RIGHT_SW (PINC&8) // Right 이동 스위치 PC3
#define PUT_SW (PINC&0x10) // Put 스위치(사용 안함)PC4
#define START_SW (PINC&0x20) // Start 스위치 PC5
#define UP 1 // 지렁이 움직이는 방향 위
#define DOWN 2 // 지렁이 움직이는 방향 아래
#define LEFT 3 // 지렁이 움직이는 방향 왼쪽
#define RIGHT 4 // 지렁이 움직이는 방향 오른쪽
// 사용 변수
int dot_i=0; // 타이머 오버플로우(1ms)인터럽트 함수에서
// 다음에 표시할 라인 번호
int h_x,h_y; // 머리 x,y 좌표
int o_x,o_y; // 먹이 x,y 좌표
char dir; // 지렁이 이동 방향
int tcnt=0;
int length=0; // 지렁이 마디 수
int kk; // 꼬리 배열 번호(새로운 머리 좌표 저장할 배연 번호)
int lent_time,st=0;
char dot_red[SIZE][SIZE]; // LDM 제어신호에서 사용할 R성분
char dot_green[SIZE][SIZE]; // LDM 제어신호에서 사용할 G성분
char w_x[256],w_y[256]; // 마디 좌표 저장 배열 변수
char buf_x[256],buf_y[256]; // 마디 좌표 일시 저장 작업 배열 변수
// 7-세그먼트 숫자 출력 패턴
char seg_pat[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
char w_init[3][2]={{ 0,0},{ 1,0},{ 2,0} }; // 지렁이 시작 마디 좌표
char sijak[16][16]={ // "웜게임" 문자 패턴
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,1},
{ 0,1,0,0,1,0,0,1,0,0,0,1,0,1,0,1},
{ 0,1,0,0,1,0,0,1,0,0,0,1,0,1,0,1},
{ 0,0,1,1,0,0,0,1,0,0,0,1,1,1,0,1},
{ 0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,1},
{ 0,1,1,1,1,1,0,1,0,0,1,0,0,1,0,1},
{ 0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1},
{ 0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0},
{ 0,0,0,1,0,0,0,1,0,0,1,1,1,0,0,1},
{ 0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1},
{ 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,1},
{ 0,1,0,0,0,0,0,1,0,0,1,1,1,0,0,1},
{ 0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,1},
{ 0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1},
{ 0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1}
};
char end[16][16]={ // "END" 문자 패턴
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 1,1,1,1,0,1,0,0,0,1,0,1,1,1,0,0},
{ 1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,1,0,1,0,1,0,0,1,0},
{ 1,1,1,1,0,1,0,1,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,1,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,1,0,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0},
{ 1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0},
{ 1,1,1,1,0,1,0,0,0,1,0,1,1,1,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
//
void disp_init(void){ // LDM "웜게임" 출력 표시
int i,j;
for(j=0; j<SIZE; j++){
for(i=0; i<SIZE; i++){
dot_green[j][i]=sijak[j][i]; // 도트매트릭스 클리어
dot_red[j][i]=sijak[j][i];
}
}
}
//
void disp_end(void){ // LDM "END" 출력 표시
int i,j;
for(j=0; j<SIZE; j++){
for(i=0; i<SIZE; i++)dot_red[j][i]=end[j][i]; // 도트매트릭스 클리어
}
}
//
void warm_init(void){ // 게임 초시 상태 설정
int i,j,x,y;
// 도트매트릭스 클리어
for(j=0; j<SIZE; j++){
for(i=0; i<SIZE; i++){
dot_green[j][i]=0;
dot_red[j][i]=0;
}
}
// 지렁이 초기 상태의 마디 좌표 설정(길이 3)
for(i=0; i<3; i++){
x=w_init[i][0];
y=w_init[i][1];
w_x[i]=x; // 마디 x좌표
w_y[i]=y; // 마디 y좌표
dot_green[y][x]=1; // 녹색 LED on(지렁이 몸체)
}
h_x=w_init[2][0]; // 머리 x 좌표
h_y=w_init[2][1]; // 머리 y 좌표
length=3; // 길이 3
kk=0; // 꼬리 배열 번호
dot_i=0; // 타이머 인터럽트 함수에서 표시할 라인 초기 번호
o_x=12; // 초기 먹이 위치
o_y=12;
LINE_ADDR=0; // 표시할 라인 초기 어드레스=0
RED_0; // Red LED off
GREEN_0; // Green LED off
LATCH_1; // Latch high
ENABLE_0; // Output Enable low
CLOCK_0; // Clock low
dot_red[o_y][o_x]=1; // 먹이 적색 표시
lent_time=500-length*5; // 게임 진행 속도 딜레이 계산
}
//
void seg_out(){ // 지렁이 마디 수 7-세그먼트 표시
int n100,n10,n1,buf;
n100=length/100; // 100자리 추출
buf=length%100; // 100으로 나눈 나머지
n10=buf/10; // 10자리 추출
n1=buf%10; // 1자리 추출
PORTF=0b11100000; // 1자리 세그먼트 ON
PORTB=seg_pat[n1]; // 1자리 출력
_delay_us(50);
PORTF=0b11010000; // 10자리 세그먼트 ON
PORTB=seg_pat[n10]; // 10자리 출력
_delay_us(50);
PORTF=0b10110000; // 100자리 세그먼트 ON
PORTB=seg_pat[n100]; // 100자리 출력
_delay_us(50);
}
//
void sw_input(){ // 스위치 입력 처리
seg_out(); // 지렁이 마디수 출력
if(dir!=DOWN&&UP_SW==0)dir=UP; // 이동 방향 위로
else if(dir!=UP&&DOWN_SW==0)dir=DOWN; // 아래 이동 스위치
else if(dir!=RIGHT&&LEFT_SW==0)dir=LEFT; // 왼쪽 이동 스위치
else if(dir!=LEFT&&RIGHT_SW==0)dir=RIGHT; // 오른쪽 이동 스위치
}
//
ISR(TIMER0_OVF_vect){ // 타이머/카운터0(256-0)*64/16 us=1.024ms
int bx,by,i,di;
dot_i=(dot_i+1)%SIZE; // LDM 표시라인 1증가
tcnt++; // 게임 진행속도 조절 카운터
for(di=0; di<SIZE; di++){ // 한 라인 데이터 출력
if(dot_red[dot_i][di])RED_1; else RED_0; // 적색 먹이 데이터
if(dot_green[dot_i][di])GREEN_1; else GREEN_0; // 녹색 먹이 데이터
CLOCK_1; // 클럭 ON
_delay_us(1);
CLOCK_0; // 클럭 OFF
_delay_us(1);
}
_delay_us(1);
ENABLE_1; // Enable 비트 셋
LATCH_0;
_delay_us(1);
LATCH_1;
LINE_ADDR=dot_i; // 출력 라인 설정
_delay_us(1);
ENABLE_0; // 인에이블 비트 리셋
// 게임 진행속도에 맞춰 지렁이 이동방행으로 1칸 이동 처리
if(tcnt>=lent_time&&st==1){
tcnt=0;
if(dir==UP){ // 이동방향=위?
if(h_y>0)h_y--; // 머리 Y좌표 1감소
else st=0; // 윗쪽 벽 충돌 게임종료
}
else if(dir==DOWN){ // 이동방향=아래?
if(h_y<15)h_y++; // 머리 Y좌표 1증가
else st=0; // 아래쪽 벽 충돌 게임종료
}
else if(dir==LEFT){ // 이동방향=왼쪽?
if(h_x>0)h_x--; // 머리 X좌표 1감소
else st=0; // 왼쪽 벽 충돌 게임종료
}
else{ // 이동방향=오른쪽?
if(h_x<15)h_x++; // 머리 X좌표 1감소
else st=0; // 오른쪽 벽 충돌 게임종료
}
if(st==0)return; // 게임종료
if(o_x==h_x&&o_y==h_y){ // 먹이좌표=새로운 머리좌표
// 지렁이 마디 좌표 재정렬 저장
for(i=0; i<length; i++){
buf_x[i]=w_x[kk];
buf_y[i]=w_y[kk];
kk=(kk+1)%length;
}
for(i=0; i<length; i++){
w_x[i]=buf_x[i];
w_y[i]=buf_y[i];
}
w_x[length]=h_x; // 머리부분 좌표
w_y[length]=h_y;
kk=0; // 꼬리부분 배열 번호
length=length+1; // 길이 1증가
if(length<50)lent_time=500-length*5; // 길이에 따라 점점 빠르게
dot_red[o_y][o_x]=0; // 현재 먹이 제거
dot_green[h_y][h_x]=1; // 먹이 부분 추가
// 새 먹이 발생
while(1){
o_x=rand()%16;
o_y=rand()%16;
if(dot_green[o_y][o_x]!=0)continue; // 지렁이 없는 위치에 생성
dot_red[o_y][o_x]=1;
break;
}
}
else{ // 지렁이 단순 이동(먹이 먹지 않은 이동)
bx=w_x[kk]; // 꼬리 좌표 백업
by=w_y[kk];
w_x[kk]=h_x; // 현재의 머리좌표 kk번째 배열에 저장
w_y[kk]=h_y;
dot_green[by][bx]=0; // 현재 꼬리부분 클리어
kk=(kk+1)%length; // 새로운 꼬리부분 배열 번호 갱신
if(dot_green[h_y][h_x]==1)st=0; // 몸부분과 충돌 체크
else dot_green[h_y][h_x]=1; // 새 머리 부분 추가
}
}
}
//
int main(void){
int i;
DDRA=0x1F; // 포트A 출력 설정(LDM 제어핀)
DDRG=0x1F; // 포트G 출력설정(LDM 어드레스 A0-A3)
DDRC=0x00; // 포트C 입력 설정(스위치)
DDRB=0xFF; // 포트B 출력 설정(패턴값 출력)
DDRF=0xFF; // 포트F 출력 설정(구동 7-Segment 선택)
PORTA=0b00001100; // Enable High
PORTG=0x0F; // A0-A3=1111
PORTA=0b00001000; // Enable Low
ASSR=0x00; // 타이머/카운터0 타이머 모드
TCCR0=0x04; // 일반모드,프리스케일=CK/64
TCNT0=0x00; // 타이머/카운터0 레지스터 초기값
TIMSK=0x01; // TOIE0=1,타이머/카운터0 인터럽트 인에이블
SREG=0x80; // 전역 인터럽트 인에이블 비트 I 셋
while(1){
disp_init(); // 시작을 위한 초기설정
dir=RIGHT; // 지렁이 이동방향 오른쪽 설정
while(START_SW)seg_out(); // 시작 스위치가 눌려질 때까지 대기
warm_init(); // 지렁이 게임 시작 상태 설정
st=1; // 게임 진행
srand(TCNT0); // TCNTO값 랜덤 seed값으로 이용
while(st)sw_input(); // 스위치 입력 체크
disp_end(); // "END" 표시
for(i=0; i<30000; i++)seg_out(); // 일시 대기
}
}
댓글 : 0
조회수 : 3,769
등록된 댓글이 없습니다.