/* gc_n64_usb : Gamecube or N64 controller to USB adapter firmware Copyright (C) 2007-2016 Raphael Assenat This program 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. This program 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 should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include "gcn64_protocol.h" #include "gcn64txrx.h" #undef FORCE_KEYBOARD #undef TRACE_GCN64 /******** IO port definitions and options **************/ #ifndef STK525 #define GCN64_DATA_PORT PORTD #define GCN64_DATA_DDR DDRD #define GCN64_DATA_PIN PIND #define GCN64_DATA_BIT0 (1<<0) #define GCN64_DATA_BIT1 (1<<1) #define GCN64_DATA_BIT2 (1<<2) #define GCN64_DATA_BIT3 (1<<3) #define GCN64_BIT_NUM_S "0" // for asm #else #define GCN64_DATA_PORT PORTA #define GCN64_DATA_DDR DDRA #define GCN64_DATA_PIN PINA #define GCN64_DATA_BIT0 (1<<0) #define GCN64_DATA_BIT1 (1<<2) // This is not an error #define GCN64_DATA_BIT2 (1<<1) // This is not an error #define GCN64_DATA_BIT3 (1<<3) #define GCN64_BIT_NUM_S "0" // for asm #endif #define DISABLE_INTS_DURING_COMM void gcn64protocol_hwinit(void) { // data as input GCN64_DATA_DDR &= ~(GCN64_DATA_BIT0 | GCN64_DATA_BIT1 | GCN64_DATA_BIT2 | GCN64_DATA_BIT3); // keep data low. By toggling the direction, we make the // pin act as an open-drain output. GCN64_DATA_PORT &= ~(GCN64_DATA_BIT0 | GCN64_DATA_BIT1 | GCN64_DATA_BIT2 | GCN64_DATA_BIT3); /* debug bit PORTB4 (MISO) */ DDRB |= 0x10; PORTB &= ~0x10; } /** * \brief Send n data bytes + stop bit, wait for answer. * * \param chn Channel (0 to 3) * \param tx Data to be transmitted * \param tx_len Transmission length * \param rx Reception buffer * \param rx_max Buffer size * \return The number of bytes received, 0 on timeout/error. */ unsigned char gcn64_transaction(unsigned char chn, const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max) { int count; unsigned char sreg = SREG; void (*sendBytes)(const unsigned char *data, unsigned char n_bytes); unsigned char (*receiveBytes)(unsigned char *dstbuf, unsigned char max_bytes); switch(chn) { case 0: sendBytes = gcn64_sendBytes0; receiveBytes = gcn64_receiveBytes0; break; case 1: sendBytes = gcn64_sendBytes1; receiveBytes = gcn64_receiveBytes1; break; case 2: sendBytes = gcn64_sendBytes2; receiveBytes = gcn64_receiveBytes2; break; case 3: sendBytes = gcn64_sendBytes3; receiveBytes = gcn64_receiveBytes3; break; default: return 0; } #ifdef TRACE_GCN64 int i; printf("TX[%d] = { ", tx_len); for (i=0; i> 8) & 0x0F) { case 0x05: return CONTROLLER_IS_N64; case 0x09: // normal controllers case 0x0b: // Never saw this one, but it is mentionned above. return CONTROLLER_IS_GC; case 0x08: if (id == 0x0820) { // Ascii keyboard return CONTROLLER_IS_GC_KEYBOARD; } // wavebird, controller off. return CONTROLLER_IS_GC; default: return CONTROLLER_IS_UNKNOWN; } return 0; }