mirror of
https://github.com/mnzlmstr/N64toiQue
synced 2025-01-07 11:58:07 -05:00
135 lines
4.2 KiB
C++
135 lines
4.2 KiB
C++
#include "Output.h"
|
|
#include "PinMappings.h"
|
|
|
|
#include <Arduino.h>
|
|
|
|
int encoderXpos = 0;
|
|
int encoderYpos = 0;
|
|
|
|
void setupIO()
|
|
{
|
|
// the controller data line
|
|
LINE_WRITE_HIGH;
|
|
|
|
pinMode(PIN_BUTTON_A,OUTPUT);
|
|
pinMode(PIN_BUTTON_B,OUTPUT);
|
|
pinMode(PIN_BUTTON_Z,OUTPUT);
|
|
pinMode(PIN_BUTTON_S,OUTPUT);
|
|
pinMode(PIN_BUTTON_L,OUTPUT);
|
|
pinMode(PIN_BUTTON_R,OUTPUT);
|
|
|
|
pinMode(PIN_DPAD_UP, OUTPUT);
|
|
pinMode(PIN_DPAD_DOWN, OUTPUT);
|
|
pinMode(PIN_DPAD_LEFT, OUTPUT);
|
|
pinMode(PIN_DPAD_RIGHT,OUTPUT);
|
|
|
|
pinMode(PIN_C_UP, OUTPUT);
|
|
pinMode(PIN_C_DOWN, OUTPUT);
|
|
pinMode(PIN_C_LEFT, OUTPUT);
|
|
pinMode(PIN_C_RIGHT,OUTPUT);
|
|
|
|
pinMode(PIN_A_AXIS_X, OUTPUT);
|
|
pinMode(PIN_B_AXIS_X, OUTPUT);
|
|
|
|
pinMode(PIN_A_AXIS_Y, OUTPUT);
|
|
pinMode(PIN_B_AXIS_Y, OUTPUT);
|
|
}
|
|
|
|
/** Function to simulate the 90° phaseshifted quadrature encoding used by
|
|
* the N64-Controller's joystick's linear encoders. As only change in position
|
|
* (not absolute position) is reported the change in the value between writes
|
|
* is needed for calculation. Must be run from RAM to mitigate timing differences in
|
|
* ESP32's SPI-Flash Chip Access Times.
|
|
* @param relativeMovement should be processed by calling 'mapJoystickToEncoderPos'
|
|
* with the read joystick position.
|
|
*/
|
|
void IRAM_ATTR moveAxis(int axisPinA,int axisPinB,int requestedEncoderPos,int *realEncoderPos)
|
|
{
|
|
// get difference from requested ender position to real encoder position
|
|
int difference = requestedEncoderPos - *realEncoderPos;
|
|
|
|
// store new real encoder position
|
|
*realEncoderPos = requestedEncoderPos;
|
|
|
|
// set pins used for outputting
|
|
int pinA = axisPinA;
|
|
int pinB = axisPinB;
|
|
|
|
// invert pins if moving in the other direction
|
|
if(difference > 0)
|
|
{
|
|
pinA = axisPinB;
|
|
pinB = axisPinA;
|
|
}
|
|
|
|
// get absolute movement value
|
|
difference = abs(difference);
|
|
|
|
// for each change in movement
|
|
for(int i = 0;i < difference;i++)
|
|
{
|
|
// replicate 90° phaseshifted quadrate output
|
|
digitalWrite(pinA,LOW);
|
|
delayMicroseconds(2);
|
|
digitalWrite(pinB,LOW);
|
|
delayMicroseconds(6);
|
|
digitalWrite(pinA,HIGH);
|
|
delayMicroseconds(2);
|
|
digitalWrite(pinB,HIGH);
|
|
|
|
// debounce as N64 will not detect change correctly otherwise
|
|
delayMicroseconds(40);
|
|
}
|
|
}
|
|
|
|
/** Function to map Joystick position to relative Encoder Position.
|
|
* According to Nintendo the maximum value for any axis to be assumed should
|
|
* be +- 60. The encoder starts acting strange after ~ 30 turns in a given
|
|
* direction. Also passing on ControllerData struct so that user specified
|
|
* modifiers can be used to specify alternate mapping, eg. for
|
|
* easier ESS-Position in Ocarina of Time (see my example)
|
|
*/
|
|
int mapJoystickToEncoderPos(int joyval,ControllerData *data)
|
|
{
|
|
// ESS-Modifier for Ocarina of Time, hold A+B to stay in ESS-Position
|
|
if(data->buttonA && data->buttonB) return -2;
|
|
|
|
// deadzone handling
|
|
if(abs(joyval) < 3) return 0;
|
|
|
|
// normally return half ???
|
|
return (int)(joyval * .5f);
|
|
}
|
|
|
|
void outputToiQue(ControllerData *data)
|
|
{
|
|
// ===== Write Button Data =====
|
|
digitalWrite(PIN_BUTTON_A,data->buttonA);
|
|
digitalWrite(PIN_BUTTON_B,data->buttonB);
|
|
digitalWrite(PIN_BUTTON_L,data->buttonL);
|
|
digitalWrite(PIN_BUTTON_R,data->buttonR);
|
|
digitalWrite(PIN_BUTTON_Z,data->buttonZ);
|
|
digitalWrite(PIN_BUTTON_S,data->buttonStart);
|
|
|
|
// ===== Write D-Pad Data =====
|
|
digitalWrite(PIN_DPAD_UP, data->DPadUp);
|
|
digitalWrite(PIN_DPAD_DOWN, data->DPadDown);
|
|
digitalWrite(PIN_DPAD_LEFT, data->DPadLeft);
|
|
digitalWrite(PIN_DPAD_RIGHT,data->DPadRight);
|
|
|
|
// ===== Write C-Button Data =====
|
|
digitalWrite(PIN_C_UP, data->CUp);
|
|
digitalWrite(PIN_C_DOWN, data->CDown);
|
|
digitalWrite(PIN_C_LEFT, data->CLeft);
|
|
digitalWrite(PIN_C_RIGHT, data->CRight);
|
|
|
|
// ===== Write Joystick Data =====
|
|
|
|
// calculate change in axis between writes
|
|
//int xAxisChange = data->xAxis - lastxAxis;
|
|
//int yAxisChange = data->yAxis - lastyAxis;
|
|
|
|
// move axis accordingly
|
|
moveAxis(PIN_A_AXIS_X,PIN_B_AXIS_X,mapJoystickToEncoderPos(data->xAxis,data),&encoderXpos);
|
|
moveAxis(PIN_A_AXIS_Y,PIN_B_AXIS_Y,mapJoystickToEncoderPos(data->yAxis,data),&encoderYpos);
|
|
} |