'임베이드 장비/입문 실습장비'에 해당되는 글 1건

EMPOS-II 라는 기기가 있습니다

(주 : 한빛전자의 EMPOS II 설명 http://www.hanback.co.kr/htm/sub2_2.htm)

임베이드 시스템 (CPU가 인텔 호환 계열 PC가 아닌, PDA나 휴대폰, 게임기에 들어가는 ARM 계열)의 프로그래밍을
교육 목적으로 만들어 졌다는 기계입니다 ... (;;;)

운영체제 시간때 프로그래밍으로 이 기계 가지고 게임을 만들라는군요.. (게임 공학과 답..)
뭐... CPU 400 Mhz 급... 렘 64MB .. 3D짓을 하면 일이 복잡하니.. 간단한 게임 만들자 해서...



일단 익숙한 윈도우 API 환경.. (임베이드 장비는 웬만하면 리눅스를 사용합니다.)으로 프로토 타입을 뽑았습니다.
30분 가량 대충 뚜둘겨 만든겁니다.. (컬러키니 뭐니 그런거 프로토 타입에 필요 없으니.. 애초에 이게 목적이 아니니)
(해당 소스.. API)

뭐 흔한 플래쉬 게임인 위에서 떨어지는 케릭터를 맞춰서 점수를 올리는
흔한... 낙하병 맞추기 게임 입니다.. (케릭터가.. 전혀 낙하산이 없지만;;;)

음.. 그 다음... 리눅스 기반의 프로그래밍은 vim을 사용하기에.. (전.. 이맥스 인가.. 그걸 씁니다. orz)
그래픽을 삽입하는법을 어떻게 할까 하다가...
예전 닌텐도 DS 만졌을때 윈도우 BMP 파일을 그쪽 NDS에 업로드 해서 띄울때 C언어, 즉 배열에다가 각 픽셀값을 다 때려박아 버리는 무식한 방법.. 이 떠올라

이전에 만든 프로그램을 좀 개조해서 EMPOS-II 에서 제대로 나오게 개조 했습니다.

음.. 이렇게 보니 무슨 암호문 같군요 ㅋㅋ 참고로 0xF81F 는.. 위의 RGB(255,0,255) 투명색을..
16진수상... 0xff00ff00를 각각 RGB 5,6,5 bit로 쉬프트 해서 연산한 결과 입니다.

그리고 여러 짓거리를 하고..
결국은 처음 API로 구현한 프로그램과 같은것이 EMPOS에 떳습니다.
배경 그림 ... 유성 떨어지는걸로 바꿧고...
마우스 클릭을, EMPOS 는 마우스가 없으니 터치 하면 격추한걸로 했고...
7-seg에 16진수로 맞춘 갯수를 표시하게 했고

적이 총 100여개 떨어지는데.. 100개 다 떨어지면 모니터상 (모니터닝 PC) 7-seg에 표시된 16진수를 10진수로 바꿔서 printf 하게 해놨습니다..

자세한건 아래 소스를 보시면...될거 같네요.. >_<;;

음...
main 이 picture_ex.c 파일입니다.
주석이 왜 영어냐면... 한글이 안써져서 입니다 ;;; 리눅스상.. 쩝..

중요 소스는..
// number 7-segment change function
unsigned char Getsegcode(int x)
{
 unsigned int code;
 switch(x)
 {
  case 0x0 : code = 0x3f; break;
  case 0x1 : code = 0x06; break;
  case 0x2 : code = 0x5b; break;
  case 0x3 : code = 0x4f; break;
  case 0x4 : code = 0x66; break;
  case 0x5 : code = 0x6d; break;
  case 0x6 : code = 0x7d; break;
  case 0x7 : code = 0x07; break;
  case 0x8 : code = 0x7f; break;
  case 0x9 : code = 0x6f; break;
  case 0xA : code = 0x77; break;
  case 0xB : code = 0x7C; break;
  case 0xC : code = 0x39; break;
  case 0xD : code = 0x5e; break;
  case 0xE : code = 0x79; break;
  case 0xF : code = 0x71; break;
  default  : code = 0; break;
 }
 return code;
}
숫자가 들어오면 해당 7-seg (디지털 숫자판의 각 led on off 비트 배열 숫자 입니다..)를 리턴하고...
음... 0에 대한 0x3f 값과  7에 대한 0x07 를 플래그로 하면 각각...  
0 :  8421 8421   | 7 : 8421 8421
      0011 1111   |     0000 0111  의 플레그 값이고 이걸 표로 하면

0 : 0x3f
   0 : on  
 5 : on   1 : on
  6 : off   
 4 : on   2 : on
   3 : on  

7 : 0x07   
   0 : on  
 5 : off   1 : on
  6 : off   
 4 : off   2 : on
   3 : off  
 음.. 뭐 대략 저런겁니다..

그림.. 이라 해봤자 적 케릭터 뿌리는 함수입니다.
void draw_image(int x, int y, int widht, int height, unsigned short *data)
{
 int n = 0;
 int i,j;

  for(j = y; j < height + y; ++j)
 {
  if(0 < y && y + height < LCD_HEIGHT)
  for(i = x; i< widht + x; ++i)
  {
   // draw image, but trancolor no draw
   if(0 < x && x + widht < LCD_WIDTH
    && enemy_data[n] != 0xF81F)
   {
    *(back_surface + (j*LCD_WIDTH + i)) = *(data + n);
   }
   ++n;
  } 
 }
}
빨간건, 투명색입니다.. 투명색이 아니거나 메모리 접근해선 안되는곳에 픽셀이 지정되면 그리지 않게 하는겁니다.

main 함수내.. 각 장치 초기화 및 메모리 접근 입니다..
 if( (fd_touch=open("/dev/touch", O_RDWR))<0 )
 {
  puts("device open fail");
  exit( 2 );
 }
 puts("init toutch!!");
 
 // set lcd system
 fd_lcd = open(FBDEVFILE, O_RDWR);
 if(fd_lcd < 0)
 {
  printf("Error fbdev open\n");
  exit(1);
 }
  
 // set lcd pointer
 real_surface =
  (unsigned short *) mmap(0, LCD_WIDTH * LCD_HEIGHT * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd_lcd, 0);
 puts("init lcd");

 // set 7-sement pointer
 for(i = 0; i< 2; ++i)
 {
  if((fd_led[0]=open("/dev/mem", O_RDWR | O_SYNC)) < 0)
  {
   printf("memory open fail\n");
   exit(1);
  }
  addr[i] = mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd_led[0], SEGADDR_1 + (0x00100000 * i));
 }
 puts("init 7seg");
 cnt = 0;
 print_7seg(cnt);
