mirror of
https://github.com/mnzlmstr/N64toiQue
synced 2025-01-07 11:58:07 -05:00
206 lines
6.8 KiB
C++
206 lines
6.8 KiB
C++
#include "ControllerBuffer.h"
|
|
#include "PinMappings.h"
|
|
#include "Debug.h"
|
|
|
|
// buffer to hold data being read from controller
|
|
bool buffer[DATA_SIZE + DATA_OFFSET];
|
|
|
|
// bit resolution and offsets
|
|
int bitOffsets[32];
|
|
int bitResolution;
|
|
|
|
/** Function to send a Command to the attached N64-Controller.
|
|
* Must be run from RAM to defy timing differences introduced from
|
|
* reading Code from ESP32's SPI Flash Chip.
|
|
*/
|
|
void IRAM_ATTR sendCommand(byte command)
|
|
{
|
|
// the current bit to write
|
|
bool bit;
|
|
|
|
// clear output buffer
|
|
memset(buffer,0,DATA_SIZE + DATA_OFFSET);
|
|
|
|
// for each bit
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
// get value
|
|
bit = (1 << (7 - i)) & command;
|
|
|
|
// write data
|
|
LINE_WRITE_LOW;
|
|
delayMicroseconds((3 - 2 * bit));
|
|
LINE_WRITE_HIGH;
|
|
delayMicroseconds((1 + 2 * bit));
|
|
}
|
|
|
|
// console stop bit
|
|
LINE_WRITE_LOW;
|
|
delayMicroseconds(1);
|
|
LINE_WRITE_HIGH;
|
|
delayMicroseconds(2);
|
|
|
|
// read returned data as fast as possible
|
|
for(int i = 0;i < DATA_SIZE + DATA_OFFSET;i++)
|
|
{
|
|
buffer[i] = digitalRead(DATA_PIN);
|
|
}
|
|
|
|
// plot polling process from controller if unstructed to
|
|
#ifdef PLOT_CONSOLE_POLLING
|
|
for(int i = 0; i < DATA_SIZE + DATA_OFFSET;i++)
|
|
{
|
|
Serial.println(buffer[i]*2500);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Function to extract a controller bit from the buffer of returned data */
|
|
void getBit(bool *bit,int offset,bool *data)
|
|
{
|
|
// sanity check offset
|
|
if(offset < 0) offset = 0;
|
|
|
|
// count
|
|
short count = 0;
|
|
|
|
// get count from offset to offset + length
|
|
for(int i = offset + DATA_OFFSET;i < offset + bitResolution;i++)
|
|
{
|
|
count += *(data + i);
|
|
}
|
|
|
|
// if offset surpasses threshold set bit
|
|
*bit = false;
|
|
if(count > BIT_THRESHOLD) *bit = true;
|
|
}
|
|
|
|
/** Function to populate the controller struct if command 0x01 was sent.
|
|
* Buttons are set according to data in buffer, raw axis data is written,
|
|
* Axis Data is correctly decoded from raw axis data by taking two's complement
|
|
* and checking if value if below 'MAX_INCLINE_AXIS_X' or 'MAX_INCLINE_AXIS_Y'.
|
|
* If values surpass the maximum incline they are set to match those values.
|
|
*/
|
|
void populateControllerStruct(ControllerData *data)
|
|
{
|
|
// first byte
|
|
getBit(&(data->buttonA) , bitOffsets[0] ,&buffer[0]);
|
|
getBit(&(data->buttonB), bitOffsets[1] ,&buffer[0]);
|
|
getBit(&(data->buttonZ), bitOffsets[2] ,&buffer[0]);
|
|
getBit(&(data->buttonStart), bitOffsets[3] ,&buffer[0]);
|
|
getBit(&(data->DPadUp), bitOffsets[4] ,&buffer[0]);
|
|
getBit(&(data->DPadDown), bitOffsets[5] ,&buffer[0]);
|
|
getBit(&(data->DPadLeft), bitOffsets[6] ,&buffer[0]);
|
|
getBit(&(data->DPadRight), bitOffsets[7] ,&buffer[0]);
|
|
|
|
// second byte, first two bits are unused
|
|
getBit(&(data->buttonL), bitOffsets[10] ,&buffer[0]);
|
|
getBit(&(data->buttonR), bitOffsets[11] ,&buffer[0]);
|
|
getBit(&(data->CUp), bitOffsets[12] ,&buffer[0]);
|
|
getBit(&(data->CDown), bitOffsets[13] ,&buffer[0]);
|
|
getBit(&(data->CLeft), bitOffsets[14] ,&buffer[0]);
|
|
getBit(&(data->CRight), bitOffsets[15] ,&buffer[0]);
|
|
|
|
// third byte
|
|
getBit(&(data->xAxisRaw[0]), bitOffsets[16], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[1]), bitOffsets[17], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[2]), bitOffsets[18], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[3]), bitOffsets[19], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[4]), bitOffsets[20], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[5]), bitOffsets[21], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[6]), bitOffsets[22], &buffer[0]);
|
|
getBit(&(data->xAxisRaw[7]), bitOffsets[23], &buffer[0]);
|
|
|
|
// fourth byte
|
|
getBit(&(data->yAxisRaw[0]), bitOffsets[24], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[1]), bitOffsets[25], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[2]), bitOffsets[26], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[3]), bitOffsets[27], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[4]), bitOffsets[28], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[5]), bitOffsets[29], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[6]), bitOffsets[30], &buffer[0]);
|
|
getBit(&(data->yAxisRaw[7]), bitOffsets[31], &buffer[0]);
|
|
|
|
// sum up bits to get axis bytes
|
|
data->xAxis = 0;
|
|
data->yAxis = 0;
|
|
for(int i = 0;i < 8;i++)
|
|
{
|
|
data->xAxis += (data->xAxisRaw[i] * (0x80 >> (i)));
|
|
data->yAxis += (data->yAxisRaw[i] * (0x80 >> (i)));
|
|
|
|
// print y axis values
|
|
#ifdef PRINT_Y_AXIS_VALUES
|
|
Serial.printf("%i %i %i %i %i %i %i %i\n",data->yAxisRaw[0],data->yAxisRaw[1],data->yAxisRaw[2],data->yAxisRaw[3],data->yAxisRaw[4],data->yAxisRaw[5],data->yAxisRaw[6],data->yAxisRaw[7]);
|
|
Serial.printf("yAxis: %i \n",data->yAxis);
|
|
#endif
|
|
|
|
// print x axis values
|
|
#ifdef PRINT_X_AXIS_VALUES
|
|
Serial.printf("%i %i %i %i %i %i %i %i\n",data->xAxisRaw[0],data->xAxisRaw[1],data->xAxisRaw[2],data->xAxisRaw[3],data->xAxisRaw[4],data->xAxisRaw[5],data->xAxisRaw[6],data->xAxisRaw[7]);
|
|
Serial.printf("xAxis: %i \n",data->xAxis);
|
|
#endif
|
|
}
|
|
|
|
// decode xAxis two's complement
|
|
if(data->xAxis & 0x80)
|
|
{
|
|
data->xAxis = -1 * (0xff - data->xAxis);
|
|
}
|
|
|
|
// decode yAxis two's complement
|
|
if(data->yAxis & 0x80)
|
|
{
|
|
data->yAxis = -1 * (0xff - data->yAxis);
|
|
}
|
|
|
|
// keep x axis below maxIncline
|
|
if(data->xAxis > MAX_INCLINE_AXIS_X) data->xAxis = MAX_INCLINE_AXIS_X;
|
|
if(data->xAxis < -MAX_INCLINE_AXIS_X) data->xAxis = -MAX_INCLINE_AXIS_X;
|
|
|
|
// keep y axis below maxIncline
|
|
if(data->yAxis > MAX_INCLINE_AXIS_Y) data->yAxis = MAX_INCLINE_AXIS_Y;
|
|
if(data->yAxis < -MAX_INCLINE_AXIS_Y) data->yAxis = -MAX_INCLINE_AXIS_Y;
|
|
|
|
//Serial.printf("xaxis: %-3i yaxis: %-3i \n",data->xAxis,data->yAxis);
|
|
}
|
|
|
|
void updateOffsetsAndResolution()
|
|
{
|
|
// the current bit counter
|
|
int bitCounter = 0;
|
|
|
|
// to hold the offset of A Button's falling edge
|
|
int bitAfallingOffset = 0;
|
|
|
|
// iterate over buffer
|
|
for(int i = 0;i < DATA_SIZE + DATA_OFFSET - 1;i++)
|
|
{
|
|
// if a falling edge is detected
|
|
if(buffer[i] == true && buffer[1+i] == false)
|
|
{
|
|
// store bit's end offset
|
|
bitOffsets[bitCounter] = i+1;
|
|
|
|
// if it's the A button store offset of the falling edge
|
|
if(bitCounter == 0) bitAfallingOffset = i+1;
|
|
|
|
// if it's the B button calculate the bit Resolution
|
|
if(bitCounter == 1) bitResolution = (i+1) - bitAfallingOffset;
|
|
|
|
// increment bit counter
|
|
bitCounter++;
|
|
}
|
|
}
|
|
|
|
Serial.printf("Bit resolution is %i \n",bitResolution);
|
|
|
|
// calculate bit's beginning offsets by subtracting resolution
|
|
for(int i = 0;i < 32;i++)
|
|
{
|
|
bitOffsets[i] -= bitResolution;
|
|
Serial.printf("beginning of bit %i detected @ begin+%i \n",i+1,bitOffsets[i]);
|
|
}
|
|
|
|
|
|
} |