|
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
View previous topic :: View next topic |
Author |
Message |
lego
Joined: 17 Oct 2008 Posts: 43
|
Posted: Sat Oct 03, 2009 5:15 am Post subject: [PSP] libctrl |
|
|
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 |
|
|
lego
Joined: 17 Oct 2008 Posts: 43
|
Posted: Sat Oct 03, 2009 5:19 am Post subject: |
|
|
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 |
|
|
lego
Joined: 17 Oct 2008 Posts: 43
|
Posted: Sat Oct 03, 2009 6:06 am Post subject: |
|
|
I have a strange idea. May be I will add a callback mechanism to the library. |
|
Back to top |
|
|
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Fri Oct 09, 2009 2:30 pm Post subject: |
|
|
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 |
|
|
|
|
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
|