Caanoo / WIZ Caanoo Controls Info


Pickle

Mega GP Mania
Joined
May 30, 2006
Messages
5,518
Location
Detroit, Michigan
Website
Visit site
I have confirmed some things with GPH

gpio only supports the buttons
but standard linux events are supported

Here are some code samples from GPH. nothing surprising here, but may be useful to beginners.

Code:
#include <stdio.h>
 #include <stdlib.h>
 #include <linux/input.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 
 int main(int argc, char *argv[])
 {
     int fd;
     struct input_event event[16];
     int rbytes, i;
 
     if (argc < 2)
     {
         printf("usage: %s [device]n", argv[0]);
         exit(1);
     }
 
     fd = open(argv[1], O_RDONLY|O_NONBLOCK);
     if (fd < 0)
         perror("open");
 
     while (1) 
     {
         rbytes = read(fd, &event, sizeof(event));
         if (rbytes <= 0)
             continue;
         for (i=0; i<rbytes/sizeof(struct input_event); i++) 
         {
             switch (event[i].type) 
             {
                 case EV_ABS: 
                     switch (event[i].code) 
                     {
                         case ABS_X: printf("x = 0x%xn", event[i].value); break;
                         case ABS_Y: printf("y = 0x%xn", event[i].value); break;
                         default   : printf("type = 0x%x, code = 0x%xn", event[i].type, event[i].code);
                     }
                     break;
                 case EV_KEY:
                     if (event[i].value)
                         printf("button 0x%x pressedn", event[i].code);
                     else
                         printf("button 0x%x releasedn", event[i].code);
                     break;
                 default:
                     if (event[i].type)
                         printf("type = 0x%x, code = 0x%xn", event[i].type, event[i].code);
                     break;
             }
         }
     }
 }

