Main Page | Namespace List | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Joypad.cpp

Go to the documentation of this file.
00001 
00004 #include <iostream>
00005 #include <string.h>
00006 #include "Joypad.h"
00007 
00016 NablaPS2Utils::JoypadManager::JoypadManager(int JoypadNumber) : m_AStickTreshold(30) {
00017 
00018     //Open device file.
00019     PadHandle = open(JoyDev[JoypadNumber], O_RDONLY);
00020     if (Status() == PS2PAD_STAT_READY) {
00021     
00022         m_UpdateType();
00023         if (m_Type != PS2PAD_TYPE_DUALSHOCK && 
00024              m_Type != PS2PAD_TYPE_DIGITAL) 
00025             Close();
00026     }
00027     m_AnalogLocked = false;
00028     //Reset all the variables of the class, all enum values are set to zero
00029     //so all the button are in Unpressed state
00030     memset(m_AnalogStick, 0, sizeof(m_AnalogStick));
00031     memset(m_Buttons, 0, sizeof(m_Buttons));
00032 }
00033 
00040 NablaPS2Utils::JoypadManager::~JoypadManager() {
00041 
00042     UnlockAnalogMode();
00043     Close();
00044 }
00045 
00051 void NablaPS2Utils::JoypadManager::m_UpdateType() {
00052 
00053     m_ReadData();
00054     PadDataType *Data = (PadDataType *) m_PadData;
00055     m_Type = Data->Type;    
00056  }
00057 
00067 int NablaPS2Utils::JoypadManager::Status() {
00068 
00069     if (PadHandle > 0) {
00070     
00071         ioctl(PadHandle, PS2PAD_IOCGETSTAT, &m_Status);
00072         while(m_Status == PS2PAD_STAT_BUSY) {
00073         
00074             ioctl(PadHandle, PS2PAD_IOCGETSTAT, &m_Status);
00075         } 
00076     }
00077     else {
00078         
00079         m_Status = PS2PAD_STAT_ERROR;
00080     }
00081     return m_Status;
00082 }
00083 
00088 void NablaPS2Utils::JoypadManager::WaitUntilBusy() {
00089 
00090     if (PadHandle > 0) {
00091     
00092         int Status;
00093         ioctl(PadHandle, PS2PAD_IOCGETSTAT, &Status);
00094         while(Status == PS2PAD_STAT_BUSY) {
00095         
00096             ioctl(PadHandle, PS2PAD_IOCGETSTAT, &Status);
00097         } 
00098     }
00099 }
00106 bool NablaPS2Utils::JoypadManager::ReadPadData() {
00107 
00108     return m_ReadData();
00109 }
00113 int NablaPS2Utils::JoypadManager::GetType() {
00114 
00115     return m_Type;  
00116 }
00117 
00127 bool NablaPS2Utils::JoypadManager::SetAnalogMode(bool AMEnable) {   
00128     
00129     ps2pad_mode PS2PMode;
00130     PS2PMode.lock = 1;
00131     if (AMEnable) 
00132         PS2PMode.offs = 1;
00133     else
00134         PS2PMode.offs = 0;
00135     ioctl(PadHandle, PS2PAD_IOCSETMODE, &PS2PMode);
00136     //If pad is in analog mode its type is PS2PAD_TYPE_DIGITAL
00137     //when analog mode is enabled its type change into PS2PAD_TYPE_DUALSHOCK
00138     m_UpdateType();
00139     return true;
00140 }
00141 
00148 bool NablaPS2Utils::JoypadManager::LockAnalogMode() {
00149     
00150     m_AnalogLocked = true;
00151     ps2pad_mode PS2PMode;
00152     PS2PMode.offs = 1;
00153     PS2PMode.lock = 3;
00154     ioctl(PadHandle, PS2PAD_IOCSETMODE, &PS2PMode);
00155     return true;
00156 }
00157 
00162 bool NablaPS2Utils::JoypadManager::UnlockAnalogMode() {
00163 
00164     if (m_AnalogLocked) {
00165     
00166         ps2pad_mode PS2PMode;
00167         PS2PMode.offs = 1;
00168         PS2PMode.lock = 2;
00169         ioctl(PadHandle, PS2PAD_IOCSETMODE, &PS2PMode); 
00170     }
00171     return true;
00172 }
00178 bool NablaPS2Utils::JoypadManager::AnalogButtonSupported() {
00179 
00180     int Supported = 0;
00181     if (Status() == PS2PAD_STAT_READY) {
00182 
00183         ioctl(PadHandle, PS2PAD_IOCPRESSMODEINFO, &Supported);
00184     }
00185     return Supported == 1;
00186 }
00187 
00192 void NablaPS2Utils::JoypadManager::EnableActuators() {
00193 
00194     //Enable actuators
00195     ps2pad_act PSact;
00196     memset(PSact.data, -1, sizeof(PSact.data));
00197     PSact.len = 6;
00198     PSact.data[0] = 0;
00199     PSact.data[1] = 1;
00200     ioctl(PadHandle, PS2PAD_IOCSETACTALIGN, &PSact);
00201 
00202     WaitUntilBusy();
00203     m_constActuatorStatus   = false;
00204     m_VariableActuatorValue = 0;
00205 }
00206 
00211 bool NablaPS2Utils::JoypadManager::ActuatorsSupported() {
00212 
00213     ps2pad_actinfo PSActInfo;
00214 
00215     //Remember that when actno = -1 term value is unused 
00216     PSActInfo.actno = -1;
00217     PSActInfo.term = 0;
00218     PSActInfo.result = 0;
00219     ioctl(PadHandle, PS2PAD_IOCACTINFO, &PSActInfo);
00220 
00221     //Since only supported pad is DualShock there must be exactly 2 actuators
00222     return (PSActInfo.result == 2);
00223 }
00224 
00232 void NablaPS2Utils::JoypadManager::SetActuatorConst(bool Status) {
00233 
00234     //Enable only if pad is of DualShock type
00235     if (m_Type == PS2PAD_TYPE_DUALSHOCK) {
00236     
00237         ps2pad_act PSact;
00238         PSact.len = 6;
00239         memset(PSact.data, -1, sizeof(PSact.data));
00240         if (Status) 
00241             PSact.data[0] = 1;
00242         else
00243             PSact.data[0] = 0;
00244         //Set back current value of variable actuator
00245         PSact.data[1] = m_VariableActuatorValue;
00246         //Update the status of const actuator
00247         m_constActuatorStatus = Status;
00248         ioctl(PadHandle, PS2PAD_IOCSETACT, &PSact);
00249     }
00250 }
00251 
00257 void NablaPS2Utils::JoypadManager::SetActuatorVariable(unsigned char Value) {
00258 
00259     if (m_Type == PS2PAD_TYPE_DUALSHOCK) {
00260     
00261         ps2pad_act PSact;
00262         PSact.len = 6;
00263         memset(PSact.data, -1, sizeof(PSact.data));
00264         PSact.data[1] = Value;
00265         PSact.data[0] = m_constActuatorStatus;
00266         m_VariableActuatorValue = PSact.data[1];
00267         ioctl(PadHandle, PS2PAD_IOCSETACT, &PSact);
00268     }
00269 }
00276 bool NablaPS2Utils::JoypadManager::SetAnalogButtonStatus(bool ABEnable) {
00277 
00278     if (Status() == PS2PAD_STAT_READY) {
00279 
00280         if (ABEnable) 
00281             ioctl(PadHandle, PS2PAD_IOCENTERPRESSMODE);
00282         else
00283             ioctl(PadHandle, PS2PAD_IOCEXITPRESSMODE);
00284         m_AnalogButtonEnabled = ABEnable;
00285         return true;
00286     }
00287     return false;
00288 }
00289 
00293 void NablaPS2Utils::JoypadManager::Close() {
00294 
00295     if (PadHandle >= 0) 
00296         close(PadHandle);
00297     PadHandle = -1;
00298 }
00299 
00300 
00306 bool NablaPS2Utils::JoypadManager::m_ReadData() {
00307 
00308     if (Status() == PS2PAD_STAT_READY) {
00309 
00310         int ReadBytes = read(PadHandle, m_PadData, PS2PAD_DATASIZE);
00311         if (ReadBytes > 0) {
00312             
00313             //Call member function to analyze data of the pad 
00314             m_AnalyzeRead();
00315             return true;
00316         }
00317     }
00318     //If data cannot be read from the pad the user must be informed
00319     //that something went wrong
00320     return false;
00321 }
00322 
00329 float   NablaPS2Utils::JoypadManager::m_ReadStickValueX(unsigned char Value) {
00330 
00331     //First of all subtract half the maximum value and then normalize
00332     //to float range [-1, 1]
00333     float Unbiased = Value - 127.5;
00334     if (Unbiased < m_AStickTreshold && Unbiased > -m_AStickTreshold) {
00335         
00336         return 0.0f;
00337     }
00338     return Unbiased / 127.5f;
00339 }
00340 
00347 float   NablaPS2Utils::JoypadManager::m_ReadStickValueY(unsigned char Value) {
00348 
00349     float Unbiased = Value - 127.5;
00350     if (Unbiased < m_AStickTreshold && Unbiased > -m_AStickTreshold) {
00351         
00352         return 0.0f;
00353     }
00354     //Remember that Y axix of analog stick grow from up to bottom, since 
00355     //in a right coordinate system Y axix point up it is more natural
00356     //to negate the original value.
00357     return -Unbiased / 127.5f;
00358 }
00359 
00366 void NablaPS2Utils::JoypadManager::m_AnalyzeRead() {
00367 
00368     //First of all analyze digital button state that is contained in third and
00369     //fourth byte of DataRead. To read data cast raw binary format to 
00370     //PadDataType structure
00371     PadDataType *Data = (PadDataType *) m_PadData;
00372     for (int I = 0; I < 16; ++I) {
00373     
00374         int CurStatus = Data->DButtons & (1 << I);
00375         if (CurStatus) {
00376             
00377             //Remember that 1 means button released while 0 means 
00378             //button pressed so if (Curstatus) == true button is not
00379             //pressed
00380             if (m_Buttons[I].State == Pressed || m_Buttons[I].State == MPressed)
00381                 m_Buttons[I].State = Released;
00382             else
00383                 m_Buttons[I].State = Unpressed;
00384         }
00385         else {
00386         
00387             if (m_Buttons[I].State == Unpressed || m_Buttons[I].State == Released)
00388                 m_Buttons[I].State = Pressed;
00389             else
00390                 m_Buttons[I].State = MPressed;
00391         }
00392     }
00393 
00394     //Take value of analog stick. Remember to check threshold of the stick
00395     m_AnalogStick[RX] = m_ReadStickValueX(Data->AnalogSRX);
00396     m_AnalogStick[RY] = m_ReadStickValueY(Data->AnalogSRY);
00397     m_AnalogStick[LX] = m_ReadStickValueX(Data->AnalogSLX);
00398     m_AnalogStick[LY] = m_ReadStickValueY(Data->AnalogSLY);
00399 
00400     //Now take level of pressure for analog button if needed.
00401     if (m_AnalogButtonEnabled) {
00402     
00403         m_Buttons[CIRCLE].PressureLevel     = Data->PadCircle / 255.0f;
00404         m_Buttons[SQUARE].PressureLevel     = Data->PadSquare / 255.0f;
00405         m_Buttons[TRIANGLE].PressureLevel   = Data->PadTriangle / 255.0f;
00406         m_Buttons[CROSS].PressureLevel      = Data->PadCross / 255.0f;
00407         m_Buttons[R1].PressureLevel         = Data->PadR1 / 255.0f;
00408         m_Buttons[R2].PressureLevel         = Data->PadR2 / 255.0f;
00409         m_Buttons[L1].PressureLevel         = Data->PadL1 / 255.0f;
00410         m_Buttons[L2].PressureLevel         = Data->PadL2 / 255.0f;
00411         m_Buttons[LEFT].PressureLevel           = Data->PadL / 255.0f;
00412         m_Buttons[DOWN].PressureLevel           = Data->PadD / 255.0f;
00413         m_Buttons[RIGHT].PressureLevel      = Data->PadR / 255.0f;
00414         m_Buttons[UP].PressureLevel         = Data->PadU / 255.0f;
00415     }
00416 }

Generated on Wed Jan 7 19:11:56 2004 for PS2 Tutorial by doxygen 1.3.4