David Rimer
/
Gigatron_Emulator
A small emulator for the gigatron created for the STM32F746G-DISCO and an NES wii controller
WiiClassicControllerReader/WiiClassicControllerReader.cpp@1:4c1f3d32fceb, 2020-03-05 (annotated)
- Committer:
- davidr99
- Date:
- Thu Mar 05 01:33:52 2020 +0000
- Revision:
- 1:4c1f3d32fceb
Emulator all one project
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
davidr99 | 1:4c1f3d32fceb | 1 | /* |
davidr99 | 1:4c1f3d32fceb | 2 | * WiiClassicControllerReader. A program allowing the output of one or two |
davidr99 | 1:4c1f3d32fceb | 3 | * Wii Classic Controllers to be read via I2C and decoded for use, using the mbed |
davidr99 | 1:4c1f3d32fceb | 4 | * microcontroller and its associated libraries. |
davidr99 | 1:4c1f3d32fceb | 5 | * |
davidr99 | 1:4c1f3d32fceb | 6 | * Written by Alfredo Guerrero <alfredog83@gmail.com> for the mbedGC open-source |
davidr99 | 1:4c1f3d32fceb | 7 | * game console <http://www.mbedgc.com>. Based on the original code for |
davidr99 | 1:4c1f3d32fceb | 8 | * the WiiNunchuckReader written by Petras Saduikis <petras@petras.co.uk>. |
davidr99 | 1:4c1f3d32fceb | 9 | * |
davidr99 | 1:4c1f3d32fceb | 10 | * This file is part of WiiClassicControllerReader. |
davidr99 | 1:4c1f3d32fceb | 11 | * |
davidr99 | 1:4c1f3d32fceb | 12 | * WiiClassicControllerReader is free software: you can redistribute it and/or modify |
davidr99 | 1:4c1f3d32fceb | 13 | * it under the terms of the GNU General Public License as published by |
davidr99 | 1:4c1f3d32fceb | 14 | * the Free Software Foundation, either version 3 of the License, or |
davidr99 | 1:4c1f3d32fceb | 15 | * (at your option) any later version. |
davidr99 | 1:4c1f3d32fceb | 16 | * |
davidr99 | 1:4c1f3d32fceb | 17 | * WiiClassicControllerReader is distributed in the hope that it will be useful, |
davidr99 | 1:4c1f3d32fceb | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
davidr99 | 1:4c1f3d32fceb | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
davidr99 | 1:4c1f3d32fceb | 20 | * GNU General Public License for more details. |
davidr99 | 1:4c1f3d32fceb | 21 | * |
davidr99 | 1:4c1f3d32fceb | 22 | * You can find a copy of the GNU General Public License at <http://www.gnu.org/licenses/>. |
davidr99 | 1:4c1f3d32fceb | 23 | */ |
davidr99 | 1:4c1f3d32fceb | 24 | |
davidr99 | 1:4c1f3d32fceb | 25 | #include "WiiClassicControllerReader.h" |
davidr99 | 1:4c1f3d32fceb | 26 | |
davidr99 | 1:4c1f3d32fceb | 27 | // constructor |
davidr99 | 1:4c1f3d32fceb | 28 | WiiClassicControllerReader::WiiClassicControllerReader(PinName sda, PinName scl) : |
davidr99 | 1:4c1f3d32fceb | 29 | controllerPort(sda, scl), |
davidr99 | 1:4c1f3d32fceb | 30 | ljoyX(0), ljoyY(0), rjoyX(0), rjoyY(0), buttonX(0), buttonY(0), buttonA(0), |
davidr99 | 1:4c1f3d32fceb | 31 | buttonB(0), buttonZL(0), buttonZR(0), buttonLT(0), buttonRT(0), buttonLC(0), |
davidr99 | 1:4c1f3d32fceb | 32 | buttonRC(0), buttonHOME(0), buttonSELECT(0), buttonSTART(0), buttonDU(0), |
davidr99 | 1:4c1f3d32fceb | 33 | buttonDD(0), buttonDL(0), buttonDR(0), controllerInit(false) |
davidr99 | 1:4c1f3d32fceb | 34 | { |
davidr99 | 1:4c1f3d32fceb | 35 | } |
davidr99 | 1:4c1f3d32fceb | 36 | |
davidr99 | 1:4c1f3d32fceb | 37 | void WiiClassicControllerReader::RequestRead() |
davidr99 | 1:4c1f3d32fceb | 38 | { |
davidr99 | 1:4c1f3d32fceb | 39 | // don't expect client to remember to send an init to the nunchuck |
davidr99 | 1:4c1f3d32fceb | 40 | // so do it for them here |
davidr99 | 1:4c1f3d32fceb | 41 | if (!controllerInit) |
davidr99 | 1:4c1f3d32fceb | 42 | { |
davidr99 | 1:4c1f3d32fceb | 43 | controllerInit = ControllerInit(); |
davidr99 | 1:4c1f3d32fceb | 44 | } |
davidr99 | 1:4c1f3d32fceb | 45 | |
davidr99 | 1:4c1f3d32fceb | 46 | if (controllerInit) // don't start reading if init failed |
davidr99 | 1:4c1f3d32fceb | 47 | { |
davidr99 | 1:4c1f3d32fceb | 48 | if (ControllerRead()) |
davidr99 | 1:4c1f3d32fceb | 49 | { |
davidr99 | 1:4c1f3d32fceb | 50 | // only decode successful reads |
davidr99 | 1:4c1f3d32fceb | 51 | ControllerDecode(); |
davidr99 | 1:4c1f3d32fceb | 52 | } |
davidr99 | 1:4c1f3d32fceb | 53 | } |
davidr99 | 1:4c1f3d32fceb | 54 | } |
davidr99 | 1:4c1f3d32fceb | 55 | |
davidr99 | 1:4c1f3d32fceb | 56 | bool WiiClassicControllerReader::ControllerInit() |
davidr99 | 1:4c1f3d32fceb | 57 | { |
davidr99 | 1:4c1f3d32fceb | 58 | bool success = false; |
davidr99 | 1:4c1f3d32fceb | 59 | |
davidr99 | 1:4c1f3d32fceb | 60 | const BYTE cmd[] = {CONTROLLER_REGADDR, 0x00}; |
davidr99 | 1:4c1f3d32fceb | 61 | if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) success = true; |
davidr99 | 1:4c1f3d32fceb | 62 | |
davidr99 | 1:4c1f3d32fceb | 63 | return success; |
davidr99 | 1:4c1f3d32fceb | 64 | } |
davidr99 | 1:4c1f3d32fceb | 65 | |
davidr99 | 1:4c1f3d32fceb | 66 | bool WiiClassicControllerReader::ControllerRead() |
davidr99 | 1:4c1f3d32fceb | 67 | { |
davidr99 | 1:4c1f3d32fceb | 68 | bool success = false; |
davidr99 | 1:4c1f3d32fceb | 69 | |
davidr99 | 1:4c1f3d32fceb | 70 | // write the address we want to read from |
davidr99 | 1:4c1f3d32fceb | 71 | const BYTE cmd[] = {0x00}; |
davidr99 | 1:4c1f3d32fceb | 72 | if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) |
davidr99 | 1:4c1f3d32fceb | 73 | { |
davidr99 | 1:4c1f3d32fceb | 74 | // the Wii Classic Controller is non-standard I2C |
davidr99 | 1:4c1f3d32fceb | 75 | // and can't manage setting the read address and immediately supplying the data |
davidr99 | 1:4c1f3d32fceb | 76 | // so wait a bit |
davidr99 | 1:4c1f3d32fceb | 77 | wait(I2C_READ_DELAY); |
davidr99 | 1:4c1f3d32fceb | 78 | |
davidr99 | 1:4c1f3d32fceb | 79 | if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf))) success = true; |
davidr99 | 1:4c1f3d32fceb | 80 | } |
davidr99 | 1:4c1f3d32fceb | 81 | |
davidr99 | 1:4c1f3d32fceb | 82 | return success; |
davidr99 | 1:4c1f3d32fceb | 83 | } |
davidr99 | 1:4c1f3d32fceb | 84 | |
davidr99 | 1:4c1f3d32fceb | 85 | bool WiiClassicControllerReader::ControllerWriteCmd() |
davidr99 | 1:4c1f3d32fceb | 86 | { |
davidr99 | 1:4c1f3d32fceb | 87 | bool success = false; |
davidr99 | 1:4c1f3d32fceb | 88 | |
davidr99 | 1:4c1f3d32fceb | 89 | // write the address we want to read from |
davidr99 | 1:4c1f3d32fceb | 90 | const BYTE cmd[] = {0x00}; |
davidr99 | 1:4c1f3d32fceb | 91 | if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) |
davidr99 | 1:4c1f3d32fceb | 92 | { |
davidr99 | 1:4c1f3d32fceb | 93 | success = true; |
davidr99 | 1:4c1f3d32fceb | 94 | } |
davidr99 | 1:4c1f3d32fceb | 95 | |
davidr99 | 1:4c1f3d32fceb | 96 | return success; |
davidr99 | 1:4c1f3d32fceb | 97 | } |
davidr99 | 1:4c1f3d32fceb | 98 | |
davidr99 | 1:4c1f3d32fceb | 99 | bool WiiClassicControllerReader::ControllerReadCmd() |
davidr99 | 1:4c1f3d32fceb | 100 | { |
davidr99 | 1:4c1f3d32fceb | 101 | bool success = false; |
davidr99 | 1:4c1f3d32fceb | 102 | |
davidr99 | 1:4c1f3d32fceb | 103 | if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf))) |
davidr99 | 1:4c1f3d32fceb | 104 | { |
davidr99 | 1:4c1f3d32fceb | 105 | success = true; |
davidr99 | 1:4c1f3d32fceb | 106 | } |
davidr99 | 1:4c1f3d32fceb | 107 | |
davidr99 | 1:4c1f3d32fceb | 108 | return success; |
davidr99 | 1:4c1f3d32fceb | 109 | } |
davidr99 | 1:4c1f3d32fceb | 110 | |
davidr99 | 1:4c1f3d32fceb | 111 | void WiiClassicControllerReader::ControllerDecode() |
davidr99 | 1:4c1f3d32fceb | 112 | { |
davidr99 | 1:4c1f3d32fceb | 113 | ljoyX = (int)readBuf[0] & MASK_LX; |
davidr99 | 1:4c1f3d32fceb | 114 | ljoyY = (int)readBuf[1] & MASK_LY; |
davidr99 | 1:4c1f3d32fceb | 115 | rjoyY = (int)readBuf[2] & MASK_RY; |
davidr99 | 1:4c1f3d32fceb | 116 | buttonRT = (int)readBuf[3] & MASK_RT; |
davidr99 | 1:4c1f3d32fceb | 117 | buttonRC = (int)readBuf[4] & MASK_RC_DL; |
davidr99 | 1:4c1f3d32fceb | 118 | buttonSTART = (int)readBuf[4] & MASK_BSTART_ZR; |
davidr99 | 1:4c1f3d32fceb | 119 | buttonHOME = (int)readBuf[4] & MASK_BHOME_X; |
davidr99 | 1:4c1f3d32fceb | 120 | buttonSELECT = (int)readBuf[4] & MASK_BSELECT_A; |
davidr99 | 1:4c1f3d32fceb | 121 | buttonLC = (int)readBuf[4] & MASK_LC_Y; |
davidr99 | 1:4c1f3d32fceb | 122 | buttonDD = (int)readBuf[4] & MASK_BDD_B; |
davidr99 | 1:4c1f3d32fceb | 123 | buttonDR = (int)readBuf[4] & MASK_BDR_ZL; |
davidr99 | 1:4c1f3d32fceb | 124 | buttonDU = (int)readBuf[5] & MASK_BDU; |
davidr99 | 1:4c1f3d32fceb | 125 | buttonDL = (int)readBuf[5] & MASK_RC_DL; |
davidr99 | 1:4c1f3d32fceb | 126 | buttonZR = (int)readBuf[5] & MASK_BSTART_ZR; |
davidr99 | 1:4c1f3d32fceb | 127 | buttonX = (int)readBuf[5] & MASK_BHOME_X; |
davidr99 | 1:4c1f3d32fceb | 128 | buttonA = (int)readBuf[5] & MASK_BSELECT_A; |
davidr99 | 1:4c1f3d32fceb | 129 | buttonY = (int)readBuf[5] & MASK_LC_Y; |
davidr99 | 1:4c1f3d32fceb | 130 | buttonB = (int)readBuf[5] & MASK_BDD_B; |
davidr99 | 1:4c1f3d32fceb | 131 | buttonZL = (int)readBuf[5] & MASK_BDR_ZL; |
davidr99 | 1:4c1f3d32fceb | 132 | |
davidr99 | 1:4c1f3d32fceb | 133 | // the RjoyX axis and LT values are really 5 bit values |
davidr99 | 1:4c1f3d32fceb | 134 | // so shift the 2 bit values read from the controller |
davidr99 | 1:4c1f3d32fceb | 135 | // 3 bits to the right |
davidr99 | 1:4c1f3d32fceb | 136 | rjoyX = ( (int)readBuf[0] & MASK_RX34 ) << 3; |
davidr99 | 1:4c1f3d32fceb | 137 | buttonLT = ( (int)readBuf[2] & MASK_LT34 ) << 3; |
davidr99 | 1:4c1f3d32fceb | 138 | |
davidr99 | 1:4c1f3d32fceb | 139 | // and for each value add bit 2, bit 1, and bit 0 |
davidr99 | 1:4c1f3d32fceb | 140 | // as required |
davidr99 | 1:4c1f3d32fceb | 141 | if (readBuf[2] & MASK_BDR_ZL) rjoyX += 1; |
davidr99 | 1:4c1f3d32fceb | 142 | if (readBuf[1] & MASK_BDD_B) rjoyX += 2; |
davidr99 | 1:4c1f3d32fceb | 143 | if (readBuf[1] & MASK_BDR_ZL) rjoyX += 4; |
davidr99 | 1:4c1f3d32fceb | 144 | if (readBuf[3] & MASK_LC_Y) buttonLT += 1; |
davidr99 | 1:4c1f3d32fceb | 145 | if (readBuf[3] & MASK_BDD_B) buttonLT += 2; |
davidr99 | 1:4c1f3d32fceb | 146 | if (readBuf[3] & MASK_BDR_ZL) buttonLT += 4; |
davidr99 | 1:4c1f3d32fceb | 147 | |
davidr99 | 1:4c1f3d32fceb | 148 | } |