SDL test code:
Code:
#include <SDL.h>
 
 #ifndef WIN32
 
 #include <unistd.h>
 
 #endif
 
 #include <math.h>
 
 #ifdef WIN32
 
 #pragma comment(lib, "SDLmain.lib")
 #pragma comment(lib, "SDL.lib")
 
 #endif
 
 #define FUNCTION_PROCESS
 
 enum
 {
     // 버튼 상태 = 단말기 / 조이스틱
     // 그린 아시아 칩셋 사용 조이스틱 의존
 
     BTN_A = 0,     //       A /             1
     BTN_X = 1,     //       X /             2
     BTN_B = 2,     //       B /             3
     BTN_Y = 3,     //       Y /             4
     BTN_L = 4,     //       L /         5, L1
     BTN_R = 5,     //       R /         6, L2
     BTN_HOME = 6,  //    Home /         7, R1
     BTN_HOLD = 7,  //    Hold /         8, R2
     BTN_HELP1 = 8, //  Help I /        Select
     BTN_HELP2 = 9, // Help II /         Start
     BTN_TACT = 10, //    Tact / L Thumb Stick
 };
 
 // 입력 상태 ( 비트 플래그 사용 )
 enum
 {
     // 방향키( 시계 방향 )
     GP_UP         = 0x00001,
     GP_UP_RIGHT   = 0x00002,
     GP_RIGHT      = 0x00004,
     GP_DOWN_RIGHT = 0x00008,
     GP_DOWN       = 0x00010,
     GP_DOWN_LEFT  = 0x00020,
     GP_LEFT       = 0x00040,
     GP_UP_LEFT    = 0x00080,
 
     // 버튼
     GP_A          = 0x00100,
     GP_X          = 0x00200,
     GP_B          = 0x00400,
     GP_Y          = 0x00800,
     GP_L          = 0x01000,
     GP_R          = 0x02000,
 
     // 기능 버튼
     GP_HOME       = 0x04000,
     GP_HOLD       = 0x08000,
     GP_HELP1      = 0x10000,
     GP_HELP2      = 0x20000,
     GP_TACT       = 0x40000,
 };
 
 // 입력 상태( 조이스틱 연결 개수 )
 int *inputStates = NULL;
 
 // 조이스틱 정보
 SDL_Joystick **joystick = NULL;
 
 // 조이스틱 연결 최개 개수
 const int MAX_CONNECT_JOYSTICK = 4;
 
 // 조이스틱 연결 개수
 int connectJoystickNumber = 0;
 
 // 조이스틱 구분 색상
 int *joystickColors = NULL;
 
 // 화면
 SDL_Surface *screen = NULL;
 
 // 아날로그 스틱 축 좌표
 Sint16 *positionX = NULL;
 Sint16 *positionY = NULL;
 
 // 기준 거리( 아날로그 스틱 입력 무시 구간 )
 const unsigned int basisLength = 10000;
 
 // 이벤트 상태
 SDL_Event eventState;
 
 // 터치 상태 구분
 enum TOUCH_STATE
 {
     TOUCH_NONE = 0,
     TOUCH_DOWN,
     TOUCH_UP,
 };
 
 // 이전 터치 상태
 TOUCH_STATE touchState = TOUCH_NONE;
 
 // 터치 좌표
 Uint16 touchPositionX = 0;
 Uint16 touchPositionY = 0;
 
 // GUI 구분
 enum
 {
     // 방향키( 시계 방향 )
     GUI_UP         = 0,
     GUI_UP_RIGHT   = 1,
     GUI_RIGHT      = 2,
     GUI_DOWN_RIGHT = 3,
     GUI_DOWN       = 4,
     GUI_DOWN_LEFT  = 5,
     GUI_LEFT       = 6,
     GUI_UP_LEFT    = 7,
 
     // 버튼
     GUI_A          = 8,
     GUI_X          = 9,
     GUI_B          = 10,
     GUI_Y          = 11,
     GUI_L          = 12,
     GUI_R          = 13,
 
     // 기능 버튼
     GUI_HOME       = 14,
     GUI_HOLD       = 15,
     GUI_HELP1      = 16,
     GUI_HELP2      = 17,
     GUI_TACT       = 18,
 };
 
 // GUI 출력 영역 최대 개수
 const int MAX_GUI_RECT = 19;
 
 // GUI 출력 영역( 입력 상태 표시 영역 )
 SDL_Rect guiRects[MAX_GUI_RECT];
 
 // GUI 출력 영역 초기화
 void InitializeGUI()
 {
     // 방향키( 시계 방향 )
 
     //GP_UP
     guiRects[GUI_UP].x = 80;
     guiRects[GUI_UP].y = 50;
     guiRects[GUI_UP].w = 20;
     guiRects[GUI_UP].h = 20;
     //GP_UP_RIGHT
     guiRects[GUI_UP_RIGHT].x = 110;
     guiRects[GUI_UP_RIGHT].y = 50;
     guiRects[GUI_UP_RIGHT].w = 20;
     guiRects[GUI_UP_RIGHT].h = 20;
     //GP_RIGHT
     guiRects[GUI_RIGHT].x = 110;
     guiRects[GUI_RIGHT].y = 80;
     guiRects[GUI_RIGHT].w = 20;
     guiRects[GUI_RIGHT].h = 20;
     //GP_DOWN_RIGHT
     guiRects[GUI_DOWN_RIGHT].x = 110;
     guiRects[GUI_DOWN_RIGHT].y = 110;
     guiRects[GUI_DOWN_RIGHT].w = 20;
     guiRects[GUI_DOWN_RIGHT].h = 20;
     //GP_DOWN
     guiRects[GUI_DOWN].x = 80;
     guiRects[GUI_DOWN].y = 110;
     guiRects[GUI_DOWN].w = 20;
     guiRects[GUI_DOWN].h = 20;
     //GP_DOWN_LEFT
     guiRects[GUI_DOWN_LEFT].x = 50;
     guiRects[GUI_DOWN_LEFT].y = 110;
     guiRects[GUI_DOWN_LEFT].w = 20;
     guiRects[GUI_DOWN_LEFT].h = 20;
     //GP_LEFT
     guiRects[GUI_LEFT].x = 50;
     guiRects[GUI_LEFT].y = 80;
     guiRects[GUI_LEFT].w = 20;
     guiRects[GUI_LEFT].h = 20;
     //GP_UP_LEFT
     guiRects[GUI_UP_LEFT].x = 50;
     guiRects[GUI_UP_LEFT].y = 50;
     guiRects[GUI_UP_LEFT].w = 20;
     guiRects[GUI_UP_LEFT].h = 20;
 
     // 버튼
     //GP_A
     guiRects[GUI_A].x = 160;
     guiRects[GUI_A].y = 80;
     guiRects[GUI_A].w = 20;
     guiRects[GUI_A].h = 20;
     //GP_X
     guiRects[GUI_X].x = 190;
     guiRects[GUI_X].y = 110;
     guiRects[GUI_X].w = 20;
     guiRects[GUI_X].h = 20;
     //GP_B
     guiRects[GUI_B].x = 220;
     guiRects[GUI_B].y = 80;
     guiRects[GUI_B].w = 20;
     guiRects[GUI_B].h = 20;
     //GP_Y
     guiRects[GUI_Y].x = 190;
     guiRects[GUI_Y].y = 50;
     guiRects[GUI_Y].w = 20;
     guiRects[GUI_Y].h = 20;
     //GP_L
     guiRects[GUI_L].x = 80;
     guiRects[GUI_L].y = 20;
     guiRects[GUI_L].w = 20;
     guiRects[GUI_L].h = 20;
     //GP_R
     guiRects[GUI_R].x = 190;
     guiRects[GUI_R].y = 20;
     guiRects[GUI_R].w = 20;
     guiRects[GUI_R].h = 20;
 
     // 기능 버튼
     //GP_HOME
     guiRects[GUI_HOME].x = 190;
     guiRects[GUI_HOME].y = 140;
     guiRects[GUI_HOME].w = 20;
     guiRects[GUI_HOME].h = 20;
     //GP_HOLD
     guiRects[GUI_HOLD].x = 250;
     guiRects[GUI_HOLD].y = 80;
     guiRects[GUI_HOLD].w = 20;
     guiRects[GUI_HOLD].h = 20;
     //GP_HELP1
     guiRects[GUI_HELP1].x = 80;
     guiRects[GUI_HELP1].y = 140;
     guiRects[GUI_HELP1].w = 20;
     guiRects[GUI_HELP1].h = 20;
     //GP_HELP2
     guiRects[GUI_HELP2].x = 80;
     guiRects[GUI_HELP2].y = 170;
     guiRects[GUI_HELP2].w = 20;
     guiRects[GUI_HELP2].h = 20;
     //GP_TACT
     guiRects[GUI_TACT].x = 80;
     guiRects[GUI_TACT].y = 80;
     guiRects[GUI_TACT].w = 20;
     guiRects[GUI_TACT].h = 20;
 }
 
 // GUI 화면 출력
 void DrawGUI()
 {
     // 사각형 색상 설정
     Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
 
     // 모든 GUI 영역 출력
     for(int count = 0; count != MAX_GUI_RECT; ++count)
     {
         // 사각형 출력
         SDL_FillRect(screen, &guiRects[count], color);
     }
 }
 
 // 초기화
 int Initialize()
 {
     // SDL 초기화
     SDL_Init(SDL_INIT_EVERYTHING);
 
     // 화면 생성
     screen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE);
 
     // 화면 생성 성공 여부 확인
     if(screen == NULL)
     {
         // 실패
         printf("Create Screen Fail!n");
 
         return -1;
     }
 
     // 조이스틱 연결 개수 얻기
     connectJoystickNumber = SDL_NumJoysticks();
     // 연결 개수 제한
     connectJoystickNumber = connectJoystickNumber > MAX_CONNECT_JOYSTICK ? MAX_CONNECT_JOYSTICK : connectJoystickNumber;
 
     // 조이스틱 연결 개수 확인
     if(connectJoystickNumber < 1)
     {
         // 최소 미달
         printf("Connect Joystick Number : %dn", connectJoystickNumber);
 
         return -1;
     }
 
     // 조이스틱 연결 저장 공간 생성
     joystick = (SDL_Joystick**)malloc(sizeof(SDL_Joystick*) * connectJoystickNumber);
 
     // 조이스틱 연결( 순차적 디바이스 연결 기대 )
     for(int count = 0; count != connectJoystickNumber; ++count)
     {
         joystick[count] = SDL_JoystickOpen(count);
 
         // 조이스틱 연결 확인
         if(joystick[count] == NULL)
         {
             // 실패
             printf("Connect Joystick Fail!n");
 
             return -1;
         }
         else
         {
             // 성공
             printf("Connect Joystick %d Success!n", count);
 
             // 조이스틱 상태 출력
             printf("Hat Number : %dn", SDL_JoystickNumHats(joystick[count]));
             printf("Axe Number : %dn", SDL_JoystickNumAxes(joystick[count]));
             printf("Ball Number : %dn", SDL_JoystickNumBalls(joystick[count]));
             printf("Button Number : %dn", SDL_JoystickNumButtons(joystick[count]));
         }
     }
 
     // 입력 상태 저장 공간 생성, 초기화
     inputStates = (int*)calloc(connectJoystickNumber, sizeof(int));
 
     // 아날로그 스틱 축 좌표 저장 공간 생성, 초기화
     positionX = (Sint16*)calloc(connectJoystickNumber, sizeof(Sint16));
     positionY = (Sint16*)calloc(connectJoystickNumber, sizeof(Sint16));
 
     // 조이스틱 구분 색상 저장 공간 생성, 초기화
     joystickColors = (int*)calloc(MAX_CONNECT_JOYSTICK, sizeof(int));
 
     // 조이스틱 구분 색상 설정
     joystickColors[0] = SDL_MapRGB(screen->format, 255, 0, 0);
     joystickColors[1] = SDL_MapRGB(screen->format, 0, 255, 0);
     joystickColors[2] = SDL_MapRGB(screen->format, 0, 0, 255);
     joystickColors[3] = SDL_MapRGB(screen->format, 255, 255, 0);
 
     // 성공
     return 0;
 }
 
 // 정리
 void CleanUp()
 {
     // 화면 해제
     SDL_FreeSurface(screen);
 
     // 조이스틱 구분 색상 저장 공간 해제
     free(joystickColors);
 
     // 아날로그 스틱 축 좌표 저장 공간 해제
     free(positionX);
     free(positionY);
 
     // 입력 상태 저장 공간 해제
     free(inputStates);
 
     // 조이스틱 해제
     for(int count = 0; count != connectJoystickNumber; ++count)
     {
         SDL_JoystickClose(joystick[count]);
     }
 
     // SDL 정리
     SDL_Quit();
 }
 
 
 // 아날로그 스틱 입력 상태 확인( 8 버튼 맵핑 )
 void CheckAnalogstick(int index, Sint16 x, Sint16 y)
 {
     // 이동 거리 계산
     unsigned int length = (unsigned int)(x * x + y * y);
 
     // 이동 거리 확인
     if(length > basisLength * basisLength)
     {
         // 입력 발생
 
         // 각도 계산
         double radian = atan2((double)y, (double)x);
 
         // 각도 변환( 우측 시작점, 시계 방향 양의 각도, 반시계 방향 음의 각도 )
         float angle = (float)(radian * 180.0 / 3.14159265358979323846);
 
         // 각도 변환( 0 ~ 360도 사이 )
         if(angle < 0.0f)
         {
             angle += 360.0f;
         }
 
         // 외각 총 8개 영역 360 / 8 = 45, 45 / 2 = 22.5
 
         // 우측 영역 확인
         if((angle <= 22.5f ) || (angle >= 360.0f - 22.5f))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_RIGHT;
         }
 
         // 우하단 영역 확인
         else if((22.5f < angle ) && (angle < 22.5f + 45.0f))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_DOWN_RIGHT;
         }
 
         // 하단 영역 확인
         else if((22.5f + 45.0f <= angle ) && (angle <= 22.5f + 45.0f * 2))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_DOWN;
         }
 
         // 좌하단 영역 확인
         else if((22.5f + 45.0f * 2 < angle ) && (angle < 22.5f + 45.0f * 3))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_DOWN_LEFT;
         }
 
         // 좌측 영역 확인
         else if((22.5f + 45.0f * 3 <= angle ) && (angle <= 22.5f + 45.0f * 4))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_LEFT;
         }
 
         // 좌상단 영역 확인
         else if((22.5f + 45.0f * 4 < angle ) && (angle < 22.5f + 45.0f * 5))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_UP_LEFT;
         }
 
         // 상단 영역 확인
         else if((22.5f + 45.0f * 5 <= angle ) && (angle <= 22.5f + 45.0f * 6))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_UP;
         }
 
         // 우상단 영역 확인
         else if((22.5f + 45.0f * 6 < angle ) && (angle < 22.5f + 45.0f * 7))
         {
             // 입력 상태 기록
             inputStates[index] |= GP_UP_RIGHT;
         }
     }
 }
 
 // 업데이트( 함수 사용 )
 int UpdateUsingFunction()
 {
     // 이전 입력 상태 초기화
     memset(inputStates, 0, sizeof(int) * connectJoystickNumber);
 
     // 조이스틱 상태 업데이트
     SDL_JoystickUpdate();
 
     // 모든 조이스틱 대상 처리
     for(int count = 0; count != connectJoystickNumber; ++count)
     {
         // 아날로그 스틱 입력 상태 확인
         Sint16 x = SDL_JoystickGetAxis(joystick[count], 0);
         Sint16 y = SDL_JoystickGetAxis(joystick[count], 1);
         CheckAnalogstick(count, x, y);
 
         // Digital Mode / Analog Mode / CAANOO
         // Center   -257 /  -1281 /      0
         // Up     -32768 / -32768 / -32768
         // Down    32767 /  32767 /  32767
         // Left   -32768 / -32768 / -32768
         // Right   32767 /  32767 /  32767
 
         // 아날로그 스틱 입력 상태 표시
         printf("Joystick %d : < %d, %d >n", count, x, y);
 
         // 키 패드 입력 상태 확인, 기록
         if(SDL_JoystickGetButton(joystick[count], BTN_A))
         {
             printf("Joystick %d : An", count);
             inputStates[count] |= GP_A;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_X))
         {
             printf("Joystick %d : Xn", count);
             inputStates[count] |= GP_X;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_ B) )
         {
             printf("Joystick %d : Bn", count);
             inputStates[count] |= GP_B;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_Y))
         {
             printf("Joystick %d : Yn", count);
             inputStates[count] |= GP_Y;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_L))
         {
             printf("Joystick %d : Ln", count);
             inputStates[count] |= GP_L;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_R))
         {
             printf("Joystick %d : Rn", count);
             inputStates[count] |= GP_R;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_HOME))
         {
             printf("Joystick %d : HOMEn", count);
             inputStates[count] |= GP_HOME;
 
             // 종료 요청
             return -1;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_HOLD))
         {
             printf("Joystick %d : HOLDn", count);
             inputStates[count] |= GP_HOLD;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_HELP1))
         {
             printf("Joystick %d : HELP1n", count);
             inputStates[count] |= GP_HELP1;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_HELP2))
         {
             printf("Joystick %d : HELP2n", count);
             inputStates[count] |= GP_HELP2;
         }
 
         if(SDL_JoystickGetButton(joystick[count], BTN_TACT))
         {
             printf("Joystick %d : TACTn", count);
             inputStates[count] |= GP_TACT;
         }
     }
 
     return 0;
 }
 
 // 업데이트( 이벤트 사용 )
 int UpdateUsingEvent()
 {
     // 이전 입력 상태 초기화
     memset(&eventState, 0, sizeof(SDL_Event));
 
     // 조이스틱 입력 상태 얻기
     SDL_PollEvent(&eventState);
 
     // 입력 발생 확인
     switch(eventState.jbutton.type)
     {
     case SDL_JOYAXISMOTION:
         {
             // 이전 아날로그 스틱 정보 초기화
             inputStates[eventState.jaxis.which] &= 0xFFFFFF00;
 
             // 축 확인
             if(eventState.jaxis.axis == 0)
             {
                 // 아날로그 스틱 X축 좌표 얻기
                 positionX[eventState.jaxis.which] = eventState.jaxis.value;
             }
             else if(eventState.jaxis.axis == 1)
             {
                 // 아날로그 스틱 Y축 좌표 얻기
                 positionY[eventState.jaxis.which] = eventState.jaxis.value;
             }
 
             // 아날로그 스틱 입력 상태 확인
             CheckAnalogstick(eventState.jaxis.which, positionX[eventState.jaxis.which], positionY[eventState.jaxis.which]);
 
             // Digital Mode / Analog Mode / CAANOO
             // Center  -2 / - 10 /    0
             // Up    -256 / -256 / -256
             // Down      255 /  255 /  255
             // Left  -256 / -256 / -256
             // Right  255 /  255 /  255
 
             // 아날로그 스틱 입력 상태 표시
             printf("Joystick %d : < %d, %d >n", eventState.jaxis.which, positionX[eventState.jaxis.which], positionY[eventState.jaxis.which]);
 
             break;
         }
     case SDL_JOYBUTTONDOWN:
         {
             // 키 패드 입력 상태 확인, 기록
             switch(eventState.jbutton.button)
             {
             case BTN_A:
                 {
                     printf("Joystick %d : An", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_A;
                     break;
                 }
             case BTN_X:
                 {
                     printf("Joystick %d : Xn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_X;
                     break;
                 }
             case BTN_B:
                 {
                     printf("Joystick %d : Bn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_B;
                     break;
                 }
             case BTN_Y:
                 {
                     printf("Joystick %d : Yn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_Y;
                     break;
                 }
             case BTN_L:
                 {
                     printf("Joystick %d : Ln", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_L;
                     break;
                 }
             case BTN_R:
                 {
                     printf("Joystick %d : Rn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_R;
                     break;
                 }
             case BTN_HOME:
                 {
                     printf("Joystick %d : HOMEn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_HOME;
 
                     // 종료 요청
                     return -1;
 
                     break;
                 }
             case BTN_HOLD:
                 {
                     printf("Joystick %d : HOLDn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_HOLD;
                     break;
                 }
             case BTN_HELP1:
                 {
                     printf("Joystick %d : HELP1n", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_HELP1;
                     break;
                 }
             case BTN_HELP2:
                 {
                     printf("Joystick %d : HELP2n", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_HELP2;
                     break;
                 }
             case BTN_TACT:
                 {
                     printf("Joystick %d : TACTn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] |= GP_TACT;
                     break;
                 }
             }
 
             break;
         }
     case SDL_JOYBUTTONUP:
         {
             // 키 패드 입력 상태 확인, 기록
             switch(eventState.jbutton.button)
             {
             case BTN_A:
                 {
                     printf("Joystick %d : An", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_A;
                     break;
                 }
             case BTN_X:
                 {
                     printf("Joystick %d : Xn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_X;
                     break;
                 }
             case BTN_B:
                 {
                     printf("Joystick %d : Bn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_B;
                     break;
                 }
             case BTN_Y:
                 {
                     printf("Joystick %d : Yn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_Y;
                     break;
                 }
             case BTN_L:
                 {
                     printf("Joystick %d : Ln", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_L;
                     break;
                 }
             case BTN_R:
                 {
                     printf("Joystick %d : Rn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_R;
                     break;
                 }
             case BTN_HOME:
                 {
                     printf("Joystick %d : HOMEn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_HOME;
 
                     // 종료 요청
                     return -1;
 
                     break;
                 }
             case BTN_HOLD:
                 {
                     printf("Joystick %d : HOLDn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_HOLD;
                     break;
                 }
             case BTN_HELP1:
                 {
                     printf("Joystick %d : HELP1n", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_HELP1;
                     break;
                 }
             case BTN_HELP2:
                 {
                     printf("Joystick %d : HELP2n", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_HELP2;
                     break;
                 }
             case BTN_TACT:
                 {
                     printf("Joystick %d : TACTn", eventState.jaxis.which);
                     inputStates[eventState.jaxis.which] ^= GP_TACT;
                     break;
                 }
             }
 
             break;
         }
     }
 
     // 마우스( 터치 ) 입력 처리 테스트
     if(eventState.button.button == SDL_BUTTON_LEFT)
     {
         // 이동 중 터치 상태 유지
 
         // 입력
         if(eventState.type == SDL_MOUSEBUTTONDOWN)
         {
             touchState = TOUCH_DOWN;
         }
 
         // 해제
         if(eventState.type == SDL_MOUSEBUTTONUP)
         {
             if(touchState == TOUCH_DOWN)
             {
                 touchState = TOUCH_UP;
             }
             else
             {
                 touchState = TOUCH_NONE;
             }
         }
 
         // 터치 좌표 얻기
         touchPositionX = eventState.button.x;
         touchPositionY = eventState.button.y;
 
         // 터치 상태 출력
         printf("Touch State : %s", touchState == TOUCH_NONE ? "NONE" : ( touchState == TOUCH_DOWN ? "DOWN" : "UP"));
 
         // 터치 좌표 출력
         printf(" Touch Position X : %d, Y : %dn", touchPositionX, touchPositionY);
     }
 
     return 0;
 }
 
 // 업데이트
 int Update()
 {
     // 반환값
     int result = 0;
 
 #ifdef FUNCTION_PROCESS
 
     // 업데이트( 함수 사용 )
     result = UpdateUsingFunction();
 
 #else
 
     // 업데이트( 이벤트 사용 )
     result = UpdateUsingEvent();
 
 #endif
 
     // 반환값 전달
     return result;
 }
 
 // 화면 출력
 void Draw()
 {
 // 사각형 크기
     int width = 15;
     int height = 10;
 
     // 사각형 영역 설정
     SDL_Rect rect;
     rect.x = 0;
     rect.y = 0;
     rect.w = 320;
     rect.h = 240;
 
     // 사각형 색상 설정
     Uint32 color = SDL_MapRGB(screen->format, 255, 255, 255);
 
     // 사각형 출력
     SDL_FillRect(screen, &rect, color);
 
     // GUI 화면 출력
     DrawGUI();
 
     // 사각형 영역 설정
     rect.x = 0;
     rect.y = 0;
     rect.w = width;
     rect.h = height;
 
     // 연결된 모든 조이스틱 입력 상태 확인
     for(int count = 0; count != connectJoystickNumber; ++count)
     {
         if(inputStates[count] & GP_UP)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_UP], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_UP_RIGHT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_UP_RIGHT], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_RIGHT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_RIGHT], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_DOWN_RIGHT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_DOWN_RIGHT], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_DOWN)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_DOWN], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_DOWN_LEFT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_DOWN_LEFT], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_LEFT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_LEFT], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_UP_LEFT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_UP_LEFT], joystickColors[count]);
         }
 
         // 입력 상태 확인
         if(inputStates[count] & GP_A)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_A], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_X)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_X], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_ B) 
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_B], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_Y)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_Y], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_L)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_L], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_R)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_R], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_HOME)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_HOME], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_HOLD)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_HOLD], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_HELP1)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_HELP1], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_HELP2)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_HELP2], joystickColors[count]);
         }
 
         if(inputStates[count] & GP_TACT)
         {
             // 사각형 출력
             SDL_FillRect(screen, &guiRects[GUI_TACT], joystickColors[count]);
         }
     }
 
     // 화면 반영
     SDL_Flip(screen);
 
 }
 
 int main(int argc, char* argv[])
 {
     // GUI 출력 영역 초기화
     InitializeGUI();
 
     // 초기화
     if(!Initialize())
     {
         // 메인 루프
         while(!Update())
         {
             // 화면 출력
             Draw();
         }
     }
 
     // 정리
     CleanUp();
 
 #ifndef _HOST_
 
     // 메뉴 복귀
     chdir("/usr/gp2x");
     system("./gpid.gpu &");
     execlp("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", "--disable-autorun", NULL, 0);
 
 #endif
 
     return 1;
 }
 
