apps/graphics/pdcurses: Add support for discrete joystick input. This is sufficient to get through all menuing tests that do not require text input.

This commit is contained in:
Gregory Nutt 2017-11-20 14:17:45 -06:00
parent 6eae5e0c4c
commit b346d1d6eb
6 changed files with 416 additions and 117 deletions

View File

@ -150,3 +150,35 @@ config PDCURSES_BGCOLOR_BLUE
depends on !PDCURSES_MONO
endmenu # Initial Screen Color
config PDCURSES_HAVE_INPUT
bool
default n
menu "Input Devices"
config PDCURSES_DJOYSTICK
bool "Discrete Joystick"
default n
select PDCURSES_HAVE_INPUT
depends on DJOYSTICK && !DISABLE_POLL
config PDCURSES_DJOYDEV
string "Discrete Joystick Device"
default "/dev/djoy0"
depends on PDCURSES_DJOYSTICK
config PDCURSES_KEYBOARD
bool "Discrete Joystick"
default n
select PDCURSES_HAVE_INPUT
depends on USBHOST_HIDKBD && !DISABLE_POLL && EXPERIMENTAL
config PDCURSES_MOUSE
bool "Discrete Joystick"
default n
select PDCURSES_HAVE_INPUT
depends on MOUSE && !DISABLE_POLL && EXPERIMENTAL
endmenu # Input Devices

View File

@ -257,7 +257,7 @@ static void PDC_update(FAR struct pdc_fbstate_s *fbstate, int row, int col,
/* Then perfom the update via IOCTL */
ret = ioctl(fbstate->fd, FBIO_UPDATE,
ret = ioctl(fbstate->fbfd, FBIO_UPDATE,
(unsigned long)((uintptr_t)rect));
if (ret < 0)
{
@ -450,3 +450,57 @@ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
PDC_update(fbstate, lineno, x, nextx - x);
}
/****************************************************************************
* Name: PDC_clear_screen
*
* Description:
* Set the framebuffer content to a single color
*
****************************************************************************/
void PDC_clear_screen(FAR struct pdc_fbstate_s *fbstate)
{
FAR uint8_t *line;
FAR pdc_color_t *dest;
int row;
int col;
#ifdef CONFIG_LCD_UPDATE
struct nxgl_rect_s rect;
int ret;
#endif
/* Write the intial color into the entire framebuffer */
for (row = 0, line = (FAR uint8_t *)fbstate->fbmem;
row < fbstate->yres;
row++, line += fbstate->stride)
{
for (col = 0, dest = (FAR pdc_color_t *)line;
col < fbstate->xres;
col++)
{
*dest++ = PDCURSES_INIT_COLOR;
}
}
#ifdef CONFIG_LCD_UPDATE
/* Update the entire display */
/* Setup the bounding rectangle */
rect.pt1.x = 0;
rect.pt1.y = 0;
rect.pt2.x = fbstate->xres - 1;
rect.pt2.y = fbstate->yres - 1;
/* Then perfom the update via IOCTL */
ret = ioctl(fbstate->fbfd, FBIO_UPDATE, (unsigned long)((uintptr_t)rect));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIO_UPDATE) failed: %d\n", errno));
}
#endif
}

View File

@ -43,6 +43,29 @@
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: PDC_get_rows
*
* Description:
* Returns the size of the screen in rows. It's used in resize_term() to
* set the new value of LINES. (Some existing implementations also call it
* internally from PDC_scr_open(), but this is not required.)
*
****************************************************************************/
int PDC_get_rows(void)
{
FAR struct pdc_fbscreen_s *fbscreen = (FAR struct pdc_fbscreen_s *)SP;
FAR struct pdc_fbstate_s *fbstate;
PDC_LOG(("PDC_get_rows() - called\n"));
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
return fbstate->yres / fbstate->fheight;
}
/****************************************************************************
* Name: PDC_get_columns
*
@ -55,9 +78,15 @@
int PDC_get_columns(void)
{
FAR struct pdc_fbscreen_s *fbscreen = (FAR struct pdc_fbscreen_s *)SP;
FAR struct pdc_fbstate_s *fbstate;
PDC_LOG(("PDC_get_columns() - called\n"));
#warning Missing logic
return ERR;
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
return fbstate->xres / fbstate->fwidth;
}
/****************************************************************************
@ -74,23 +103,6 @@ int PDC_get_columns(void)
int PDC_get_cursor_mode(void)
{
#warning Missing logic
return ERR;
}
/****************************************************************************
* Name: PDC_get_rows
*
* Description:
* Returns the size of the screen in rows. It's used in resize_term() to
* set the new value of LINES. (Some existing implementations also call it
* internally from PDC_scr_open(), but this is not required.)
*
****************************************************************************/
int PDC_get_rows(void)
{
PDC_LOG(("PDC_get_rows() - called\n"));
#warning Missing logic
return ERR;
PDC_LOG(("PDC_get_cursor_mode() - called\n"));
return 0;
}

