forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[PSP] libctrl

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> Patch Submissions
View previous topic :: View next topic  
Author Message
lego



Joined: 17 Oct 2008
Posts: 43

PostPosted: Sat Oct 03, 2009 5:15 am    Post subject: [PSP] libctrl Reply with quote

Hi.

This is a wrapper library for the pspctrl one. May be it will be useful.

Code:

diff -ru -N -x '.git*' tmp/libctrl.c libctrl/libctrl.c
--- tmp/libctrl.c       1970-01-01 03:00:00.000000000 +0300
+++ libctrl/libctrl.c   2009-10-02 22:54:43.000000000 +0400
@@ -0,0 +1,594 @@
+/*
+ *  libctrl - A wrapper for the pspctrl lib
+ *  Version 1.0.1
+ *  Copyright (C) 2009 Lego_12239 aka Oleg Nemanov
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <pspkernel.h>
+#include <pspdebug.h>
+#include <pspctrl.h>
+#include <pspdisplay.h>
+#include <psprtc.h>
+#include "libctrl.h"
+
+
+#define printf pspDebugScreenPrintf
+
+
+#define CTRL_KEY_COUNT 10
+
+static ctrl_key_t ctrl_key[CTRL_KEY_COUNT];
+static ctrl_jstick_t ctrl_jstick;
+
+/* For an efficient memory allocation time usage this variable is global.*/
+static pspTime ctrl_key_time;
+
+static int ctrl_events_queue_len = 16;
+static ctrl_event_t *ctrl_events_queue;
+/* Pointers to the last event and the first event in the events queue. */
+static ctrl_event_t *ctrl_events_queue_le, *ctrl_events_queue_fe;
+static SceUID ctrl_key_event_mutex;
+
+
+/*
+ * Lock a mutex.
+ * Return 0 if error or 1 otherwise.
+ */
+inline static int lock_mutex(SceUID mutex)
+{
+  if ( sceKernelWaitSema(mutex, 1, 0) < 0 )
+    return 0;
+  else
+    return 1;
+}
+
+/*
+ * Unlock a mutex.
+ * Return 0 if error or 1 otherwise.
+ */
+inline static int unlock_mutex(SceUID mutex)
+{
+  if ( sceKernelSignalSema(mutex, 1) < 0 )
+    return 0;
+  else
+    return 1;
+}
+
+/*
+ * Create the events queue.
+ * Return 0 if error or 1 otherwise.
+ */
+static int create_events_queue(void)
+{
+  int i;
+
+
+  ctrl_events_queue = (ctrl_event_t*)malloc(ctrl_events_queue_len *
+                                           sizeof(ctrl_event_t));
+  if ( !ctrl_events_queue )
+    return 0;
+
+  ctrl_events_queue_fe = ctrl_events_queue_le = ctrl_events_queue;
+
+  for(i = 0; i < ctrl_events_queue_len; i++) {
+    ctrl_events_queue[i].event = EMPTY;
+  }
+
+  return 1;
+}
+
+/*
+ * Change an events queue length.
+ * All events existing in the queue are deleted.
+ * A smaller events queue give a smaller latency.
+ * Return 0 if an error has occured during the create_events_queue()
+ * call (Not enough memory for a queue) or the lock_mutex() call or
+ * unlock_mutex().
+ */
+int ctrl_set_eq_len(size_t len)
+{
+  int ret;
+
+
+  if ( ! lock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  /* Delete old events queue. */
+  free(ctrl_events_queue);
+
+  /* Create new events queue. */
+  /* Cann't create a zero-length queue. */
+  if ( ! len ) len++;
+  ctrl_events_queue_len = len;
+  ret = create_events_queue();
+
+  if ( ! unlock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  return ret;
+}
+
+/*
+ * Clear an all events.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+int ctrl_clear_events(void)
+{
+  int i;
+
+  if ( ! lock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  for(i = 0; i < ctrl_events_queue_len; i++) {
+    ctrl_events_queue[i].event = EMPTY;
+  }
+
+  ctrl_events_queue_fe = ctrl_events_queue_le = ctrl_events_queue;
+
+  if ( ! unlock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  return 1;
+}
+
+/*
+ * Set key mode.
+ */
+void ctrl_set_key_mode(ctrl_key_code_t key_code, ctrl_mode_t mode)
+{
+  if (( key_code < 0 ) || ( key_code > CTRL_KEY_CODE_MAX )) return;
+
+  ctrl_key[key_code].mode = mode;
+}
+
+/*
+ * Get a key mode.
+ */
+ctrl_mode_t ctrl_get_key_mode(ctrl_key_code_t key_code)
+{
+  if (( key_code < 0 ) || ( key_code > CTRL_KEY_CODE_MAX )) return -1;
+
+  return ctrl_key[key_code].mode;
+}
+
+/*
+ * Set key repeat start time.
+ * rep_start_time is a time in seconds since key is pressed when
+ * repeating start.
+ */
+void ctrl_set_key_repstart(ctrl_key_code_t key_code,
+                         unsigned int rep_start_time)
+{
+  if (( key_code < 0 ) || ( key_code > CTRL_KEY_CODE_MAX )) return;
+
+  ctrl_key[key_code].repeat_start = rep_start_time;
+}
+
+/*
+ * Set key repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen PRESSED events
+ * while key is pressed.
+ */
+void ctrl_set_key_repinterval(ctrl_key_code_t key_code,
+                            unsigned int rep_interval)
+{
+  if (( key_code < 0 ) || ( key_code > CTRL_KEY_CODE_MAX )) return;
+
+  ctrl_key[key_code].repeat_interval = rep_interval;
+}
+
+/*
+ * Set joystick axes zero ranges.
+ * If an axis changes within this range, it interpretes like the zero value.
+ */
+void ctrl_set_jstick_zerorange(unsigned char x_zero_range,
+                              unsigned char y_zero_range)
+{
+  ctrl_jstick.axis_x.zero_range = x_zero_range;
+  ctrl_jstick.axis_y.zero_range = y_zero_range;
+}
+
+/*
+ * Get values of axes zero ranges.
+ */
+void ctrl_get_jstick_zerorange(unsigned char *x_zero_range,
+                              unsigned char *y_zero_range)
+{
+  *x_zero_range = ctrl_jstick.axis_x.zero_range;
+  *y_zero_range = ctrl_jstick.axis_y.zero_range;
+}
+
+/*
+ * Set joystick axes coordinates step.
+ * For example, if x_coord_step is 1, than x axis can be from -128 to 127;
+ * if x_coord_step is 10, than x axis can be from -12 to 12.
+ */
+void ctrl_set_jstick_coordstep(unsigned char x_coord_step,
+                              unsigned char y_coord_step)
+{
+  if ( !x_coord_step ) x_coord_step++;
+  if ( !y_coord_step ) y_coord_step++;
+
+  ctrl_jstick.axis_x.coord_step = x_coord_step;
+  ctrl_jstick.axis_y.coord_step = y_coord_step;
+}
+
+/*
+ * Get joystick axes coordinates step.
+ */
+void ctrl_get_jstick_coordstep(unsigned char *x_coord_step,
+                              unsigned char *y_coord_step)
+{
+  *x_coord_step = ctrl_jstick.axis_x.coord_step;
+  *y_coord_step = ctrl_jstick.axis_y.coord_step;
+}
+
+/*
+ * Return a count of coordinates taking into account a current coord_step.
+ */
+void ctrl_get_jstick_coordcount(unsigned char *x_count, unsigned char *y_count)
+{
+  *x_count = 128 / ctrl_jstick.axis_x.coord_step;
+  *y_count = 128 / ctrl_jstick.axis_y.coord_step;
+}
+
+/*
+ * Set joystick mode.
+ */
+void ctrl_set_jstick_mode(ctrl_mode_t mode)
+{
+  ctrl_jstick.mode = mode;
+}
+
+/*
+ * Set joystick repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen JOYSTICK events
+ * while key is pressed.
+ */
+void ctrl_set_jstick_repinterval(unsigned int rep_interval)
+{
+  ctrl_jstick.repeat_interval = rep_interval;
+}
+
+/*
+ * Push an event into the queue.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+static int ctrl_events_queue_pushe(ctrl_event_type_t event, unsigned int key,
+                                   char axis_x, char axis_y)
+{
+  ctrl_event_t *tmp = ctrl_events_queue_le;
+
+
+  if ( ! lock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  if ( ctrl_events_queue_le->event != EMPTY ) {
+    if ( tmp == &ctrl_events_queue[ctrl_events_queue_len - 1] )
+      tmp = ctrl_events_queue;
+    else
+      tmp = ctrl_events_queue_le + 1;
+
+    if ( tmp == ctrl_events_queue_fe ) {
+      if ( ! unlock_mutex(ctrl_key_event_mutex) ) return 0;
+      return 1;
+    }
+    ctrl_events_queue_le = tmp;
+  }
+
+  ctrl_events_queue_le->event = event;
+  ctrl_events_queue_le->key = key;
+  ctrl_events_queue_le->jstick_x = axis_x;
+  ctrl_events_queue_le->jstick_y = axis_y;
+
+  if ( ! unlock_mutex(ctrl_key_event_mutex) ) return 0;
+
+  return 1;
+}
+
+/*
+ * Return 1 if some event is poped.
+ * Return 0 if there is no event to pop.
+ * Return -1 if a mutex error occured.
+ */
+static int ctrl_events_queue_pope(ctrl_event_t *const event)
+{
+  if ( ! lock_mutex(ctrl_key_event_mutex) ) return -1;
+
+  if ( ctrl_events_queue_fe->event == EMPTY ) {
+    event->event = EMPTY;
+    if ( ! unlock_mutex(ctrl_key_event_mutex) ) return -1;
+    return 0;
+  }
+
+  event->event = ctrl_events_queue_fe->event;
+  event->key = ctrl_events_queue_fe->key;
+  event->jstick_x = ctrl_events_queue_fe->jstick_x;
+  event->jstick_y = ctrl_events_queue_fe->jstick_y;
+  ctrl_events_queue_fe->event = EMPTY;
+
+  if ( ctrl_events_queue_fe == ctrl_events_queue_le ) {
+    if ( ! unlock_mutex(ctrl_key_event_mutex) ) return -1;
+    return 1;
+  }

+  if ( ctrl_events_queue_fe == &ctrl_events_queue[ctrl_events_queue_len - 1] )
+    ctrl_events_queue_fe = ctrl_events_queue;
+  else
+    ctrl_events_queue_fe++;
+
+  if ( ! unlock_mutex(ctrl_key_event_mutex) ) return -1;
+  return 1;
+}
+
+/*
+ * Nonblocking function.
+ * It check if any button is pressed.
+ * If any button is pressed return 1 and fill the key structure with
+ * apropriate values or return 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+inline int ctrl_pollevent(ctrl_event_t *const event)
+{
+  return ctrl_events_queue_pope(event);
+}
+
+/*
+ * Blocking function.
+ * It wait button event and return a pointer to ctrl_key_t structure,
+ * after a key is pressed.
+ * Return -1 if a mutex error occured.
+ */
+int ctrl_waitevent(ctrl_event_t *const event)
+{
+  int caught;
+
+  do {
+    caught = ctrl_events_queue_pope(event);
+    sceDisplayWaitVblankStart();
+  } while (!caught);
+
+  return caught;
+}
+
+/*
+ * Return 1 if pressed, 2 if released, 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+static int process_but(unsigned int key_code, unsigned int is_pressed)
+{
+  ctrl_key_t * key = &ctrl_key[key_code];
+  time_t t;
+  unsigned int decisec;
+
+  if ( ( !is_pressed ) && ( !key->press_time ) ) return 0;
+
+  if ( is_pressed ) {
+    if ( !key->press_time ) {
+      key->press_time = time(NULL);
+      key->last_repeat = 0;
+
+      if ( ! ctrl_events_queue_pushe(PRESSED, key_code, 0, 0) ) return -1;
+
+      return 1;
+    } else {
+      t = time(NULL);
+      sceRtcGetCurrentClockLocalTime(&ctrl_key_time);
+      decisec = (t - key->press_time)*10 +
+       ctrl_key_time.microseconds/100000;
+
+      if ( ( key->mode == REPEAT ) &&
+          ( t - key->press_time >= key->repeat_start ) &&
+          ( decisec - key->last_repeat >= key->repeat_interval) ) {
+       if ( ! ctrl_events_queue_pushe(PRESSED, key_code, 0, 0) ) return -1;
+       key->last_repeat = decisec;
+      }
+
+      return 0;
+    }
+  } else {
+    key->press_time = 0;
+  }
+
+
+  if ( ! ctrl_events_queue_pushe(RELEASED, key_code, 0, 0) ) return -1;
+
+  return 2;
+}
+
+/*
+ * Return 1 if everything is ok.
+ * Return 0 if a mutex error occured.
+ */
+static int process_jstick(unsigned char Lx, unsigned char Ly)
+{
+  char x, y;
+  /* x and y zero half range. */
+  char x_zhr = ctrl_jstick.axis_x.zero_range / 2;
+  char y_zhr = ctrl_jstick.axis_y.zero_range / 2;
+  time_t t;
+  unsigned int decisec_delta;
+
+
+  /* Process the x axis. */
+  x = Lx - 128;
+  /*
+   * If Lx isn't in the zero range, calculate x.
+   * Otherwise, set x to zero.
+   */
+  if ( x < -x_zhr )
+    x = (x + x_zhr) / ctrl_jstick.axis_x.coord_step - 1;
+  else if ( x > x_zhr )
+    x = (x - x_zhr) / ctrl_jstick.axis_x.coord_step + 1;
+  else
+    x = 0;
+
+  /* Process the y axis. */
+  y = Ly - 128;
+  /*
+   * If Ly isn't in the zero range, calculate y.
+   * Otherwise, set y to zero.
+   */
+  if ( y < -y_zhr )
+    y = (y + y_zhr) / ctrl_jstick.axis_y.coord_step - 1;
+  else if ( y > y_zhr )
+    y = (y - y_zhr) / ctrl_jstick.axis_y.coord_step + 1;
+  else
+    y = 0;
+
+
+  /* Make a decision. */
+  /* If nothing has been changed - exit. */
+  if (( x == ctrl_jstick.axis_x.coord ) && ( y == ctrl_jstick.axis_y.coord )) {
+    if ( ctrl_jstick.mode == REPEAT ) {
+      t = time(NULL);
+      sceRtcGetCurrentClockLocalTime(&ctrl_key_time);
+      decisec_delta = (t - ctrl_jstick.changed_time)*10 +
+       ctrl_key_time.microseconds/100000 - ctrl_jstick.last_repeat;
+
+      if ( decisec_delta < ctrl_jstick.repeat_interval )
+       return 1;
+
+      ctrl_jstick.last_repeat += decisec_delta;
+    } else
+      return 1;
+  } else
+    if ( ctrl_jstick.mode == REPEAT ) {
+      ctrl_jstick.changed_time = time(NULL);
+      ctrl_jstick.last_repeat = 0;
+    }
+
+
+  /* Else - place event in the events queue. */
+  if ( ! ctrl_events_queue_pushe(JOYSTICK, 0, x, y) ) return 0;
+
+  ctrl_jstick.axis_x.coord = x;
+  ctrl_jstick.axis_y.coord = y;
+
+  return 1;
+}
+
+/*
+ * Return 1 if everything is ok.
+ * Return 0 if error.
+ */
+static int init_events_queue(void)
+{
+  ctrl_key_event_mutex = sceKernelCreateSema("event_mutex", 0, 1, 1, NULL);
+
+  return create_events_queue();
+}
+
+static void init_keys_array(void)
+{
+  int i;
+
+
+  for(i = 0; i < CTRL_KEY_COUNT; i++) {
+    ctrl_key[i].repeat_start = 1;
+    ctrl_key[i].repeat_interval = 4;
+  }
+
+  ctrl_key[PSP_CTRL_UP_KEY].button       = PSP_CTRL_UP;
+  ctrl_key[PSP_CTRL_RIGHT_KEY].button    = PSP_CTRL_RIGHT;
+  ctrl_key[PSP_CTRL_DOWN_KEY].button     = PSP_CTRL_DOWN;
+  ctrl_key[PSP_CTRL_LEFT_KEY].button     = PSP_CTRL_LEFT;
+  ctrl_key[PSP_CTRL_LTRIGGER_KEY].button = PSP_CTRL_LTRIGGER;
+  ctrl_key[PSP_CTRL_RTRIGGER_KEY].button = PSP_CTRL_RTRIGGER;
+  ctrl_key[PSP_CTRL_TRIANGLE_KEY].button = PSP_CTRL_TRIANGLE;
+  ctrl_key[PSP_CTRL_CIRCLE_KEY].button   = PSP_CTRL_CIRCLE;
+  ctrl_key[PSP_CTRL_CROSS_KEY].button    = PSP_CTRL_CROSS;
+  ctrl_key[PSP_CTRL_SQUARE_KEY].button   = PSP_CTRL_SQUARE;
+}
+
+static void init_jstick(void)
+{
+  sceCtrlSetSamplingMode(1);
+
+  ctrl_jstick.axis_x.coord = 0;
+  ctrl_jstick.axis_x.zero_range = 40;
+  ctrl_jstick.axis_x.coord_step = 10;
+  ctrl_jstick.axis_y.coord = 0;
+  ctrl_jstick.axis_y.zero_range = 40;
+  ctrl_jstick.axis_y.coord_step = 10;
+  ctrl_jstick.mode = NO_REPEAT;
+  ctrl_jstick.changed_time = 0;
+  ctrl_jstick.last_repeat = 0;
+  ctrl_jstick.repeat_interval = 4;
+}
+
+int ctrl_thread(SceSize args, void *argp)
+{
+  SceCtrlData *pad;
+  int i;

+  if ( !(pad = (SceCtrlData*)malloc(sizeof(SceCtrlData))) )
+    sceKernelExitThread(1);
+
+  /* Initialize the events queue. */
+  init_events_queue();
+
+  /* Initialize the ctrl_key array. */
+  init_keys_array();
+
+  /* Initialize the joystick related things. */
+  init_jstick();
+
+  /* Do a work. */
+  while (1) {
+    sceDisplayWaitVblankStart();
+
+    sceCtrlReadBufferPositive(pad, 1);
+
+    for(i = 0; i < CTRL_KEY_COUNT; i++) {
+      process_but(i, pad->Buttons & ctrl_key[i].button);
+    }
+    process_jstick(pad->Lx, pad->Ly);
+  }
+
+  free(pad);
+
+  return 0;
+}
+
+/*
+ * Init a ctrl thread. Must be called before calling any of the ctrl
+ * functions.
+ * Return an error code or 0 if evething is ok.
+ * ctrl thread id is returned through *thid. If an error occured
+ * *thid is undefined.
+ */
+int init_ctrl_thread(SceUID *thid)
+{
+  SceUID ctrl_thid;
+
+
+  ctrl_thid = sceKernelCreateThread("ctrl_thread", ctrl_thread, 0x10, 16384,
+                                 0, NULL);
+  if ( ctrl_thid < 0 )
+    return ctrl_thid;
+
+  sceKernelStartThread(ctrl_thid, 0, NULL);
+  /* Give ctrl_thread() a time to initialize needed variables. */
+  sceKernelDelayThread(10000);
+
+  /* If ctrl_thread() do sceKernelExitThread() return the error code 1. */
+  if ( sceKernelGetThreadExitStatus(ctrl_thid) != 0x800201a4 )
+    return 1;
+
+  *thid = ctrl_thid;
+
+  return 0;
+}
diff -ru -N -x '.git*' tmp/libctrl.h libctrl/libctrl.h
--- tmp/libctrl.h       1970-01-01 03:00:00.000000000 +0300
+++ libctrl/libctrl.h   2009-10-02 22:54:40.000000000 +0400
@@ -0,0 +1,212 @@
+/*
+ *  libctrl - A wrapper for the pspctrl lib
+ *  Version 1.0.1
+ *  Copyright (C) 2009 Lego_12239 aka Oleg Nemanov
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __LIBCTRL_H_
+#define __LIBCTRL_H_
+
+
+#define CTRL_KEY_CODE_MAX 9
+
+/* Key to array index mappings. */
+typedef enum ctrl_key_code_t {
+  PSP_CTRL_UP_KEY = 0,
+  PSP_CTRL_RIGHT_KEY = 1,
+  PSP_CTRL_DOWN_KEY = 2,
+  PSP_CTRL_LEFT_KEY = 3,
+  PSP_CTRL_LTRIGGER_KEY = 4,
+  PSP_CTRL_RTRIGGER_KEY = 5,
+  PSP_CTRL_TRIANGLE_KEY = 6,
+  PSP_CTRL_CIRCLE_KEY = 7,
+  PSP_CTRL_CROSS_KEY = 8,
+  PSP_CTRL_SQUARE_KEY = CTRL_KEY_CODE_MAX
+} ctrl_key_code_t;
+
+typedef enum ctrl_event_type_t {
+    EMPTY,
+    PRESSED,
+    RELEASED,
+    JOYSTICK
+} ctrl_event_type_t;
+
+typedef struct ctrl_event_t {
+  /* Key codes. Like a PSP_CTRL_UP_KEY. */
+  ctrl_key_code_t key;
+  char jstick_x;
+  char jstick_y;
+  ctrl_event_type_t event;
+} ctrl_event_t;
+
+typedef enum ctrl_mode_t {
+  NO_REPEAT,
+  REPEAT
+} ctrl_mode_t;
+
+typedef struct ctrl_key_t {
+  /* PSP button codes. Like a PSP_CTRL_UP. */
+  unsigned int button;
+  /* Last press time. Must be 0 when initialized.*/
+  time_t press_time;
+  /* Last repeat time in deciseconds since press_time. */
+  unsigned int last_repeat;
+  /* Repeat start time in seconds since press_time. Default: 1.*/
+  unsigned int repeat_start;
+  /* Repeat interval in deciseconds. Default: 4. */
+  unsigned int repeat_interval;
+  /* Repeat or no repeat. */
+  ctrl_mode_t mode;
+  SceUID mutex;
+} ctrl_key_t;
+
+typedef struct ctrl_jstick_axis_t {
+  /* Axis value. */
+  char coord;
+  /* Zero range value. Default: 40.*/
+  unsigned char zero_range;
+  /* Axis values step. Default: 10.*/
+  unsigned char coord_step;
+} ctrl_jstick_axis_t;
+
+typedef struct ctrl_jstick_t {
+  /* Axes. */
+  ctrl_jstick_axis_t axis_x;
+  ctrl_jstick_axis_t axis_y;
+  /* Last change time. Must be 0 when initialized.*/
+  time_t changed_time;
+  /* Last repeat time in deciseconds since press_time. */
+  unsigned int last_repeat;
+  /* Repeat interval in deciseconds. Default: 4. */
+  unsigned int repeat_interval;
+  /* Repeat or no repeat. */
+  ctrl_mode_t mode;
+} ctrl_jstick_t;
+
+
+/*
+ * Change an events queue length by a queue recreating.
+ * All events existing in the queue and queue by itself are deleted.
+ * A smaller events queue give a smaller latency.
+ * Return 0 if an error has occured (May be not enough memory for
+ * a new queue or a mutex error occured). By default the queue len is 16.
+ */
+int ctrl_set_eq_len(size_t len);
+
+/*
+ * Clear an all events.
+ * Return 0 if a mutex error occured or 1 otherwise.
+ */
+int ctrl_clear_events(void);
+
+/*
+ * Set key mode
+ */
+void ctrl_set_key_mode(ctrl_key_code_t key_code, ctrl_mode_t mode);
+
+/*
+ * Get a key mode.
+ */
+ctrl_mode_t ctrl_get_key_mode(ctrl_key_code_t key_code);
+
+/*
+ * Set key repeat start time.
+ * rep_start_time is a time in seconds since key is pressed when
+ * repeating start.
+ */
+void ctrl_set_key_repstart(ctrl_key_code_t key_code,
+                         unsigned int rep_start_time);
+
+/*
+ * Set key repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen PRESSED events
+ * until key is pressed.
+ */
+void ctrl_set_key_repinterval(ctrl_key_code_t key_code,
+                            unsigned int rep_interval);
+
+/*
+ * Set a joystick axis zero range.
+ * If an axis changes within this range, it interpretes like the zero value.
+ */
+void ctrl_set_jstick_zerorange(unsigned char x_zero_range,
+                              unsigned char y_zero_range);
+
+/*
+ * Get values of axes zero ranges.
+ */
+void ctrl_get_jstick_zerorange(unsigned char *x_zero_range,
+                              unsigned char *y_zero_range);
+
+/*
+ * Set joystick axes values step.
+ * For example, if x_coord_step is 1, than x axis can be from -128 to 127;
+ * if x_coord_step is 10, than x axis can be from -12 to 12.
+ */
+void ctrl_set_jstick_coordstep(unsigned char x_coord_step,
+                              unsigned char y_coord_step);
+
+/*
+ * Return a count of coordinates taking into account a current coord_step.
+ */
+void ctrl_get_jstick_coordcount(unsigned char *x_count,
+                               unsigned char *y_count);
+
+/*
+ * Set joystick mode.
+ */
+void ctrl_set_jstick_mode(ctrl_mode_t mode);
+
+/*
+ * Set joystick repeat interval.
+ * rep_interval is a time interval in deciseconds beetwen JOYSTICK events
+ * while key is pressed.
+ */
+void ctrl_set_jstick_repinterval(unsigned int rep_interval);
+
+/*
+ * Nonblocking function.
+ * It check if any button is pressed.
+ * If any button is pressed return 1 and fill the key structure with
+ * apropriate values or return 0 otherwise.
+ * Return -1 if a mutex error occured.
+ */
+inline int ctrl_pollevent(ctrl_event_t *key);
+
+/*
+ * Blocking function.
+ * It wait button event and fill with values the key structure
+ * after a key is pressed and return.
+ * User must free it by himself.
+ * Return -1 if a mutex error occured.
+ */
+int ctrl_waitevent(ctrl_event_t *key);
+
+int ctrl_thread(SceSize args, void *argp);
+
+/*
+ * Init a ctrl thread. Must be called before calling any of the ctrl
+ * functions.
+ * Return an error code or 0 if evething is ok.
+ * ctrl thread id is returned through *thid. If an error occured
+ * *thid is undefined.
+ */
+int init_ctrl_thread(SceUID *thid);
+
+
+#endif /* __LIBCTRL_H__ */
diff -ru -N -x '.git*' tmp/Makefile libctrl/Makefile
--- tmp/Makefile        1970-01-01 03:00:00.000000000 +0300
+++ libctrl/Makefile    2009-03-26 21:46:48.000000000 +0300
@@ -0,0 +1,30 @@
+TARGET_LIB = libctrl.a
+OBJS = libctrl.o
+
+INCDIR =
+CFLAGS = -O2 -G0 -Wall
+CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
+ASFLAGS = $(CFLAGS)
+
+LIBDIR =
+LDFLAGS =
+
+PSPSDK=$(shell psp-config --pspsdk-path)
+PSP_PREF=$(shell psp-config --psp-prefix)
+
+include $(PSPSDK)/lib/build.mak
+
+
+myclean:
+       rm -f *~
+
+install: all
+       install -m644 $(TARGET_LIB) $(PSP_PREF)/lib
+       install -m644 $(patsubst %.a,%.h,$(TARGET_LIB)) $(PSP_PREF)/include
+
+uninstall:
+       rm -f $(PSP_PREF)/lib/$(TARGET_LIB)
+       rm -f $(PSP_PREF)/include/$(patsubst %.a,%.h,$(TARGET_LIB))
+
+tags:
+       etags --members --typedefs $(patsubst %.o,%.c,$(OBJS))
Back to top
View user's profile Send private message
lego



Joined: 17 Oct 2008
Posts: 43

PostPosted: Sat Oct 03, 2009 5:19 am    Post subject: Reply with quote

Some demonstration program:

ctrldemo.c:
Code:

/* 68x34 480x272 */
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <libctrl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>


PSP_MODULE_INFO("libctrl demo", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);

#define printf pspDebugScreenPrintf


#define WORD_INTERVAL 7
#define MAX_X 417 // 480 - word_count*WORD_INTERVAL
#define MAX_Y 262 // 272 - 10

/* coordinate settings */
int x = 0;
int oldx = 0;
int y = 9;
int oldy = 9;
int dx = 1;
int dy = 1;
SceUID dx_mutex, dy_mutex;
int color = 0x11ffe6;

char autochange = 1;

int delay = 30000;

char pressed = 0;


/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
  sceKernelExitGame();
  return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
  int cbid;

  cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
  sceKernelRegisterExitCallback(cbid);

  sceKernelSleepThreadCB();

  return 0;

}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
  int thid = 0;

  thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
  if(thid >= 0) {
    sceKernelStartThread(thid, 0, 0);
  }

  return thid;
}