Don't know if it helps anyone, but if you're porting something from Wiz to Caanoo, and are using SDL events, i used something similar to the following code as a quick fix:


Code:
#ifdef CAANOO

enum
{
     BTN_A = 0,     //       A /             1
     BTN_X = 1,     //       X /             2
     BTN_B = 2,     //       B /             3
     BTN_Y = 3,     //       Y /             4
     BTN_L = 4,     //       L /         5, L1
     BTN_R = 5,     //       R /         6, L2
     BTN_HOME = 6,  //    Home /         7, R1
     BTN_HOLD = 7,  //    Hold /         8, R2
     BTN_HELP1 = 8, //  Help I /        Select
     BTN_HELP2 = 9, // Help II /         Start
     BTN_TACT = 10, //    Tact / L Thumb Stick
     BTN_UP = 11, 
     BTN_DOWN = 12,
     BTN_LEFT = 13,
     BTN_RIGHT = 14,

};



void Caanoo_PushAnalogEvent(int btn, int pressed){
	
    SDL_Event event;
	
    event.type = (pressed)?SDL_JOYBUTTONDOWN:SDL_JOYBUTTONUP;
    event.jbutton.button = btn;
    event.jbutton.state = (pressed)?SDL_PRESSED:SDL_RELEASED;
    event.jbutton.which = 0;
	
    SDL_PushEvent(&event);	
}