디버깅을 쉽게 하기 위해 초기화 완료되면 init 무엇 이라 했습니다.

다음..
while(Check_End())
 {
  tv.tv_sec = 0;
  tv.tv_usec = 10000;
  FD_ZERO( &rfds );
  FD_SET( fd_touch, &rfds );
  if( (judge = select(fd_touch+1, &rfds, NULL, NULL, &tv)) < 0 )
  {
   puts("select() fail");
   exit( 2 );
  }
셀렉입니다.. 음... 리눅스에선.. 소켓 뿐만 아니라 각 장치가 파일 시스템으로 (int)로 인식되므로 저런게 가능합니다.
대략.. 터치 스크린에 반응이 있으면 1 이상의 값이 judge로 저장 됩니다.. 만약.. -1 이 리턴되면 에러 겠죠

if( judge )
  {
   read( fd_touch, &p, 6 );
   if(p.flag == 0)
   {
    if(Check_Hit(p.x, p.y) == 0)
    {
     print_7seg(cnt++);
    }
   }
   
  // printf("\n(x,y,flag,byte) = (%.3d,%.3d,%d,%d)", p.x, p.y, p.flag, judge);
  }
  // output backscreen
  lmemcpy(back_surface, bg_data, bg_WIDTH * bg_HEIGHT * 2);
   
  // output enemy screen
  for(i=0; i<ENEMY_CNT; ++i)
  {
   if(Enemy[i].life == 1)
   {
    draw_image(Enemy[i].x, Enemy[i].y, enemy_WIDTH, enemy_HEIGHT, enemy_data);
    Enemy[i].y+=add;
   }
  }
  add > 30 ? add : add++;
  
  // copy to real lcd
  lmemcpy(real_surface, back_surface, LCD_WIDTH * LCD_HEIGHT * 2);
맨 윗부터.. 만약 반응이 있으면..... 이넘이 계속 눌려저 있는지 보고(치트 방지), 처음 눌려진거면, 해당 좌표 체크해서 7_seg의 숫자를 증가 시켜 갱신합니다.

다음... 반응이 있던 없던...
백스크린 버퍼에 배경 그림을 카피 하고
그 다음.. 적 스프라이트를 백 스크린 버퍼에 복사하고.
add 는... 떨어지는 속도 값입니다.. 처음에는 5만큰 떨어지다가 매순간 증감시켜서 30이 될때까지 증가 시키죠..
(즉 처음에 천천히 떨어지는 표적이 점점 일정 속도 까지 빨라지는겁니다..)

마지막에 이렇게 갱신된 백스크린의 그림을 리얼 스크린 (지금 LCD 포인터에 연결된 변수에..) 카피 합니다.

소스 자체는 간단하다고 생각되실지 모릅니다만..
리눅스 프로그래밍이라는것이.. vs 가 없어서.. vs에 찌든 사람들은 접근이 어렵지 않을까 생각되네요..
(디버깅 방법 이라던가... 리소스 켓치 라던가..)
신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

티스토리 툴바