Better PC Joystick calibration routine

* Cleaned up the parameters page
    * Tweaked main/credits page
This commit is contained in:
Aaron Culliney 2013-12-21 23:55:23 -08:00
parent 34a5fea9a7
commit ef59e1ae9a
3 changed files with 219 additions and 146 deletions

View File

@ -37,7 +37,8 @@ static int altdrive;
/*#else*/
/*#define undoc_supported 0*/
static void copy_and_pad_string(char *dest, const char* src, char c, int len, char cap) {
void copy_and_pad_string(char *dest, const char* src, const char c, const int len, const char cap)
{
const char* p;
char* d = dest;
@ -54,7 +55,7 @@ static void copy_and_pad_string(char *dest, const char* src, char c, int len, ch
*d = cap;
}
static void pad_string(char *s, char c, int len) {
static void pad_string(char *s, const char c, const int len) {
char *p;
for (p = s; ((*p != '\0') && (p-s < len-1)); p++)
@ -103,7 +104,6 @@ void c_interface_print( int x, int y, int cs, const char *s )
{
video_plotchar( x, y, cs, *s );
}
}
/* -------------------------------------------------------------------------
@ -117,20 +117,6 @@ void c_interface_print_screen( char screen[24][INTERFACE_SCREEN_X+1] )
}
}
/* -------------------------------------------------------------------------
c_interface_redo_bottom()
------------------------------------------------------------------------- */
void c_interface_redo_bottom() {
c_interface_print( 1, 21, 2,
" Use arrow keys (or Return) to modify "
);
c_interface_print( 1, 22, 2,
" parameters. (Press ESC to exit menu) "
);
}
/* -------------------------------------------------------------------------
c_interface_translate_screen()
------------------------------------------------------------------------- */
@ -138,7 +124,7 @@ void c_interface_redo_bottom() {
#define IsGraphic(c) ((c) == '|' || (((unsigned char)c) >= 0x80 && ((unsigned char)c) <= 0x8A))
#define IsInside(x,y) ((x) >= 0 && (x) <= xlen-1 && (y) >= 0 && (y) <= ylen-1)
static void _convert_screen_graphics( char *screen, int x, int y, int xlen, int ylen )
static void _convert_screen_graphics( char *screen, const int x, const int y, const int xlen, const int ylen )
{
static char map[11][3][4] ={ { "...",
".||",
@ -228,48 +214,36 @@ static void _convert_screen_graphics( char *screen, int x, int y, int xlen, int
if (found_glyph)
{
//screen[ y ][ x ] = 0x80 + k;
*(screen + y*(xlen+1) + x) = 0x80 + k;
}
}
void c_interface_translate_screen( char screen[24][INTERFACE_SCREEN_X+1] )
{
for (int y = 0; y < 24; y++)
{
for (int x = 0; x < INTERFACE_SCREEN_X; x++)
{
if (screen[ y ][ x ] == '|')
{
_convert_screen_graphics(screen[0], x, y, INTERFACE_SCREEN_X, 24);
}
}
}
}
/* -------------------------------------------------------------------------
c_interface_translate_menu()
------------------------------------------------------------------------- */
void c_interface_translate_menu( char *submenu, int xlen, int ylen )
static void c_interface_translate_screen_x_y(char *screen, const int xlen, const int ylen)
{
for (int idx=0, y=0; y < ylen; y++, idx+=xlen+1)
{
for (int x = 0; x < xlen; x++)
{
if (*(submenu + idx + x) == '|')
if (*(screen + idx + x) == '|')
{
_convert_screen_graphics(submenu, x, y, xlen, ylen);
_convert_screen_graphics(screen, x, y, xlen, ylen);
}
}
}
}
void c_interface_translate_screen( char screen[24][INTERFACE_SCREEN_X+1] )
{
c_interface_translate_screen_x_y(screen[0], INTERFACE_SCREEN_X, 24);
}
/* -------------------------------------------------------------------------
c_interface_print_submenu_centered()
------------------------------------------------------------------------- */
void c_interface_print_submenu_centered( char *submenu, int xlen, int ylen )
void c_interface_print_submenu_centered( char *submenu, const int xlen, const int ylen )
{
c_interface_translate_menu(submenu, xlen, ylen);
c_interface_translate_screen_x_y(submenu, xlen, ylen);
int x = (INTERFACE_SCREEN_X - xlen) >> 1;
int y = (24 - ylen) >> 1;
@ -784,18 +758,18 @@ typedef enum interface_enum_t {
static const char *options[] =
{
" CPU% : ",
" ALT CPU% : ",
" Path : ",
" CPU% : ",
" ALT CPU% : ",
" Path : ",
//" Mode : ",
" Color : ",
" Volume : ",
" Joystick : ",
" Calibrate ",
" JS Sens. : ",
" JS Sample: ",
" Save Prefs ",
" Quit "
" Color : ",
" Volume : ",
" Joystick : ",
" Calibrate Joystick...",
" JS Sens. : ",
" JS Sample: ",
" Save Preferences...",
" Quit Emulator...",
};
#define INTERFACE_PATH_MAX 65
@ -856,7 +830,12 @@ void c_interface_parameters()
cur_off = 0;
}
c_interface_print( 1, 5 + i, cur_y == i, options[ i + cur_off ] );
c_interface_print( 1, 5 + i, cur_y == i, options[i + cur_off]);
int optlen = strlen(options[i + cur_off]);
snprintf(temp, TEMPSIZE, " ");
pad_string(temp, ' ', INTERFACE_PATH_MAX+1-optlen);
c_interface_print( 1+optlen, 5 + i, 0, temp );
switch (i + cur_off)
{
@ -917,7 +896,6 @@ void c_interface_parameters()
break;
case OPT_CALIBRATE:
strncpy( temp, "", TEMPSIZE );
break;
case OPT_JS_SENSE:
@ -933,11 +911,9 @@ void c_interface_parameters()
break;
case OPT_SAVE:
strcpy( temp, "" );
break;
case OPT_QUIT:
strcpy( temp, "" );
break;
default:
@ -945,11 +921,12 @@ void c_interface_parameters()
}
pad_string(temp, ' ', INTERFACE_PATH_MAX+1);
if (i+cur_off != 2)
int loc = i+cur_off;
if ((loc != OPT_PATH) && (loc != OPT_CALIBRATE) && (loc != OPT_SAVE) && (loc != OPT_QUIT))
{
c_interface_print(INTERFACE_PATH_MIN, 5 + i, 0, temp);
}
else
else if (loc == OPT_PATH)
{
int j;
@ -1348,6 +1325,7 @@ void c_interface_parameters()
c_close_joystick();
c_open_joystick();
c_calibrate_joystick();
c_interface_print_screen( screen );
}
/* save settings */
@ -1455,26 +1433,33 @@ void c_interface_credits()
"| |",
"| |",
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||",
"| ESC to begin! |",
"| @ @ to scroll notes - ESC to begin emulation |",
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" };
#define SCROLL_AREA_X 2
#define SCROLL_AREA_Y 5
#define SCROLL_AREA_HEIGHT 16
screen[ 2 ][ 33 ] = MOUSETEXT_BEGIN + 0x01;
screen[ 2 ][ 46 ] = MOUSETEXT_BEGIN + 0x00;
screen[ 22 ][ 18 ] = MOUSETEXT_BEGIN + 0x0b;
screen[ 22 ][ 20 ] = MOUSETEXT_BEGIN + 0x0a;
#define SCROLL_LENGTH 54
char credits[SCROLL_LENGTH][INTERFACE_SCREEN_X+1-(SCROLL_AREA_X*2)]=
#define SCROLL_WIDTH (INTERFACE_SCREEN_X+1-(SCROLL_AREA_X*2))
char credits[SCROLL_LENGTH][SCROLL_WIDTH]=
//1. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. 55. 60. 65. 70. 75. 80.",
{ " ",
" An Apple //e Emulator for POSIX Systems! ",
" ",
"WELCOME! ",
" @ Press F8 any time to return here @ ",
" ",
" > @ @ keys will scroll this page ",
" > ESC key will exit this page and begin emulation ",
" > F10 will show the emulator preferences menu ",
" > F8 will reshow this page ",
" > F5 will show the keyboard layout menu ",
" > F1 and F2 will open the diskette selection menus ",
"QUICKSTART ",
" ",
"Press F8 at any time to return to this page ",
"Press F10 to view preferences menu ",
"Press F1 to load diskette in Slot 6, Drive A ",
"Press F2 to load diskette in Slot 6, Drive B ",
" ",
"AUTHORS/CREDITS ",
" ",
@ -1486,10 +1471,11 @@ void c_interface_credits()
" ",
"ADDITIONAL CREDITS ",
" ",
"This software uses various Open Source software libraries, including: ",
"This software uses various Free & Open Source software, including ",
" ",
" > Compression routines from the Zlib project -- http://zlib.net ",
" > Audio source code derived from AppleWin -- http://applewin.berlios.de ",
" > OpenAL audio library -- http://sourceforge.net/projects/openal-soft ",
" > Compression routines from the Zlib project -- http://zlib.net ",
" ",
"LICENSE ",
" ",
@ -1520,29 +1506,33 @@ void c_interface_credits()
video_setpage( 0 );
screen[ 2 ][ 33 ] = MOUSETEXT_BEGIN + 0x01;
screen[ 2 ][ 46 ] = MOUSETEXT_BEGIN + 0x00;
credits[ 5 ][ 3 ] = MOUSETEXT_BEGIN + 0x0b;
credits[ 5 ][ 5 ] = MOUSETEXT_BEGIN + 0x0a;
c_interface_translate_screen( screen );
c_interface_translate_screen_x_y( credits[0], SCROLL_WIDTH, SCROLL_LENGTH);
c_interface_print_screen( screen );
int pos = 0;
int ch = -1;
int count = -1;
unsigned int mt_idx = 0;
for (;;)
{
ch = c_mygetch(0);
#define FLASH_APPLE_DELAY 3
count = (count+1) % FLASH_APPLE_DELAY;
if (!count)
{
mt_idx = (mt_idx+1) % 2;
credits[ 3 ][ 20 ] = MOUSETEXT_BEGIN + mt_idx;
credits[ 3 ][ 55 ] = MOUSETEXT_BEGIN + ((mt_idx+1) % 2);
}
for (int i=0, p=pos; i<SCROLL_AREA_HEIGHT; i++)
{
c_interface_print(SCROLL_AREA_X, SCROLL_AREA_Y+i, 2, credits[p]);
p = (p+1) % SCROLL_LENGTH;
}
while ((ch = c_mygetch(1)) == -1)
{
}
if (ch == kUP)
{
--pos;
@ -1563,6 +1553,10 @@ void c_interface_credits()
{
break;
}
static struct timespec ts = { .tv_sec=0, .tv_nsec=33333333 };
nanosleep(&ts, NULL);
video_sync(1);
}
c_interface_exit(ch);

View File

@ -19,9 +19,8 @@
#define INTERFACE_SCREEN_X 80
void c_interface_print(int x, int y, int cs, const char *s);
void c_interface_print_submenu_centered(char *submenu, int xlen, int ylen);
void c_interface_redo_bottom(); /* bit of a HACK? */
void c_interface_print(int x, int y, const int cs, const char *s);
void c_interface_print_submenu_centered(char *submenu, const int xlen, const int ylen);
void c_load_interface_font();
void c_interface_keyboard_layout();
void c_interface_parameters();

View File

@ -123,10 +123,26 @@ static void c_calculate_pc_joystick_parms()
and center coordinates. assumes that it can write to the interface
screen.
------------------------------------------------------------------------- */
extern void copy_and_pad_string(char *dest, const char* src, const char c, const int len, const char cap);
static void c_calibrate_pc_joystick()
{
int almost_done, done;
unsigned char x_val, y_val;
#define JOYERR_PAD 35
#define JOYERR_SUBMENU_H 8
#define JOYERR_SUBMENU_W 40
char errmenu[JOYERR_SUBMENU_H][JOYERR_SUBMENU_W+1] =
//1. 5. 10. 15. 20. 25. 30. 35. 40.
{ "||||||||||||||||||||||||||||||||||||||||",
"| |",
"| An error occurred: |",
"| |",
"| Is a joystick device connected? |",
"| Is the proper kernel module loaded? |",
"| |",
"||||||||||||||||||||||||||||||||||||||||" };
#define JOYERR_SHOWERR(ERR) \
copy_and_pad_string(&errmenu[3][2], ERR, ' ', JOYERR_PAD, ' '); \
c_interface_print_submenu_centered(errmenu[0], JOYERR_SUBMENU_W, JOYERR_SUBMENU_H); \
while (c_mygetch(1) == -1) { }
/* reset all the extremes */
js_max_x = -1;
@ -137,36 +153,53 @@ static void c_calibrate_pc_joystick()
/* open joystick device if not open */
if (js_fd < 0)
{
if (c_open_pc_joystick()) /* problem opening device */
if (c_open_pc_joystick())
{
c_interface_print(
1, 21, 0, " " );
c_interface_print(
1, 22, 0, " cannot open joystick device. " );
video_sync(0);
usleep(1500000);
c_interface_redo_bottom();
return; /* problem */
JOYERR_SHOWERR(strerror(errno));
return;
}
}
c_interface_print(
1, 21, 0, " Move joystick to all extremes then " );
c_interface_print(
1, 22, 0, " center it and press a button. " );
video_sync(0);
usleep(1500000);
c_interface_print(
1, 21, 0, " " );
c_interface_print(
1, 22, 0, " " );
#define CALIBRATE_SUBMENU_H 7
#define CALIBRATE_SUBMENU_W 40
char submenu[CALIBRATE_SUBMENU_H][CALIBRATE_SUBMENU_W+1] =
//1. 5. 10. 15. 20. 25. 30. 35. 40.
{ "||||||||||||||||||||||||||||||||||||||||",
"| |",
"| Move joystick to all extremes then |",
"| center it and long-press joy button |",
"| |",
"| btn1:@ btn2:@ x:@@@@ y:@@@@ |",
"||||||||||||||||||||||||||||||||||||||||" };
almost_done = done = 0; /* not done calibrating */
while ((read(js_fd, &js, JS_RETURN) > 0) && (!done))
#define LONG_PRESS_THRESHOLD 120
#define SHOW_JOYSTICK_AXES(MENU, WIDTH, HEIGHT, X, Y) \
sprintf(temp, "%04x", (short)(X)); \
copy_and_pad_string(&MENU[HEIGHT-2][24], temp, ' ', 5, ' '); \
sprintf(temp, "%04x", (short)(Y)); \
copy_and_pad_string(&MENU[HEIGHT-2][32], temp, ' ', 5, ' '); \
c_interface_print_submenu_centered(MENU[0], WIDTH, HEIGHT);
#define SHOW_BUTTONS(MENU, HEIGHT) \
MENU[HEIGHT-2][8] = (js.buttons & 0x01) ? 'X' : ' '; \
MENU[HEIGHT-2][15] = (js.buttons & 0x02) ? 'X' : ' '; \
if (js.buttons & 0x03) \
{ \
++long_press; \
} \
else \
{ \
long_press = 0; \
}
unsigned int long_press = 0;
while ((read(js_fd, &js, JS_RETURN) > 0))
{
sprintf(temp, " x = %04x, y = %04x", js.x, js.y);
c_interface_print(1, 22, 0, temp);
SHOW_BUTTONS(submenu, CALIBRATE_SUBMENU_H);
SHOW_JOYSTICK_AXES(submenu, CALIBRATE_SUBMENU_W, CALIBRATE_SUBMENU_H, js.x, js.y);
video_sync(0);
if (js_max_x < js.x)
{
js_max_x = js.x;
@ -187,50 +220,79 @@ static void c_calibrate_pc_joystick()
js_min_y = js.y;
}
if (js.buttons != 0x00) /* press */
if (long_press > LONG_PRESS_THRESHOLD)
{
almost_done = 1;
}
if (almost_done && (js.buttons == 0x00)) /* release */
{
done = 1;
break;
}
}
long_press = 0;
js_center_x = js.x;
js_center_y = js.y;
printf("js_min_x = %d\n", js_min_x);
printf("js_min_y = %d\n", js_min_y);
printf("js_max_x = %d\n", js_max_x);
printf("js_max_y = %d\n", js_max_y);
printf("js_center_x = %d\n", js_center_x);
printf("js_center_y = %d\n", js_center_y);
printf("\n");
#ifndef NDEBUG
LOG("js_min_x = %d", js_min_x);
LOG("js_min_y = %d", js_min_y);
LOG("js_max_x = %d", js_max_x);
LOG("js_max_y = %d", js_max_y);
LOG("js_center_x = %d", js_center_x);
LOG("js_center_y = %d", js_center_y);
LOG(" ");
#endif
c_calculate_pc_joystick_parms(); /* determine the parms */
c_calculate_pc_joystick_parms();
printf("js_lowerrange_x = %d\n", js_lowerrange_x);
printf("js_lowerrange_y = %d\n", js_lowerrange_y);
printf("js_upperrange_x = %d\n", js_upperrange_x);
printf("js_upperrange_y = %d\n", js_upperrange_y);
printf("\n");
printf("js_offset_x = %d\n", js_offset_x);
printf("js_offset_y = %d\n", js_offset_y);
printf("\n");
printf("js_adjustlow_x = %f\n", js_adjustlow_x);
printf("js_adjustlow_y = %f\n", js_adjustlow_y);
printf("js_adjusthigh_x = %f\n", js_adjusthigh_x);
printf("js_adjusthigh_y = %f\n", js_adjusthigh_y);
printf("\n");
#ifndef NDEBUG
LOG("js_lowerrange_x = %d", js_lowerrange_x);
LOG("js_lowerrange_y = %d", js_lowerrange_y);
LOG("js_upperrange_x = %d", js_upperrange_x);
LOG("js_upperrange_y = %d", js_upperrange_y);
LOG(" ");
LOG("js_offset_x = %d", js_offset_x);
LOG("js_offset_y = %d", js_offset_y);
LOG(" ");
LOG("js_adjustlow_x = %f", js_adjustlow_x);
LOG("js_adjustlow_y = %f", js_adjustlow_y);
LOG("js_adjusthigh_x = %f", js_adjusthigh_x);
LOG("js_adjusthigh_y = %f", js_adjusthigh_y);
LOG(" ");
#endif
c_interface_print(
1, 21, 0, " Press a button to continue. " );
video_sync(0);
#define CALIBRATE_JOYMENU_H 20
#define CALIBRATE_JOYMENU_W 40
#define CALIBRATE_TURTLE_X0 4
#define CALIBRATE_TURTLE_Y0 5
#define CALIBRATE_TURTLE_STEP_X (30.f / 255.f)
#define CALIBRATE_TURTLE_STEP_Y (10.f / 255.f)
char joymenu[CALIBRATE_JOYMENU_H][CALIBRATE_JOYMENU_W+1] =
//1. 5. 10. 15. 20. 25. 30. 35. 40.
{ "||||||||||||||||||||||||||||||||||||||||",
"| |",
"| Long press joy button to quit |",
"| |",
"| ||||||||||||||||||||||||||||||||| |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| | | |",
"| ||||||||||||||||||||||||||||||||| |",
"| |",
"| btn1:@ btn2:@ x:@@@@ y:@@@@ |",
"||||||||||||||||||||||||||||||||||||||||" };
/* show the normalized values until user presses button */
while ((read(js_fd, &js, JS_RETURN) > 0) && js.buttons == 0x00)
uint8_t x_val=0, y_val=0;
uint8_t x_last=CALIBRATE_JOYMENU_W>>1, y_last=CALIBRATE_JOYMENU_H>>1;
const char* const spinney = "|/-\\";
uint8_t spinney_idx=0;
bool finished_press = false;
while (read(js_fd, &js, JS_RETURN) > 0)
{
x_val = (js.x < js_center_x)
? (js.x - js_offset_x) * js_adjustlow_x
@ -241,13 +303,31 @@ static void c_calibrate_pc_joystick()
? (js.y - js_offset_y) * js_adjustlow_y
: (js.y - (js_center_y /*+js_offset_y*/)) * js_adjusthigh_y +
HALF_JOY_RANGE;
sprintf(temp, " x = %02x, y = %02x", x_val, y_val);
c_interface_print(1, 22, 0, temp);
video_sync(0);
}
c_interface_redo_bottom();
video_sync(0);
int x_plot = CALIBRATE_TURTLE_X0 + (int)(x_val * CALIBRATE_TURTLE_STEP_X);
int y_plot = CALIBRATE_TURTLE_Y0 + (int)(y_val * CALIBRATE_TURTLE_STEP_Y);
joymenu[y_last][x_last] = ' ';
joymenu[y_plot][x_plot] = spinney[spinney_idx];
x_last = x_plot;
y_last = y_plot;
SHOW_BUTTONS(joymenu, CALIBRATE_JOYMENU_H);
SHOW_JOYSTICK_AXES(joymenu, CALIBRATE_JOYMENU_W, CALIBRATE_JOYMENU_H, x_val, y_val);
video_sync(0);
spinney_idx = (spinney_idx+1) % 4;
if (!js.buttons)
{
finished_press = true;
}
if (finished_press && (long_press > LONG_PRESS_THRESHOLD))
{
break;
}
}
}
#endif // PC_JOYSTICK