void Caanoo_UpdateAnalog(void){
	
    static int buttonsPrev = 0;
    int buttonsNow = 0;
	
    SDL_JoystickUpdate();
		
    if (SDL_JoystickGetAxis( joy0, 0 ) < -16384) buttonsNow |= (1 << BTN_LEFT);
    if (SDL_JoystickGetAxis( joy0, 0 ) >  16384) buttonsNow |= (1 << BTN_RIGHT);
    if (SDL_JoystickGetAxis( joy0, 1 ) < -16384) buttonsNow |= (1 << BTN_UP);
    if (SDL_JoystickGetAxis( joy0, 1 ) >  16384) buttonsNow |= (1 << BTN_DOWN);
    
    if (buttonsNow != buttonsPrev)
    {
	if ((buttonsNow & (1 << BTN_LEFT)) != (buttonsPrev & (1 << BTN_LEFT)))
	{
		Caanoo_PushAnalogEvent(BTN_LEFT, (buttonsNow & (1 << BTN_LEFT)));
	}
	if ((buttonsNow & (1 << BTN_RIGHT)) != (buttonsPrev & (1 << BTN_RIGHT)))
	{
		Caanoo_PushAnalogEvent(BTN_RIGHT, (buttonsNow & (1 << BTN_RIGHT)));
	}
	if ((buttonsNow & (1 << BTN_UP)) != (buttonsPrev & (1 << BTN_UP)))
	{
		Caanoo_PushAnalogEvent(BTN_UP, (buttonsNow & (1 << BTN_UP)));
	}
	if ((buttonsNow & (1 << BTN_DOWN)) != (buttonsPrev & (1 << BTN_DOWN)))
	{
		Caanoo_PushAnalogEvent(BTN_DOWN, (buttonsNow & (1 << BTN_DOWN)));
	}
    }
    buttonsPrev = buttonsNow;
}
#endif