void print_word(int x, int y, int color, char const *const str)
{
  char *i;

  if ( !str ) return;

  i = (char*)str;

  while ( *i ) {
    pspDebugScreenPutChar(x, y, color, *i);

    x += WORD_INTERVAL;
    i++;
  }
}

int draw_thread(SceSize args, void *argp)
{
  while (1) {
    print_word(oldx, oldy, color, "      ");
    print_word(x, y, color, "Hello!");

    oldx = x;
    oldy = y;
    x += dx;
    y += dy;
    if ( ( x > MAX_X ) || ( x < 1 ) ) {
      sceKernelWaitSema(dx_mutex, 1, 0);
      dx = -dx;
      sceKernelSignalSema(dx_mutex, 1);
    }
    if ( ( y > MAX_Y ) || ( y < 1 ) ) {
      sceKernelWaitSema(dy_mutex, 1, 0);
      dy = -dy;
      sceKernelSignalSema(dy_mutex, 1);
    }
    x = oldx + dx;
    y = oldy + dy;
   
    if ( autochange ) color += 1000;
    if ( color > 0xFFFFFF ) color = 1;

    sceKernelDelayThread(delay);
  }

  return 0;
}

int main()
{
  SceUID ctrl_thid, draw_thid;
  ctrl_event_t *ctrl_event;


  pspDebugScreenInit();
  SetupCallbacks();


  pspDebugScreenSetXY(40,20);

  pspDebugScreenSetTextColor(0x11ffe6);


  /* Create mutexes */
  dx_mutex = sceKernelCreateSema("dx_mutex", 0, 1, 1, NULL);
  dy_mutex = sceKernelCreateSema("dy_mutex", 0, 1, 1, NULL);

  /* threads */
  ctrl_thid = sceKernelCreateThread("ctrl_thread", ctrl_thread, 0x10, 16384,
                               0, NULL);
  if ( ctrl_thid < 0 ) {
    printf("Thread error");
    return 1;
  }
  sceKernelStartThread(ctrl_thid, 0, NULL);
  /* Time to safeguard against ctrl_thread() initialization isn't finished. */
  sceKernelDelayThread(100000);

  draw_thid = sceKernelCreateThread("draw_thread", draw_thread, 0x10, 16384,
                               0, NULL);
  if ( draw_thid < 0 ) {
    printf("Thread error");
    return 1;
  }
  sceKernelStartThread(draw_thid, 0, NULL);

  /* Some settings */
  ctrl_set_key_mode(PSP_CTRL_UP_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_UP_KEY, 0);
  ctrl_set_key_mode(PSP_CTRL_DOWN_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_DOWN_KEY, 0);
  ctrl_set_key_mode(PSP_CTRL_LEFT_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_LEFT_KEY, 0);
  ctrl_set_key_mode(PSP_CTRL_RIGHT_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_RIGHT_KEY, 0);
  ctrl_set_key_mode(PSP_CTRL_LTRIGGER_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_LTRIGGER_KEY, 0);
  ctrl_set_key_mode(PSP_CTRL_RTRIGGER_KEY, REPEAT);
  ctrl_set_key_repstart(PSP_CTRL_RTRIGGER_KEY, 0);
  ctrl_set_jstick_coordstep(50, 50);
  ctrl_set_jstick_mode(REPEAT);


  ctrl_event = (ctrl_event_t*)malloc(sizeof(ctrl_event_t));

  while (1) {
    pspDebugScreenSetTextColor(0x663333);

    pspDebugScreenSetXY(1,1);
    printf("                                                  ");
    pspDebugScreenSetXY(1,1);
    printf("delay - %d, color - %x", delay, color);

    ctrl_pollevent(ctrl_event);

    if ( ctrl_event->event == PRESSED )
      switch (ctrl_event->key) {
      case PSP_CTRL_UP_KEY:
        sceKernelWaitSema(dy_mutex, 1, 0);
        if ( dy > -5 ) dy--;
        sceKernelSignalSema(dy_mutex, 1);
        break;
      case PSP_CTRL_DOWN_KEY:
        sceKernelWaitSema(dy_mutex, 1, 0);
        if ( dy < 5 ) dy++;
        sceKernelSignalSema(dy_mutex, 1);
        break;
      case PSP_CTRL_LEFT_KEY:
        sceKernelWaitSema(dx_mutex, 1, 0);
        if ( dx > -5 ) dx--;
        sceKernelSignalSema(dx_mutex, 1);
        break;
      case PSP_CTRL_RIGHT_KEY:
        sceKernelWaitSema(dx_mutex, 1, 0);
        if ( dx < 5 ) dx++;
        sceKernelSignalSema(dx_mutex, 1);
        break;
      case PSP_CTRL_LTRIGGER_KEY:
        if ( delay < 2000000 ) delay += 2000;
        break;
      case PSP_CTRL_RTRIGGER_KEY:
        if ( delay > 10000 ) delay -= 2000;
        break;
      default:
        break;
      }

    if ( ctrl_event->event == JOYSTICK ) {
      dy += ctrl_event->jstick_y;
      if ( dy <= -5 ) dy = -5;
      if ( dy >= 5 ) dy = 5;

      dx += ctrl_event->jstick_x;
      if ( dx <= -5 ) dx = -5;
      if ( dx >= 5 ) dx = 5;
    }

    sceDisplayWaitVblankStart();
  }

  sceKernelExitGame();
  return 0;
}


