# Thread: Using State Pattern and Joystick

1. ## Using State Pattern and Joystick

Hello everyone,
I am implement using joystick as Password Logger, where Joystick remembers 3 out of 4 UTTERMOST positions, and the combination of the THREE joystick positions represents a PASSWORD.

Since I do not have any joystick, I connected two potentiometers with voltage divider to simulate the real Joystick since it reads voltage and converts it back to analog 10 bit value.

Joystick uttermost position vs analog value:

+X coordinate = 1023
-X coordinate = 0
+Y coordinate = 1023
-Y coordinate = 0

Idle position = (X, Y) ~= (511, 511)

So basically how it works, In order to memorize any position, joystick needs to be first in the IDLE position, and after it moves to for example in RIGHT position it needs to get back to IDLE position in order for a position to be memorized.

So this would be an example of a successful/unsuccessfully memorization:
IDLE -> RIGHT -> IDLE (Memorized RIGHT Position Succesfully)
IDLE -> IDLE -> IDLE (Unsuccessful Position Memorization)
IDLE -> RIGHT -> LEFT (Unsuccesful Positition Memorization - after getting to RIGHT position it should get back to IDLE not to LEFT position)

With boundaries:
Code:
```#define MAX_X_POSITION        1000
#define MIN_X_POSITION        20
#define MAX_Y_POSITION        1000
#define MIN_Y_POSITION        20```
So Joystick method check whether Joystick is in DEAD_ZONE or not based on the current x and y coordinates:
Code:
```int8_t Joystick::getZone(int nX, int nY)
{
if (nX < 0 && nX > 1023 || nY < 0 && nY > 1023)
{
return INVALID_PARAMETER;
}

if (nX > MAX_X_POSITION || nX < MIN_X_POSITION || nY > MAX_Y_POSITION || nY < MIN_Y_POSITION)
{
}
}```
So if joystick is in DEADZONE than it's considered to be in an IDLE position.

What I basically used is State pattern, where every Joystick Position is represented as a class,
and class JoystickState is used as an interface, where every state implements that interface. Every concrete state is a Singleton:

0. JoystickState (INTERFACE) Joystick/JoystickState.h at master * IvanAntunovic/Joystick * GitHub

1. IdleJoystickState Joystick/IdleJoystickState.h at master * IvanAntunovic/Joystick * GitHub

2. UpJoystickState https://github.com/IvanAntunovic/Joy...oystickState.h

3. DownJoystickState https://github.com/IvanAntunovic/Joy...oystickState.h

4. RightJoystickState https://github.com/IvanAntunovic/Joy...oystickState.h

5. LeftJoystickState https://github.com/IvanAntunovic/Joy...oystickState.h

every concrete state has a handleCoordinates method, where it changes it's next state based on the current x and y paramters, you can see that a CONTEXT which is Joystick is passed to the function.

For example in RightJoystickState::handleCoordinates method