Then you can just call Caanoo_UpdateAnalog before the event loop:

Code:
#ifdef CAANOO
    Caanoo_UpdateAnalog();
#endif
	
    SDL_Event event;
    while (SDL_PollEvent (&event))
    {
        switch (event.type)
        { 
            //...
        }
    }
 
The analog stick gives 0-255 with 128 being the zero point. I found emulating a dpad works well with triggering with values +/- 64 from the zero point.

GPIO Defines
Code:
Home    0100 1<<8 // wiz is menu
 Help2   0200 1<<9 //wiz is select
 L       0400 1<<10
 R       0800 1<<11
 A       1000 1<<12
 B       2000 1<<13
 X       4000 1<<14
 Y       8000 1<<15
 VolUp  10000 1<<16 // Wiz Only
 VolDn  20000 1<<17 // Wiz Only
 push   40000 1<<18 // Caanoo only
 ??           1<<19
 Help1 100000 1<<20 // Caanoo only
 
Thx Pickle, the GPIO defines already helped me out :)

One question concerning the analog joystick: what's the name of the device? In the first example this is only an argument of the program, so I don't know. Unfortunately I haven't got a Caanoo to test it :(
 
Jan-Nik said:
Thx Pickle, the GPIO defines already helped me out :)

One question concerning the analog joystick: what's the name of the device? In the first example this is only an argument of the program, so I don't know. Unfortunately I haven't got a Caanoo to test it :(