Makefile:
Code:

TARGET = ctrldemo.c
OBJS = ctrldemo.o

PSPSDK = $(PSPDEV)/psp/sdk
CFLAGS = -O2 -G0 -Wall
LIBS = -lctrl -lpsprtc
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

BUILD_PRX = 1
PSP_FW_VERSION = 500

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = libctrl demo

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

install:
        mount /media/usbflash
        mkdir -p /media/usbflash/psp/game5xx/ctrldemo || true
        cp EBOOT.PBP /media/usbflash/psp/game5xx/ctrldemo
        umount /media/usbflash
Back to top
View user's profile Send private message
lego



Joined: 17 Oct 2008
Posts: 43

PostPosted: Sat Oct 03, 2009 6:06 am    Post subject: Reply with quote

I have a strange idea. May be I will add a callback mechanism to the library.
Back to top
View user's profile Send private message
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Fri Oct 09, 2009 2:30 pm    Post subject: Reply with quote

I committed both the library and demo in rev 2474, thanks.
Code:
$ svn commit
Adding         libctrl
Adding         libctrl/Makefile
Adding         libctrl/demo
Adding         libctrl/demo/Makefile
Adding         libctrl/demo/ctrldemo.c
Adding         libctrl/libctrl.c
Adding         libctrl/libctrl.h
Transmitting file data .....
Committed revision 2474.

http://svn.ps2dev.org/listing.php?repname=psp&path=%2F&rev=2474&sc=1

ps. Having the inline patches here for viewing is nice, but it's hard to apply them (the forum mangles the format). For future patches, if you could also send a link to the patch somewhere, that would make things easier for us.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> Patch Submissions All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group