View File

@ -37,8 +37,19 @@
* Included Files
****************************************************************************/
#include <fcntl.h>
#include "pdcnuttx.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Currently only this bits are used. Others are simply masked out. */
#define DJOY_BITSET (DJOY_UP_BIT | DJOY_DOWN_BIT | DJOY_LEFT_BIT | \
DJOY_RIGHT_BIT | DJOY_BUTTON_SELECT_BIT)
/****************************************************************************
* Public Data
****************************************************************************/
@ -53,6 +64,44 @@
unsigned long pdc_key_modifiers;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: PDC_djoy_sample
*
* Description:
* Keyboard/mouse event check, called from wgetch(). Returns true if
* there's an event ready to process. This function must be non-blocking.
*
****************************************************************************/
#ifdef CONFIG_PDCURSES_DJOYSTICK
static djoy_buttonset_t PDC_djoy_sample(FAR struct pdc_fbstate_s *fbstate)
{
djoy_buttonset_t sample;
ssize_t nread;
PDC_LOG(("PDC_check_key() - called: DJoystick\n"));
nread = read(fbstate->djfd, &sample, sizeof(djoy_buttonset_t));
if (nread < 0)
{
PDC_LOG(("ERROR: read() failed: %d\n", errno));
return 0;
}
else if (nread != sizeof(djoy_buttonset_t))
{
PDC_LOG(("ERROR: read() unexpected size: %ld vs %d\n",
(long)nread, sizeof(djoy_buttonset_t)));
return 0;
}
return sample & DJOY_BITSET;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -68,8 +117,36 @@ unsigned long pdc_key_modifiers;
bool PDC_check_key(void)
{
#warning Missing logic
#if defined(CONFIG_PDCURSES_KEYBOARD)
# warning Missing logic
return false;
#elif defined(CONFIG_PDCURSES_MOUSE)
# warning Missing logic
return false;
#elif defined(CONFIG_PDCURSES_DJOYSTICK)
{
FAR struct pdc_fbscreen_s *fbscreen = (FAR struct pdc_fbscreen_s *)SP;
FAR struct pdc_fbstate_s *fbstate;
djoy_buttonset_t newset;
PDC_LOG(("PDC_check_key() - called: DJoystick\n"));
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
/* Sample the discrete joystick bits and return true of any of them
* are now in a different state.
*/
newset = PDC_djoy_sample(fbstate);
return (fbstate->djlast ^ newset) != 0;
}
#else
return false;
#endif
}
/****************************************************************************
@ -78,8 +155,8 @@ bool PDC_check_key(void)
* Description:
* Get the next available key, or mouse event (indicated by a return of
* KEY_MOUSE), and remove it from the OS' input queue, if applicable. This
* function is called from wgetch(). This function may be blocking, and
* traditionally is; but it need not be. If a valid key or mouse event
* function is called from wgetch(). This function may be blocking, and
* traditionally is; but it need not be. If a valid key or mouse event
* cannot be returned, for any reason, this function returns -1. Valid keys
* are those that fall within the appropriate character set, or are in the
* list of special keys found in curses.h (KEY_MIN through KEY_MAX). When
@ -97,8 +174,78 @@ bool PDC_check_key(void)
int PDC_get_key(void)
{
#warning Missing logic
return 0;
#if defined(CONFIG_PDCURSES_KEYBOARD)
# warning Missing logic
return false;
#elif defined(CONFIG_PDCURSES_MOUSE)
# warning Missing logic
return false;
#elif defined(CONFIG_PDCURSES_DJOYSTICK)
{
FAR struct pdc_fbscreen_s *fbscreen = (FAR struct pdc_fbscreen_s *)SP;
FAR struct pdc_fbstate_s *fbstate;
djoy_buttonset_t sample;
djoy_buttonset_t newbits;
PDC_LOG(("PDC_get_key() - called: DJoystick\n"));
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
/* Sample the discrete joystick bits, get the bits that have changed
* state, then update the settings for the next time we get here.
*/
sample = PDC_djoy_sample(fbstate);
newbits = sample & (sample ^ fbstate->djlast);
fbstate->djlast = sample;
if (newbits == 0)
{
/* Nothing has changed... we should:
*
* 1) Check for repeat keys. Up, Down, Left and Right should repeat
* at a most rate if held down.
* 2) Otherwise, block, polling for a change in button state. But,
* apparently, we can just return ERR in this case.
*/
return ERR;
}
/* Return a key code for any button that has just been pressed (button
* releases are not reported)
*/
if ((newbits & DJOY_BUTTON_SELECT_BIT) != 0)
{
return '\n';
}
else if ((newbits & DJOY_UP_BIT) != 0)
{
return KEY_UP;
}
else if ((newbits & DJOY_DOWN_BIT) != 0)
{
return KEY_DOWN;
}
else if ((newbits & DJOY_LEFT_BIT) != 0)
{
return KEY_LEFT;
}
else /* if ((newbits & DJOY_RIGHT_BIT) != 0) */
{
return KEY_RIGHT;
}
return ERR;
}
#else
return false;
#endif
}
/****************************************************************************
@ -112,9 +259,34 @@ int PDC_get_key(void)
unsigned long PDC_get_input_fd(void)
{
#ifdef CONFIG_PDCURSES_HAVE_INPUT
FAR struct pdc_fbscreen_s *fbscreen = (FAR struct pdc_fbscreen_s *)SP;
FAR struct pdc_fbstate_s *fbstate;
PDC_LOG(("PDC_get_input_fd() - called\n"));
#warning Missing logic
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
#if defined(CONFIG_PDCURSES_KEYBOARD)
# warning Missing logic
return -1;
#elif defined(CONFIG_PDCURSES_MOUSE)
# warning Missing logic
return -1;
#else /* if defined(CONFIG_PDCURSES_DJOYSTICK) */
return fbstate->djfd;
#endif
#else
PDC_LOG(("PDC_get_input_fd() - called: No input device\n"));
/* No input device */
return -1;
#endif
}
/****************************************************************************
@ -131,7 +303,6 @@ unsigned long PDC_get_input_fd(void)
void PDC_set_keyboard_binary(bool on)
{
PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
#warning Missing logic
}
/****************************************************************************
@ -147,7 +318,14 @@ void PDC_set_keyboard_binary(bool on)
void PDC_flushinp(void)
{
PDC_LOG(("PDC_flushinp() - called\n"));
#warning Missing logic
#ifdef CONFIG_PDCURSES_KEYBOARD
# warning Missing logic
#endif
#ifdef CONFIG_PDCURSES_MOUSE
# warning Missing logic
#endif
}
/****************************************************************************
@ -164,7 +342,9 @@ void PDC_flushinp(void)
int PDC_mouse_set(void)
{
#warning Missing logic
#ifdef CONFIG_PDCURSES_MOUSE
# warning Missing logic
#endif
return OK;
}
@ -180,6 +360,39 @@ int PDC_mouse_set(void)
int PDC_modifiers_set(void)
{
#warning Missing logic
#ifdef CONFIG_PDCURSES_KEYBOARD
# warning Missing logic
#endif
return OK;
}
/****************************************************************************
* Name: PDC_input_open
*
* Description:
* Open and configure any input devices
*
****************************************************************************/
#ifdef CONFIG_PDCURSES_HAVE_INPUT
int PDC_input_open(FAR struct pdc_fbstate_s *fbstate)
{
#ifdef CONFIG_PDCURSES_DJOYSTICK
/* Initialize discrete joystick state. */
fbstate->djlast = 0;
/* Open the djoystick device */
fbstate->djfd = open(CONFIG_PDCURSES_DJOYDEV, O_RDONLY);
if (fbstate->djfd < 0)
{
PDC_LOG(("ERROR: Failed to open %s: %d\n",
CONFIG_PDCURSES_DJOYDEV, errno));
return ERR;
}
#endif
return OK;
}
#endif