Code:
```#define INVALID_PARAMETER   -1
Code:
```void RightJoystickState::handleCoordinates(int nX, int nY, Joystick & joystick)
{
int8_t retVal = joystick.getZone(nX, nY);
// If we are in DEADZONE change state to IDLE
{
joystick.changeState(IdleJoystickState::getInstance());
{
joystick.position_states[3] = IdleJoystickState::getInstance();
}
Serial.println("Joystick moved to Idle Position!");
}
// If we are NOT in DEADZONE, then we stay in the same state (RIGHT)
// From Right State we can only get back to IDLE state in order to MEMORIZE a MOVEMENT
{
Serial.println("Joystick is not in Deadzone! - Right");
}
else if (retVal == INVALID_PARAMETER)
{
Serial.println("Invalid parameters!");
}
}```
or a little more complicated IdleJoystickState

Code:
```void IdleJoystickState::handleCoordinates(int nX, int nY, Joystick & joystick)
{
int8_t retVal = joystick.getZone(nX, nY);
Serial.print("Ret Val: ");
Serial.println(retVal);
Serial.print( "MAX_X_POSITION: ");
Serial.println( MAX_X_POSITION );
Serial.print("MAX_Y_POSITION: ");
Serial.println( MAX_Y_POSITION );

// If we are NOT in DEADZONE that means we need to change our state from IDLE to one of the 4
// States based on the X and Y coordinates
{
int8_t bufferFreeIndexNum;
if (nX > MAX_X_POSITION)
{
bufferFreeIndexNum = this->getBufferFreeIndex(joystick);

if (bufferFreeIndexNum != NOK)
{
joystick.changeState(RightJoystickState::getInstance());
joystick.position_states[bufferFreeIndexNum] = RightJoystickState::getInstance();
Serial.println( "Joystick moved to Right Position!");
}
}
else if (nX < MIN_X_POSITION)
{
bufferFreeIndexNum = this->getBufferFreeIndex(joystick);

if (bufferFreeIndexNum != NOK)
{
joystick.changeState(LeftJoystickState::getInstance());
joystick.position_states[bufferFreeIndexNum] = RightJoystickState::getInstance();
Serial.println("Joystick moved to Left Position!");
}
}
else if (nY > MAX_Y_POSITION)
{
bufferFreeIndexNum = this->getBufferFreeIndex(joystick);

if (bufferFreeIndexNum != NOK)
{
joystick.changeState(UpJoystickState::getInstance());
joystick.position_states[bufferFreeIndexNum] = UpJoystickState::getInstance();
Serial.println("Joystick moved to Up Position!" );
}
}
else if (nY < MIN_Y_POSITION)
{
bufferFreeIndexNum = this->getBufferFreeIndex(joystick);

if (bufferFreeIndexNum != NOK)
{
joystick.changeState(DownJoystickState::getInstance());
joystick.position_states[bufferFreeIndexNum] = DownJoystickState::getInstance();
Serial.println( "Joystick moved to Down position!" );
}
}
}
// If we are in the DEADZONE that means we stay in the currentState = IDLE State
{
Serial.println( "Joystick is in Deadzone! - Idle");
}
else if (retVal == INVALID_PARAMETER)
{
Serial.println("Invalid parameters!" );
}

}```
The problem happens with +X (RIGHT position) and +Y (UP position) uttermost positions. For example when I am in the IDLE state.

Joystick Memorizing LEFT Position

Unsuccessful UP Position
https://s13.postimg.org/rk3dkmg37/Jo...p_Position.jpg

Unsuccessful RIGHT Position

I tested the program in visual studio and it seemed to work:

Successful memorization: (Enter key 'P' for Password memorziation)
https://s24.postimg.org/tea92kbv5/Jo...Successful.jpg

After Succesfull memorization I tried to enter the password and log in (Enter key 'K' for logging in), but I entered on purpose on wrong position and it showed the message that wrong password is entered
https://s7.postimg.org/irzd3qo5z/Joystick_Invalid.jpg

Whole code in VS C++:
https://github.com/IvanAntunovic/Joy...ree/master/src

Whole code for Arduino:

https://github.com/IvanAntunovic/Joy...er/Arduino/src

It took me an hour to write this post, I tried to be as clear as possible, so I hope someone could help me resolve my problem. I really do not see what I am doing wrong since logic works in Visual studio, but then it fails once it is connected to the microcontroller.

Thanks in advance and sorry if this is a wrong place to post this kind of question.

2. SOLVED:

OK I got it working, The map function was the problem... somehow it didn't map the values right.

Analog Refrence Voltage is 5V for reading the analog values. And guess what, pin that was reading X coordinate was reading 0 - 2.62 V,
and pin that was reading Y coordinate was reading 0 - 2.58 V (because of the voltage dividor I used). And that means I could only get analog values from 0 to ~536. So I mapped these values to get a full range from 0 - 2^10 - 1 and passed them as an nX and nY arguments to the handleCoordinates method, and it seems like I was passing the wrong MAPPED values.

Trecherous map function...