Skip to content

Commit fa9c890

Browse files
authored
Merge pull request #657 from adafruit/TheKitty-patch-19
Create teensySNES_stellakey.ino
2 parents 271a58a + 1dc63ef commit fa9c890

1 file changed

Lines changed: 230 additions & 0 deletions

File tree

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#define KEYREPEAT 85 // delay when repeating characters
2+
#define KEYDELAY 200 // delay from first to second character
3+
const int pinAnalogXInput = 3;
4+
const int pinAnalogYInput = 1;
5+
const int pinAnalogZInput = 2;
6+
const int pinAnalogDummyInput = 0;
7+
8+
const int pinBtnUp = 0;
9+
const int pinBtnRight = 1;
10+
const int pinBtnDown = 2;
11+
const int pinBtnLeft = 3;
12+
13+
const int pinBtnSelect = 4;
14+
const int pinBtnStart = 5;
15+
16+
const int pinBtnB = 7;
17+
const int pinBtnA = 8;
18+
const int pinBtnY = 10;
19+
const int pinBtnX = 9;
20+
21+
const int pinBtnTrigLeft = 6;
22+
const int pinBtnTrigRight = 23;
23+
24+
// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
25+
byte buttons[] = {pinBtnUp, pinBtnRight, pinBtnDown, pinBtnLeft, pinBtnSelect, pinBtnStart,
26+
pinBtnB, pinBtnA, pinBtnY, pinBtnX, pinBtnTrigLeft, pinBtnTrigRight};
27+
byte keys[] = {KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_LEFT, KEY_F1, KEY_F2, KEY_SPACE, KEY_SPACE, KEY_4, KEY_5, KEY_ESC, KEY_ENTER};
28+
29+
#define NUMBUTTONS sizeof(buttons)
30+
31+
// we will track if a button is just pressed, just released, or 'currently pressed'
32+
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
33+
34+
35+
const int pinLEDOutput = 11;
36+
37+
//Variables for the states of the SNES buttons
38+
boolean boolBtnA;
39+
boolean boolBtnB;
40+
boolean boolBtnX;
41+
boolean boolBtnY;
42+
43+
boolean boolBtnTrigLeft;
44+
boolean boolBtnTrigRight;
45+
46+
boolean boolBtnUp;
47+
boolean boolBtnDown;
48+
boolean boolBtnLeft;
49+
boolean boolBtnRight;
50+
51+
boolean boolBtnSelect;
52+
boolean boolBtnStart;
53+
54+
//Change these values if accelerometer reading are different:
55+
//How far the accerometer is tilted before
56+
//the Teensy starts moving the mouse:
57+
const int cintMovementThreshold = 18;
58+
59+
//The average zero acceleration values read
60+
//from the accelerometer for each axis:
61+
const int cintZeroXValue = 328;
62+
const int cintZeroYValue = 328;
63+
const int cintZeroZValue = 328;
64+
65+
//The maximum (positive) acceleration values read
66+
//from the accelerometer for each axis:
67+
const int cintMaxXValue = 396;
68+
const int cintMaxYValue = 396;
69+
const int cintMaxZValue = 396;
70+
71+
//The minimum (negative) acceleration values read
72+
//from the accelerometer for each axis:
73+
const int cintMinXValue = 256;
74+
const int cintMinYValue = 256;
75+
const int cintMinZValue = 256;
76+
77+
//The sign of the mouse movement relative to the acceleration.
78+
//If your cursor is going in the opposite direction you think it
79+
//should go, change the sign for the appropriate axis.
80+
const int cintXSign = 1;
81+
const int cintYSign = -1;
82+
const int cintZSign = 1;
83+
84+
//const float cfloatMovementMultiplier = 1;
85+
86+
//The maximum speed in each axis (x and y)
87+
//that the cursor should move. Set this to a higher or lower
88+
//number if the cursor does not move fast enough or is too fast.
89+
const int cintMaxMouseMovement = 10;
90+
91+
//This reduces the 'twitchiness' of the cursor by calling
92+
//a delay function at the end of the main loop.
93+
//There is a better way to do this without delaying the whole
94+
//microcontroller, but that is left for another time or person.
95+
const int cintMouseDelay = 8;
96+
97+
98+
void setup()
99+
{
100+
//This is not needed and set to default but can be useful if you
101+
//want to get the full range out of the analog channels when
102+
//reading from the 3.3V ADXL335.
103+
//If the analog reference is used, the thresholds, zeroes,
104+
//maxima and minima will need to be re-evaluated.
105+
analogReference( DEFAULT );
106+
107+
//Setup the pin modes.
108+
pinMode( pinLEDOutput, OUTPUT );
109+
110+
//Special for the Teensy is the INPUT_PULLUP
111+
//It enables a pullup resitor on the pin.
112+
for (byte i=0; i< NUMBUTTONS; i++) {
113+
pinMode(buttons[i], INPUT_PULLUP);
114+
115+
}
116+
//Uncomment this line to debug the acceleromter values:
117+
//Serial.begin(19200);
118+
}
119+
120+
121+
void loop()
122+
{
123+
// //debugging the start button...
124+
digitalWrite ( pinLEDOutput, digitalRead(pinBtnStart));
125+
126+
127+
//Process the accelerometer to make the cursor move.
128+
//Comment this line to debug the accelerometer values:
129+
fcnProcessAccelerometer();
130+
131+
//Progess the SNES controller buttons to send keystrokes.
132+
fcnProcessButtons();
133+
134+
135+
//Delay to avoid 'twitchiness' and bouncing inputs
136+
//due to too fast of sampling.
137+
//As said above, there is a better way to do this
138+
//than delay the whole MCU.
139+
delay(cintMouseDelay);
140+
}
141+
142+
143+
144+
//Function to process the acclerometer data
145+
//and send mouse movement information to the host computer.
146+
void fcnProcessAccelerometer()
147+
{
148+
//Initialize values for the mouse cursor movement.
149+
int intMouseXMovement = 0;
150+
int intMouseYMovement = 0;
151+
152+
//Read the dummy analog channel
153+
//This must be done first because the X analog channel was first
154+
//and was unstable, it dropped or pegged periodically regardless
155+
//of pin or source.
156+
analogRead( pinAnalogDummyInput );
157+
158+
//Read accelerometer readings
159+
int intAnalogXReading = analogRead(pinAnalogXInput);
160+
int intAnalogYReading = analogRead(pinAnalogYInput);
161+
int intAnalogZReading = analogRead(pinAnalogZInput);
162+
163+
//Calculate mouse movement
164+
//If the analog X reading is ouside of the zero threshold...
165+
if( cintMovementThreshold < abs( intAnalogXReading - cintZeroXValue ) )
166+
{
167+
//...calculate X mouse movement based on how far the X acceleration is from its zero value.
168+
intMouseXMovement = cintXSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxXValue - cintMinXValue ) ) * ( intAnalogXReading - cintMinXValue ) ) - cintMaxMouseMovement );
169+
//it could use some improvement, like making it trigonometric.
170+
}
171+
else
172+
{
173+
//Within the zero threshold, the cursor does not move in the X.
174+
intMouseXMovement = 0;
175+
}
176+
177+
//If the analog Y reading is ouside of the zero threshold...
178+
if( cintMovementThreshold < abs( intAnalogYReading - cintZeroYValue ) )
179+
{
180+
//...calculate Y mouse movement based on how far the Y acceleration is from its zero value.
181+
intMouseYMovement = cintYSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxYValue - cintMinYValue ) ) * ( intAnalogYReading - cintMinYValue ) ) - cintMaxMouseMovement );
182+
//it could use some improvement, like making it trigonometric.
183+
}
184+
else
185+
{
186+
//Within the zero threshold, the cursor does not move in the Y.
187+
intMouseYMovement = 0;
188+
}
189+
190+
Mouse.move(intMouseXMovement, intMouseYMovement);
191+
}
192+
193+
//Function to process the buttons from the SNES controller
194+
void fcnProcessButtons()
195+
{
196+
byte flag = 0;
197+
static long currentkey = 0;
198+
static long repeat = 0;
199+
200+
for (byte i = 0; i < NUMBUTTONS; i++) {
201+
202+
if ( !digitalRead(buttons[i])) {
203+
flag = 1;
204+
if (currentkey != keys[i]) {
205+
// unset the old key
206+
Keyboard.set_key1(0);
207+
Keyboard.send_now();
208+
Keyboard.set_key1(keys[i]);
209+
currentkey = keys[i];
210+
Keyboard.send_now();
211+
repeat = 0;
212+
} else {
213+
if (! repeat) {
214+
delay(KEYDELAY);
215+
} else {
216+
// resend
217+
repeat = 1;
218+
Keyboard.set_key1(keys[i]);
219+
Keyboard.send_now();
220+
delay(KEYREPEAT);
221+
}
222+
}
223+
}
224+
}
225+
if ( currentkey && !flag) {
226+
currentkey = 0;
227+
Keyboard.set_key1(0);
228+
Keyboard.send_now();
229+
}
230+
}

0 commit comments

Comments
 (0)