This example shows how to use the Sparkfun Joystick on the board. The Joystick shield contains an analog joystick which is connected to A0 and A1 analog channels of the Arduino connector. It also contains four push buttons connected at D3-D6 pins of the Arduino connector.
For this notebook, an Arduino joystick shield is required.
In [1]:
from pynq.overlays.base import BaseOverlay
base = BaseOverlay("base.bit")
In [2]:
DIRECTION_VALUE_MAP = {
0: 'up',
1: 'up_right',
2: 'right',
3: 'down_right',
4: 'down',
5: 'down_left',
6: 'left',
7: 'up_left',
8: 'center'
}
BUTTON_INDEX_MAP = {
'D3': 0,
'D4': 1,
'D5': 2,
'D6': 3
}
The joystick can measure horizontal direction x
and vertical direction y
.
The thresholds for raw values are:
Horizontal:
Threshold | Direction |
---|---|
x < 25000 | left |
25000 < x < 39000 | center |
x > 39000 | right |
Vertical:
Threshold | Direction |
---|---|
y < 25000 | down |
25000 < y < 39000 | center |
y > 39000 | up |
In [3]:
%%microblaze base.ARDUINO
#include "xparameters.h"
#include "circular_buffer.h"
#include "gpio.h"
#include "xsysmon.h"
#include <pyprintf.h>
#define X_THRESHOLD_LOW 25000
#define X_THRESHOLD_HIGH 39000
#define Y_THRESHOLD_LOW 25000
#define Y_THRESHOLD_HIGH 39000
typedef enum directions {
up = 0,
right_up,
right,
right_down,
down,
left_down,
left,
left_up,
centered
}direction_e;
static gpio gpio_buttons[4];
static XSysMon SysMonInst;
XSysMon_Config *SysMonConfigPtr;
XSysMon *SysMonInstPtr = &SysMonInst;
int init_joystick(){
unsigned int i, status;
SysMonConfigPtr = XSysMon_LookupConfig(XPAR_SYSMON_0_DEVICE_ID);
if(SysMonConfigPtr == NULL)
return -1;
status = XSysMon_CfgInitialize(
SysMonInstPtr, SysMonConfigPtr, SysMonConfigPtr->BaseAddress);
if(XST_SUCCESS != status)
return -1;
for (i=0; i<4; i++){
gpio_buttons[i] = gpio_open(i+3);
gpio_set_direction(gpio_buttons[i], GPIO_IN);
}
return 0;
}
unsigned int get_direction_value(){
direction_e direction;
unsigned int x_position, y_position;
while ((XSysMon_GetStatus(SysMonInstPtr) &
XSM_SR_EOS_MASK) != XSM_SR_EOS_MASK);
x_position = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_AUX_MIN+1);
y_position = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_AUX_MIN+9);
if (x_position > X_THRESHOLD_HIGH) {
if (y_position > Y_THRESHOLD_HIGH) {
direction = right_up;
} else if (y_position < Y_THRESHOLD_LOW) {
direction = right_down;
} else {
direction = right;
}
} else if (x_position < X_THRESHOLD_LOW) {
if (y_position > Y_THRESHOLD_HIGH) {
direction = left_up;
} else if (y_position < Y_THRESHOLD_LOW) {
direction = left_down;
} else {
direction = left;
}
} else {
if (y_position > Y_THRESHOLD_HIGH) {
direction = up;
} else if (y_position < Y_THRESHOLD_LOW) {
direction = down;
} else {
direction = centered;
}
}
return direction;
}
unsigned int get_button_value(unsigned int btn_i){
unsigned int value;
value = gpio_read(gpio_buttons[btn_i]);
return value;
}
In [4]:
init_joystick()
Out[4]:
The following Python wrappers will call the Microblaze functions internally.
In [5]:
def read_direction():
direction_value = get_direction_value()
return DIRECTION_VALUE_MAP[direction_value]
def read_button(button):
return get_button_value(BUTTON_INDEX_MAP[button])
In [6]:
read_direction()
Out[6]:
Let's pull the joystick towards the bottom right corner.
In [7]:
read_direction()
Out[7]:
Based on the schematic of the shield, we can see the read value will go low if the corresponding button has been pressed.
Run the next cell while pushing both button D4
and D6
.
In [8]:
for button in BUTTON_INDEX_MAP:
if read_button(button):
print('Button {} is not pressed.'.format(button))
else:
print('Button {} is pressed.'.format(button))