/dev/input/event1
 
Last edited by a moderator:
If I may, I'd like to contribute some advice for anyone writing a program or library: Instead of accessing the controls via mmap'ed GPIO registers, it would be better to access them through the linux device driver (/dev/input or even /dev/GPIO) instead. That way, future community firmwares can offer support for transparent and universal button remapping and even support running dynamically-linked Wiz or GP2X binaries directly. It would do this through a modified device driver. If you access the GPIO registers directly, you will lose this feature for your program or, in the case of the library, every program that uses it.
 
With diagonals:

Lordus said:
Don't know if it helps anyone, but if you're porting something from Wiz to Caanoo, and are using SDL events, i used something similar to the following code as a quick fix:


Code:
#ifdef CAANOO

enum
{
     BTN_A = 0,     //       A /             1
     BTN_X = 1,     //       X /             2
     BTN_B = 2,     //       B /             3
     BTN_Y = 3,     //       Y /             4
     BTN_L = 4,     //       L /         5, L1
     BTN_R = 5,     //       R /         6, L2
     BTN_HOME = 6,  //    Home /         7, R1
     BTN_HOLD = 7,  //    Hold /         8, R2
     BTN_HELP1 = 8, //  Help I /        Select
     BTN_HELP2 = 9, // Help II /         Start
     BTN_TACT = 10, //    Tact / L Thumb Stick
     BTN_UP = 11, 
     BTN_DOWN = 12,
     BTN_LEFT = 13,
     BTN_RIGHT = 14,
     // DIAGONALS
     BTN_UP_LEFT = 15,
     BTN_UP_RIGHT = 16,
     BTN_DOWN_LEFT = 17,
     BTN_DOWN_RIGHT = 18
};



