diff options
| author | XaviDCR92 <xavi.dcr@gmail.com> | 2017-07-21 00:09:35 +0200 |
|---|---|---|
| committer | XaviDCR92 <xavi.dcr@gmail.com> | 2017-07-21 00:09:35 +0200 |
| commit | 627de0d81f81ad60d26d782f2425be1e6f5a3dbc (patch) | |
| tree | 91ffa502aa62c03c2fecf28529ebc8c6b20828c5 /Source/Pad.c | |
| download | opensend-627de0d81f81ad60d26d782f2425be1e6f5a3dbc.tar.gz | |
+ First commit. It works painfully slow, but gets the job done. Still lots of room for improvement.
Diffstat (limited to 'Source/Pad.c')
| -rw-r--r-- | Source/Pad.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/Source/Pad.c b/Source/Pad.c new file mode 100644 index 0000000..ef56f08 --- /dev/null +++ b/Source/Pad.c @@ -0,0 +1,530 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "Pad.h" + +/* ************************************* + * Defines + * *************************************/ + +#define PAD_ONE 0 +#define PAD_TWO 1 +#define PAD_CHEAT_TIMEOUT 20 // 2 units * 100 ms/unit = 2000 ms +#define PAD_MAX_CHEATS 16 + +/* ************************************** + * Structs and enums * + * *************************************/ + +enum +{ + + PAD_CROSS_INDEX = 0, + PAD_SQUARE_INDEX, + PAD_TRIANGLE_INDEX, + PAD_CIRCLE_INDEX, + + PAD_DOWN_INDEX, + PAD_LEFT_INDEX, + PAD_UP_INDEX, + PAD_RIGHT_INDEX, + + PAD_L1_INDEX, + PAD_L2_INDEX, + + PAD_R1_INDEX, + PAD_R2_INDEX, + + NUMBER_OF_KEYS + +}; + + +/* ************************************* + * Local Prototypes + * *************************************/ + +static void PadOneVibrationHandler(void); +static void PadTwoVibrationHandler(void); +static void PadCheatHandler(uint8_t n_pad); +static void PadOneCleanCheatArray(void); +static void PadTwoCleanCheatArray(void); +static psx_pad_state PadOneGetState(void); +uint8_t PadGetKeyIndex(unsigned short key); + +/* ************************************* + * Local Variables + * *************************************/ + +// Pad data +static unsigned short pad1; +static unsigned short pad2; + +// Pad data from previous frame +static unsigned short previous_pad1; +static unsigned short previous_pad2; + +// Vibration timers +static uint16_t pad1_vibration_timer; +static uint16_t pad2_vibration_timer; + +// Vibration strenght data (big motor) +static uint8_t pad1_big_vibration_force; +static uint8_t pad2_big_vibration_force; + +// Vibration strenght data (small motor) +static uint8_t pad1_small_vibration_force; +static uint8_t pad2_small_vibration_force; + +// Timers for each key pressed (used for PadXXKeyRepeat() ) +static uint8_t pad1_keys_repeat[NUMBER_OF_KEYS]; +static uint8_t pad2_keys_repeat[NUMBER_OF_KEYS]; + +static unsigned short pad1_last_key_single_pressed; +static unsigned short pad2_last_key_single_pressed; + +// These arrays include last 16 buttons pressed by user and keeps them +// for cheating purposes. They are cleaned if no keys are pressed during +// PAD_CHEAT_TIMEOUT milliseconds. +static unsigned short pad1_cheat_array[CHEAT_ARRAY_SIZE]; +static unsigned short pad2_cheat_array[CHEAT_ARRAY_SIZE]; + +// Pointers to timers which clean padX_cheat_array. +static TYPE_TIMER* pad1_cheat_timer; +static TYPE_TIMER* pad2_cheat_timer; + +static TYPE_CHEAT * cheatsArray[PAD_MAX_CHEATS]; + +psx_pad_state PadOneGetState(void) +{ + psx_pad_state PadOne; + + PSX_PollPad_Fast(PAD_ONE,&PadOne); + + return PadOne; +} + +bool PadOneConnected(void) +{ + psx_pad_state PadOne = PadOneGetState(); + + if(PadOne.status != PAD_STATUS_OK) + { + return false; + } + + return true; +} + +bool PadOneAnyKeyPressed(void) +{ + return (bool)pad1; +} + +bool PadOneDirectionKeyPressed(void) +{ + return ( (PadOneKeyPressed(PAD_UP) == true) + || + (PadOneKeyPressed(PAD_LEFT) == true) + || + (PadOneKeyPressed(PAD_RIGHT) == true) + || + (PadOneKeyPressed(PAD_DOWN) == true) ); +} + +bool PadOneDirectionKeyReleased(void) +{ + return ( (PadOneKeyReleased(PAD_UP) == true) + || + (PadOneKeyReleased(PAD_LEFT) == true) + || + (PadOneKeyReleased(PAD_RIGHT) == true) + || + (PadOneKeyReleased(PAD_DOWN) == true) ); +} + +bool PadTwoDirectionKeyReleased(void) +{ + return ( (PadTwoKeyReleased(PAD_UP) == true) + || + (PadTwoKeyReleased(PAD_LEFT) == true) + || + (PadTwoKeyReleased(PAD_RIGHT) == true) + || + (PadTwoKeyReleased(PAD_DOWN) == true) ); +} + +bool PadTwoDirectionKeyPressed(void) +{ + return ( (PadTwoKeyPressed(PAD_UP) == true) + || + (PadTwoKeyPressed(PAD_LEFT) == true) + || + (PadTwoKeyPressed(PAD_RIGHT) == true) + || + (PadTwoKeyPressed(PAD_DOWN) == true) ); +} + +bool PadTwoAnyKeyPressed(void) +{ + return (bool)pad2; +} + +bool PadOneKeyPressed(unsigned short key) +{ + return (bool)( pad1 & key ); +} + +bool PadTwoKeyPressed(unsigned short key) +{ + return (bool)( pad2 & key ); +} + +bool PadOneKeySinglePress(unsigned short key) +{ + return (bool)( !(previous_pad1 & key) && (pad1 & key) ); +} + +bool PadTwoKeySinglePress(unsigned short key) +{ + return (bool)( !(previous_pad2 & key) && (pad2 & key) ); +} + +bool PadOneKeyRepeat(unsigned short key, uint8_t time) +{ + uint8_t key_index = PadGetKeyIndex(key); + + if(key_index == NUMBER_OF_KEYS) + { + return false; + } + + pad1_keys_repeat[key_index]++; + + if(pad1_keys_repeat[key_index] >= time) + { + pad1_keys_repeat[key_index] = 0; + return true; + } + + return false; +} + +bool PadTwoKeyRepeat(unsigned short key, uint8_t time) +{ + uint8_t key_index = PadGetKeyIndex(key); + + if(key_index == NUMBER_OF_KEYS) + { + return false; + } + + pad2_keys_repeat[key_index]++; + + if(pad2_keys_repeat[key_index] >= time) + { + pad2_keys_repeat[key_index] = 0; + return true; + } + + return false; +} + +void PadOneVibrationHandler(void) +{ + if(PadOneIsVibrationEnabled() == true) + { + pad_enable_vibration(PAD_ONE); + pad_set_vibration(PAD_ONE,pad1_small_vibration_force,pad1_big_vibration_force); + pad1_vibration_timer--; + } +} + +void PadTwoVibrationHandler(void) +{ + if(PadTwoIsVibrationEnabled() == true) + { + pad_enable_vibration(PAD_TWO); + pad_set_vibration(PAD_TWO,pad2_small_vibration_force,pad2_big_vibration_force); + pad2_vibration_timer--; + } +} + +bool PadOneIsVibrationEnabled(void) +{ + return (pad1_vibration_timer & true); +} + +bool PadTwoIsVibrationEnabled(void) +{ + return (pad2_vibration_timer & true); +} + +bool UpdatePads(void) +{ + PadOneVibrationHandler(); + + PadTwoVibrationHandler(); + + PadCheatHandler(PAD_ONE); + + PadCheatHandler(PAD_TWO); + + // Get now-old pad data + previous_pad1 = pad1; + previous_pad2 = pad2; + + PSX_ReadPad(&pad1,&pad2); + + if(PadOneConnected() == false) + { + return false; + } + + if(!(previous_pad1 & pad1) ) + { + pad1_last_key_single_pressed = pad1; + } + else + { + pad1_last_key_single_pressed = 0; + } + + if(!(previous_pad2 & pad2) ) + { + pad2_last_key_single_pressed = pad2; + } + else + { + pad2_last_key_single_pressed = 0; + } + + return true; +} + +bool PadOneKeyReleased(unsigned short key) +{ + return ( !(pad1 & key) && (previous_pad1 & key) ); +} + +bool PadTwoKeyReleased(unsigned short key) +{ + return ( !(pad2 & key) && (previous_pad2 & key) ); +} + +uint8_t PadGetKeyIndex(unsigned short key) +{ + switch(key) + { + case PAD_CROSS: + return PAD_CROSS_INDEX; + break; + + case PAD_SQUARE: + return PAD_SQUARE_INDEX; + break; + + case PAD_TRIANGLE: + return PAD_TRIANGLE_INDEX; + break; + + case PAD_CIRCLE: + return PAD_CIRCLE_INDEX; + break; + + case PAD_DOWN: + return PAD_DOWN_INDEX; + break; + + case PAD_LEFT: + return PAD_LEFT_INDEX; + break; + + case PAD_UP: + return PAD_UP_INDEX; + break; + + case PAD_RIGHT: + return PAD_RIGHT_INDEX; + break; + + case PAD_L1: + return PAD_L1_INDEX; + break; + + case PAD_R1: + return PAD_R1_INDEX; + break; + + case PAD_L2: + return PAD_L2_INDEX; + break; + + case PAD_R2: + return PAD_R2_INDEX; + break; + + default: + return NUMBER_OF_KEYS; + break; + } +} + +unsigned short* PadOneGetAddress(void) +{ + return &pad1; +} + +void PadClearData(void) +{ + pad1 = 0; + pad2 = 0; + + previous_pad1 = 0; + previous_pad2 = 0; +} + +void PadInit(void) +{ + pad1_cheat_timer = SystemCreateTimer(PAD_CHEAT_TIMEOUT,true /* Repeat flag */,&PadOneCleanCheatArray); + pad2_cheat_timer = SystemCreateTimer(PAD_CHEAT_TIMEOUT,true /* Repeat flag */,&PadTwoCleanCheatArray); + + memset(cheatsArray,0, sizeof(cheatsArray)); +} + +void PadCheatHandler(uint8_t n_pad) +{ + unsigned short available_keys[12] = { PAD_LEFT, PAD_RIGHT, PAD_UP, PAD_DOWN, + PAD_L2, PAD_R2, PAD_L1, PAD_R1, + PAD_TRIANGLE, PAD_CIRCLE, PAD_CROSS, PAD_SQUARE }; + + uint8_t i; + uint8_t keys_released = 0; + unsigned short key; + uint8_t j; + bool (*pressed_callback)(unsigned short); + void (*clean_callback)(void); + bool success = false; + unsigned short* cheat_array; + TYPE_TIMER* timer; + + switch(n_pad) + { + case PAD_ONE: + pressed_callback = &PadOneKeySinglePress; + cheat_array = pad1_cheat_array; + clean_callback = &PadOneCleanCheatArray; + timer = pad1_cheat_timer; + break; + + case PAD_TWO: + pressed_callback = &PadTwoKeySinglePress; + cheat_array = pad2_cheat_array; + clean_callback = &PadTwoCleanCheatArray; + timer = pad2_cheat_timer; + break; + + default: + dprintf("Invalid pad called for PadCheatHandler()!\n"); + return; + } + + for(i = 0; i < PAD_MAX_CHEATS; i++) + { + if(cheatsArray[i] != NULL) + { + if(SystemArrayCompare(cheat_array, cheatsArray[i]->Combination, CHEAT_ARRAY_SIZE) == true) + { + if(cheatsArray[i]->Callback != NULL) + { + if(clean_callback != NULL) + { + clean_callback(); + } + + cheatsArray[i]->Callback(); + + return; + } + } + } + } + + for(i = 0; i < sizeof(available_keys) / sizeof(unsigned short); i++) + { + if(pressed_callback(available_keys[i]) == true) + { + SystemTimerRestart(timer); + key = available_keys[i]; + keys_released++; + } + } + + if(keys_released != 1) + { + return; + } + + // Check for full array (return success = true if an empty array + // element was found. + for(j = 0; j < CHEAT_ARRAY_SIZE; j++) + { + if(cheat_array[j] == 0) + { + success = true; + break; + } + } + + if(success == false) + { + if(clean_callback != NULL) + { + // Overrun + clean_callback(); + } + } + + cheat_array[j] = key; +} + +bool PadAddCheat(TYPE_CHEAT * cheat) +{ + static uint8_t idx = 0; + + if(idx >= PAD_MAX_CHEATS) + { + dprintf("Maximum number of cheats exceeded!\n"); + return false; + } + + cheatsArray[idx++] = cheat; + + return true; +} + +void PadOneCleanCheatArray(void) +{ + memset(pad1_cheat_array,0,sizeof(unsigned short) * CHEAT_ARRAY_SIZE); +} + +void PadTwoCleanCheatArray(void) +{ + memset(pad2_cheat_array,0,sizeof(unsigned short) * CHEAT_ARRAY_SIZE); +} + +unsigned short* PadGetPlayerOneCheatArray(void) +{ + return pad1_cheat_array; +} + +unsigned short PadOneGetLastKeySinglePressed(void) +{ + return pad1_last_key_single_pressed; +} + +unsigned short PadTwoGetLastKeySinglePressed(void) +{ + return pad2_last_key_single_pressed; +} |
