David Rimer
/
Gigatron_Emulator
A small emulator for the gigatron created for the STM32F746G-DISCO and an NES wii controller
Diff: WiiClassicControllerReader/WiiClassicControllerReader.cpp
- Revision:
- 1:4c1f3d32fceb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WiiClassicControllerReader/WiiClassicControllerReader.cpp Thu Mar 05 01:33:52 2020 +0000 @@ -0,0 +1,148 @@ +/* +* WiiClassicControllerReader. A program allowing the output of one or two +* Wii Classic Controllers to be read via I2C and decoded for use, using the mbed +* microcontroller and its associated libraries. +* +* Written by Alfredo Guerrero <alfredog83@gmail.com> for the mbedGC open-source +* game console <http://www.mbedgc.com>. Based on the original code for +* the WiiNunchuckReader written by Petras Saduikis <petras@petras.co.uk>. +* +* This file is part of WiiClassicControllerReader. +* +* WiiClassicControllerReader is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* WiiClassicControllerReader is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You can find a copy of the GNU General Public License at <http://www.gnu.org/licenses/>. +*/ + +#include "WiiClassicControllerReader.h" + +// constructor +WiiClassicControllerReader::WiiClassicControllerReader(PinName sda, PinName scl) : + controllerPort(sda, scl), + ljoyX(0), ljoyY(0), rjoyX(0), rjoyY(0), buttonX(0), buttonY(0), buttonA(0), + buttonB(0), buttonZL(0), buttonZR(0), buttonLT(0), buttonRT(0), buttonLC(0), + buttonRC(0), buttonHOME(0), buttonSELECT(0), buttonSTART(0), buttonDU(0), + buttonDD(0), buttonDL(0), buttonDR(0), controllerInit(false) +{ +} + +void WiiClassicControllerReader::RequestRead() +{ + // don't expect client to remember to send an init to the nunchuck + // so do it for them here + if (!controllerInit) + { + controllerInit = ControllerInit(); + } + + if (controllerInit) // don't start reading if init failed + { + if (ControllerRead()) + { + // only decode successful reads + ControllerDecode(); + } + } +} + +bool WiiClassicControllerReader::ControllerInit() +{ + bool success = false; + + const BYTE cmd[] = {CONTROLLER_REGADDR, 0x00}; + if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) success = true; + + return success; +} + +bool WiiClassicControllerReader::ControllerRead() +{ + bool success = false; + + // write the address we want to read from + const BYTE cmd[] = {0x00}; + if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) + { + // the Wii Classic Controller is non-standard I2C + // and can't manage setting the read address and immediately supplying the data + // so wait a bit + wait(I2C_READ_DELAY); + + if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf))) success = true; + } + + return success; +} + +bool WiiClassicControllerReader::ControllerWriteCmd() +{ + bool success = false; + + // write the address we want to read from + const BYTE cmd[] = {0x00}; + if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) + { + success = true; + } + + return success; +} + +bool WiiClassicControllerReader::ControllerReadCmd() +{ + bool success = false; + + if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf))) + { + success = true; + } + + return success; +} + +void WiiClassicControllerReader::ControllerDecode() +{ + ljoyX = (int)readBuf[0] & MASK_LX; + ljoyY = (int)readBuf[1] & MASK_LY; + rjoyY = (int)readBuf[2] & MASK_RY; + buttonRT = (int)readBuf[3] & MASK_RT; + buttonRC = (int)readBuf[4] & MASK_RC_DL; + buttonSTART = (int)readBuf[4] & MASK_BSTART_ZR; + buttonHOME = (int)readBuf[4] & MASK_BHOME_X; + buttonSELECT = (int)readBuf[4] & MASK_BSELECT_A; + buttonLC = (int)readBuf[4] & MASK_LC_Y; + buttonDD = (int)readBuf[4] & MASK_BDD_B; + buttonDR = (int)readBuf[4] & MASK_BDR_ZL; + buttonDU = (int)readBuf[5] & MASK_BDU; + buttonDL = (int)readBuf[5] & MASK_RC_DL; + buttonZR = (int)readBuf[5] & MASK_BSTART_ZR; + buttonX = (int)readBuf[5] & MASK_BHOME_X; + buttonA = (int)readBuf[5] & MASK_BSELECT_A; + buttonY = (int)readBuf[5] & MASK_LC_Y; + buttonB = (int)readBuf[5] & MASK_BDD_B; + buttonZL = (int)readBuf[5] & MASK_BDR_ZL; + + // the RjoyX axis and LT values are really 5 bit values + // so shift the 2 bit values read from the controller + // 3 bits to the right + rjoyX = ( (int)readBuf[0] & MASK_RX34 ) << 3; + buttonLT = ( (int)readBuf[2] & MASK_LT34 ) << 3; + + // and for each value add bit 2, bit 1, and bit 0 + // as required + if (readBuf[2] & MASK_BDR_ZL) rjoyX += 1; + if (readBuf[1] & MASK_BDD_B) rjoyX += 2; + if (readBuf[1] & MASK_BDR_ZL) rjoyX += 4; + if (readBuf[3] & MASK_LC_Y) buttonLT += 1; + if (readBuf[3] & MASK_BDD_B) buttonLT += 2; + if (readBuf[3] & MASK_BDR_ZL) buttonLT += 4; + +} \ No newline at end of file