void Caanoo_PushAnalogEvent(int btn, int pressed){
	
    SDL_Event event;
	
    event.type = (pressed)?SDL_JOYBUTTONDOWN:SDL_JOYBUTTONUP;
    event.jbutton.button = btn;
    event.jbutton.state = (pressed)?SDL_PRESSED:SDL_RELEASED;
    event.jbutton.which = 0;
	
    SDL_PushEvent(&event);	
}

void Caanoo_UpdateAnalog(void){
	
    static int buttonsPrev = 0;
    int buttonsNow = 0;
	
    SDL_JoystickUpdate();
		
    if (SDL_JoystickGetAxis( joy0, 0 ) < -16384) buttonsNow |= (1 << BTN_LEFT);
    if (SDL_JoystickGetAxis( joy0, 0 ) >  16384) buttonsNow |= (1 << BTN_RIGHT);
    if (SDL_JoystickGetAxis( joy0, 1 ) < -16384) buttonsNow |= (1 << BTN_UP);
    if (SDL_JoystickGetAxis( joy0, 1 ) >  16384) buttonsNow |= (1 << BTN_DOWN);
    
    // DIAGONALS
    if (SDL_JoystickGetAxis(joy, 0) > 11585 && SDL_JoystickGetAxis(joy, 1) < -11585)
      buttonsNow |= (1 << BTN_UP_RIGHT);
    if (SDL_JoystickGetAxis(joy, 0) > 11585 && SDL_JoystickGetAxis(joy, 1) > 11585)
      buttonsNow |= (1 << BTN_DOWN_RIGHT);
    if (SDL_JoystickGetAxis(joy, 0) < -11585 && SDL_JoystickGetAxis(joy, 1) > 11585)
      buttonsNow |= (1 << BTN_DOWN_LEFT);
    if (SDL_JoystickGetAxis(joy, 0) < -11585 && SDL_JoystickGetAxis(joy, 1) < -11585)
      buttonsNow |= (1 << BTN_UP_LEFT);

    if (buttonsNow != buttonsPrev)
    {
	if ((buttonsNow & (1 << BTN_LEFT)) != (buttonsPrev & (1 << BTN_LEFT)))
	{
		Caanoo_PushAnalogEvent(BTN_LEFT, (buttonsNow & (1 << BTN_LEFT)));
	}
	if ((buttonsNow & (1 << BTN_RIGHT)) != (buttonsPrev & (1 << BTN_RIGHT)))
	{
		Caanoo_PushAnalogEvent(BTN_RIGHT, (buttonsNow & (1 << BTN_RIGHT)));
	}
	if ((buttonsNow & (1 << BTN_UP)) != (buttonsPrev & (1 << BTN_UP)))
	{
		Caanoo_PushAnalogEvent(BTN_UP, (buttonsNow & (1 << BTN_UP)));
	}
	if ((buttonsNow & (1 << BTN_DOWN)) != (buttonsPrev & (1 << BTN_DOWN)))
	{
		Caanoo_PushAnalogEvent(BTN_DOWN, (buttonsNow & (1 << BTN_DOWN)));
	}
      // DIAGONALS
      if ((buttonsNow & (1 << BTN_UP_RIGHT)) != (buttonsPrev & (1<< BTN_UP_RIGHT)))
	{
	  Caanoo_PushAnalogEvent(BTN_UP_RIGHT, (buttonsNow & (1 << BTN_UP_RIGHT)));
	}
      if ((buttonsNow & (1 << BTN_DOWN_RIGHT)) != (buttonsPrev & (1<< BTN_DOWN_RIGHT)))
	{
	  Caanoo_PushAnalogEvent(BTN_DOWN_RIGHT, (buttonsNow & (1 << BTN_DOWN_RIGHT)));
	}
      if ((buttonsNow & (1 << BTN_DOWN_LEFT)) != (buttonsPrev & (1<< BTN_DOWN_LEFT)))
	{
	  Caanoo_PushAnalogEvent(BTN_DOWN_LEFT, (buttonsNow & (1 << BTN_DOWN_LEFT)));
	}
      if ((buttonsNow & (1 << BTN_UP_LEFT)) != (buttonsPrev & (1<< BTN_UP_LEFT)))
	{
	  Caanoo_PushAnalogEvent(BTN_UP_LEFT, (buttonsNow & (1 << BTN_UP_LEFT)));
	}
    }
    buttonsPrev = buttonsNow;
}
#endif


Then you can just call Caanoo_UpdateAnalog before the event loop:

Code:
#ifdef CAANOO
    Caanoo_UpdateAnalog();
#endif
	
    SDL_Event event;
    while (SDL_PollEvent (&event))
    {
        switch (event.type)
        { 
            //...
        }
    }
 
Last edited by a moderator:
Back
Top