View File

@ -44,6 +44,7 @@
#include <stdint.h>
#include "nuttx/input/djoystick.h"
#include "nuttx/nx/nx.h"
#include "nuttx/nx/nxfonts.h"
#include <nuttx/video/fb.h>
@ -211,27 +212,34 @@ struct pdc_fbstate_s
{
/* Framebuffer */
int fd; /* Open framebuffer driver file descriptor */
FAR void *fbmem; /* Start of framebuffer memory */
fb_coord_t xres; /* Horizontal resolution (pixels) */
fb_coord_t yres; /* Vertical resolution (rows) */
fb_coord_t stride; /* Length of a line (bytes) */
int fbfd; /* Open framebuffer driver file descriptor */
FAR void *fbmem; /* Start of framebuffer memory */
fb_coord_t xres; /* Horizontal resolution (pixels) */
fb_coord_t yres; /* Vertical resolution (rows) */
fb_coord_t stride; /* Length of a line (bytes) */
#ifdef CONFIG_PDCURSES_DJOYSTICK
/* Discrete joystick */
int djfd; /* Open discrete joystick driver file descriptor */
djoy_buttonset_t djlast; /* Last sampled joystick state */
#endif
/* Font */
NXHANDLE hfont; /* Handled uses to access selected font */
NXHANDLE hfont; /* Handled uses to access selected font */
#ifdef HAVE_BOLD_FONT
NXHANDLE hbold; /* Handled uses to access bold font */
NXHANDLE hbold; /* Handled uses to access bold font */
#endif
uint8_t fheight; /* Height of the font (rows) */
uint8_t fwidth; /* Width of the font (pixels) */
uint8_t fheight; /* Height of the font (rows) */
uint8_t fwidth; /* Width of the font (pixels) */
/* Drawable area (See also SP->lines and SP->cols) */
fb_coord_t xpos; /* Drawing X position (pixels) */
fb_coord_t ypos; /* Drawing Y position (rows) */
uint8_t hoffset; /* Offset from left of display (pixels) */
uint8_t voffset; /* Offset from top of display (rows) */
fb_coord_t xpos; /* Drawing X position (pixels) */
fb_coord_t ypos; /* Drawing Y position (rows) */
uint8_t hoffset; /* Offset from left of display (pixels) */
uint8_t voffset; /* Offset from top of display (rows) */
/* Colors */
@ -260,6 +268,32 @@ struct pdc_fbscreen_s
EXTERN struct pdc_fbstate_s g_pdc_fbstate;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: PDC_clear_screen
*
* Description:
* Set the framebuffer content to a single color
*
****************************************************************************/
void PDC_clear_screen(FAR struct pdc_fbstate_s *fbstate);
/****************************************************************************
* Name: PDC_input_open
*
* Description:
* Open and configure any input devices
*
****************************************************************************/
#ifdef CONFIG_PDCURSES_HAVE_INPUT
int PDC_input_open(FAR struct pdc_fbstate_s *fbstate);
#endif
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -48,63 +48,6 @@
#include "pdcnuttx.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: PDC_clear_screen
*
* Description:
* Set the framebuffer content to a single color
*
****************************************************************************/
static void PDC_clear_screen(FAR struct pdc_fbstate_s *fbstate)
{
FAR uint8_t *line;
FAR pdc_color_t *dest;
int row;
int col;
#ifdef CONFIG_LCD_UPDATE
struct nxgl_rect_s rect;
int ret;
#endif
/* Write the intial color into the entire framebuffer */
for (row = 0, line = (FAR uint8_t *)fbstate->fbmem;
row < fbstate->yres;
row++, line += fbstate->stride)
{
for (col = 0, dest = (FAR pdc_color_t *)line;
col < fbstate->xres;
col++)
{
*dest++ = PDCURSES_INIT_COLOR;
}
}
#ifdef CONFIG_LCD_UPDATE
/* Update the entire display */
/* Setup the bounding rectangle */
rect.pt1.x = 0;
rect.pt1.y = 0;
rect.pt2.x = fbstate->xres - 1;
rect.pt2.y = fbstate->yres - 1;
/* Then perfom the update via IOCTL */
ret = ioctl(fbstate->fd, FBIO_UPDATE, (unsigned long)((uintptr_t)rect));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIO_UPDATE) failed: %d\n", errno));
}
#endif
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -143,7 +86,7 @@ void PDC_scr_free(void)
DEBUGASSERT(fbscreen != NULL);
fbstate = &fbscreen->fbstate;
close(fbstate->fd);
close(fbstate->fbfd);
free(fbscreen);
SP = NULL;
}
@ -207,8 +150,8 @@ int PDC_scr_open(int argc, char **argv)
/* Open the framebuffer driver */
fbstate->fd = open(CONFIG_PDCURSES_FBDEV, O_RDWR);
if (fbstate->fd < 0)
fbstate->fbfd = open(CONFIG_PDCURSES_FBDEV, O_RDWR);
if (fbstate->fbfd < 0)
{
PDC_LOG(("ERROR: Failed to open %s: %d\n",
CONFIG_PDCURSES_FBDEV, errno));
@ -217,12 +160,12 @@ int PDC_scr_open(int argc, char **argv)
/* Get the characteristics of the framebuffer */
ret = ioctl(fbstate->fd, FBIOGET_VIDEOINFO,
ret = ioctl(fbstate->fbfd, FBIOGET_VIDEOINFO,
(unsigned long)((uintptr_t)&vinfo));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_VIDEOINFO) failed: %d\n", errno));
goto errout_with_fd;
goto errout_with_fbfd;
}
PDC_LOG(("VideoInfo:\n"));
@ -239,7 +182,7 @@ int PDC_scr_open(int argc, char **argv)
if (vinfo.fmt != PDCURSES_COLORFMT)
{
PDC_LOG(("ERROR: color format=%u not supported\n", vinfo.fmt));
goto errout_with_fd;
goto errout_with_fbfd;
}
#ifdef CONFIG_PDCURSES_COLORFMT_Y1
@ -250,12 +193,12 @@ int PDC_scr_open(int argc, char **argv)
/* Get characteristics of the color plane */
ret = ioctl(fbstate->fd, FBIOGET_PLANEINFO,
ret = ioctl(fbstate->fbfd, FBIOGET_PLANEINFO,
(unsigned long)((uintptr_t)&pinfo));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
goto errout_with_fd;
goto errout_with_fbfd;
}
PDC_LOG(("PlaneInfo (plane 0):\n"));
@ -272,7 +215,7 @@ int PDC_scr_open(int argc, char **argv)
if (pinfo.bpp != PDCURSES_BPP)
{
PDC_LOG(("ERROR: bpp=%u not supported\n", pinfo.bpp));
goto errout_with_fd;
goto errout_with_fbfd;
}
/* mmap() the framebuffer.
@ -285,11 +228,11 @@ int PDC_scr_open(int argc, char **argv)
*/
fbstate->fbmem = mmap(NULL, pinfo.fblen, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FILE, fbstate->fd, 0);
MAP_SHARED|MAP_FILE, fbstate->fbfd, 0);
if (fbstate->fbmem == MAP_FAILED)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
goto errout_with_fd;
goto errout_with_fbfd;
}
PDC_LOG(("Mapped FB: %p\n", fbstate->fbmem));
@ -300,7 +243,7 @@ int PDC_scr_open(int argc, char **argv)
if (fbstate->hfont == NULL)
{
PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
goto errout_with_fd;
goto errout_with_fbfd;
}
#ifdef HAVE_BOLD_FONT
@ -346,6 +289,17 @@ int PDC_scr_open(int argc, char **argv)
/* Set the framebuffer to a known state */
PDC_clear_screen(fbstate);
#ifdef CONFIG_PDCURSES_HAVE_INPUT
/* Open and configure any input devices */
ret = PDC_input_open(fbstate);
if (ret == ERR)
{
goto errout_with_boldfont;
}
#endif
return OK;
errout_with_boldfont:
@ -353,9 +307,9 @@ errout_with_boldfont:
errout_with_font:
#endif
errout_with_fd:
close(fbstate->fd);
fbstate->fd = -1;
errout_with_fbfd:
close(fbstate->fbfd);
fbstate->fbfd = -1;
errout_with_sp:
free(SP);