mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 23:08:53 -05:00
Update gcn64txrx code for multiple channels
This commit is contained in:
parent
0c8dc9e7de
commit
fb43524d34
12
Makefile
12
Makefile
@ -16,6 +16,18 @@ all: $(HEXFILE)
|
|||||||
clean:
|
clean:
|
||||||
rm -f $(PROGNAME).elf $(PROGNAME).hex $(PROGNAME).map $(OBJS)
|
rm -f $(PROGNAME).elf $(PROGNAME).hex $(PROGNAME).map $(OBJS)
|
||||||
|
|
||||||
|
gcn64txrx0.o: gcn64txrx.S
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@ -DSUFFIX=0 -DGCN64_DATA_BIT=0
|
||||||
|
|
||||||
|
gcn64txrx1.o: gcn64txrx.S
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@ -DSUFFIX=1 -DGCN64_DATA_BIT=2
|
||||||
|
|
||||||
|
gcn64txrx2.o: gcn64txrx.S
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@ -DSUFFIX=2 -DGCN64_DATA_BIT=1
|
||||||
|
|
||||||
|
gcn64txrx3.o: gcn64txrx.S
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@ -DSUFFIX=3 -DGCN64_DATA_BIT=3
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
OBJS=main.o usb.o usbpad.o mappings.o gcn64_protocol.o n64.o gamecube.o usart1.o bootloader.o eeprom.o config.o hiddata.o usbstrings.o intervaltimer.o version.o gcn64txrx.o gamepads.o
|
OBJS=main.o usb.o usbpad.o mappings.o gcn64_protocol.o n64.o gamecube.o usart1.o bootloader.o eeprom.o config.o hiddata.o usbstrings.o intervaltimer.o version.o gcn64txrx0.o gcn64txrx1.o gcn64txrx2.o gcn64txrx3.o gamepads.o
|
||||||
VERSIONSTR=\"3.2.1\"
|
VERSIONSTR=\"3.2.1\"
|
||||||
VERSIONSTR_SHORT=\"3.2\"
|
VERSIONSTR_SHORT=\"3.2\"
|
||||||
|
@ -118,7 +118,7 @@ static char gamecubeUpdate()
|
|||||||
tmpdata[1] = GC_GETSTATUS2;
|
tmpdata[1] = GC_GETSTATUS2;
|
||||||
tmpdata[2] = GC_GETSTATUS3(gc_rumbling);
|
tmpdata[2] = GC_GETSTATUS3(gc_rumbling);
|
||||||
|
|
||||||
count = gcn64_transaction(tmpdata, 3, tmpdata, GC_GETSTATUS_REPLY_LENGTH);
|
count = gcn64_transaction(GCN64_CHANNEL_0, tmpdata, 3, tmpdata, GC_GETSTATUS_REPLY_LENGTH);
|
||||||
if (count != GC_GETSTATUS_REPLY_LENGTH) {
|
if (count != GC_GETSTATUS_REPLY_LENGTH) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,19 @@
|
|||||||
#define GCN64_DATA_PORT PORTD
|
#define GCN64_DATA_PORT PORTD
|
||||||
#define GCN64_DATA_DDR DDRD
|
#define GCN64_DATA_DDR DDRD
|
||||||
#define GCN64_DATA_PIN PIND
|
#define GCN64_DATA_PIN PIND
|
||||||
#define GCN64_DATA_BIT (1<<0)
|
#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
|
#define GCN64_BIT_NUM_S "0" // for asm
|
||||||
#else
|
#else
|
||||||
#define GCN64_DATA_PORT PORTA
|
#define GCN64_DATA_PORT PORTA
|
||||||
#define GCN64_DATA_DDR DDRA
|
#define GCN64_DATA_DDR DDRA
|
||||||
#define GCN64_DATA_PIN PINA
|
#define GCN64_DATA_PIN PINA
|
||||||
#define GCN64_DATA_BIT (1<<0)
|
#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
|
#define GCN64_BIT_NUM_S "0" // for asm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -46,11 +52,11 @@
|
|||||||
void gcn64protocol_hwinit(void)
|
void gcn64protocol_hwinit(void)
|
||||||
{
|
{
|
||||||
// data as input
|
// data as input
|
||||||
GCN64_DATA_DDR &= ~(GCN64_DATA_BIT);
|
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
|
// keep data low. By toggling the direction, we make the
|
||||||
// pin act as an open-drain output.
|
// pin act as an open-drain output.
|
||||||
GCN64_DATA_PORT &= ~GCN64_DATA_BIT;
|
GCN64_DATA_PORT &= ~(GCN64_DATA_BIT0 | GCN64_DATA_BIT1 | GCN64_DATA_BIT2 | GCN64_DATA_BIT3);
|
||||||
|
|
||||||
/* debug bit PORTB4 (MISO) */
|
/* debug bit PORTB4 (MISO) */
|
||||||
DDRB |= 0x10;
|
DDRB |= 0x10;
|
||||||
@ -59,11 +65,15 @@ void gcn64protocol_hwinit(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Send n data bytes + stop bit, wait for answer.
|
* \brief Send n data bytes + stop bit, wait for answer.
|
||||||
* \return The number of bytes received, 0 on timeout/error.
|
|
||||||
*
|
*
|
||||||
* The result is in gcn64_workbuf.
|
* \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(const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max)
|
unsigned char gcn64_transaction(unsigned char chn, const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
unsigned char sreg = SREG;
|
unsigned char sreg = SREG;
|
||||||
@ -81,8 +91,8 @@ unsigned char gcn64_transaction(const unsigned char *tx, int tx_len, unsigned ch
|
|||||||
#ifdef DISABLE_INTS_DURING_COMM
|
#ifdef DISABLE_INTS_DURING_COMM
|
||||||
cli();
|
cli();
|
||||||
#endif
|
#endif
|
||||||
gcn64_sendBytes(tx, tx_len);
|
gcn64_sendBytes0(tx, tx_len);
|
||||||
count = gcn64_receiveBytes(rx, rx_max);
|
count = gcn64_receiveBytes0(rx, rx_max);
|
||||||
SREG = sreg;
|
SREG = sreg;
|
||||||
|
|
||||||
if (count == 0xff) {
|
if (count == 0xff) {
|
||||||
@ -119,14 +129,14 @@ unsigned char gcn64_transaction(const unsigned char *tx, int tx_len, unsigned ch
|
|||||||
#if (GC_GETID != N64_GET_CAPABILITIES)
|
#if (GC_GETID != N64_GET_CAPABILITIES)
|
||||||
#error N64 vs GC detection commnad broken
|
#error N64 vs GC detection commnad broken
|
||||||
#endif
|
#endif
|
||||||
int gcn64_detectController(void)
|
int gcn64_detectController(unsigned char chn)
|
||||||
{
|
{
|
||||||
unsigned char tmp = GC_GETID;
|
unsigned char tmp = GC_GETID;
|
||||||
unsigned char count;
|
unsigned char count;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
unsigned char data[4];
|
unsigned char data[4];
|
||||||
|
|
||||||
count = gcn64_transaction(&tmp, 1, data, sizeof(data));
|
count = gcn64_transaction(chn, &tmp, 1, data, sizeof(data));
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return CONTROLLER_IS_ABSENT;
|
return CONTROLLER_IS_ABSENT;
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,12 @@
|
|||||||
#define GC_KEY_ENTER 0x61
|
#define GC_KEY_ENTER 0x61
|
||||||
|
|
||||||
void gcn64protocol_hwinit(void);
|
void gcn64protocol_hwinit(void);
|
||||||
int gcn64_detectController(void);
|
|
||||||
unsigned char gcn64_transaction(const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max);
|
#define GCN64_CHANNEL_0 0
|
||||||
|
#define GCN64_CHANNEL_1 1
|
||||||
|
#define GCN64_CHANNEL_2 2
|
||||||
|
#define GCN64_CHANNEL_3 3
|
||||||
|
int gcn64_detectController(unsigned char chn);
|
||||||
|
unsigned char gcn64_transaction(unsigned char chn, const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max);
|
||||||
|
|
||||||
#endif // _gcn64_protocol_h__
|
#endif // _gcn64_protocol_h__
|
||||||
|
22
gcn64txrx.S
22
gcn64txrx.S
@ -1,8 +1,20 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
; When compiling, you must define the following.
|
||||||
|
;
|
||||||
|
; SUFFIX : The suffix for exported function (eg: Set to 0 to generate gcn64_sendBytes0)
|
||||||
|
; GCN64_DATA_BIT : The bit number in the port.
|
||||||
|
;
|
||||||
|
; Port and Pin IOs are defined below.
|
||||||
|
;
|
||||||
|
|
||||||
|
#define CONCAT(a,b) a##b
|
||||||
|
#define EXPORT_SYMBOL(a, b) .global CONCAT(a,b)
|
||||||
|
#define FUNCTION(a, b) CONCAT(a,b)
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.global gcn64_sendBytes
|
EXPORT_SYMBOL(gcn64_sendBytes, SUFFIX)
|
||||||
.global gcn64_receiveBytes
|
EXPORT_SYMBOL(gcn64_receiveBytes, SUFFIX)
|
||||||
|
|
||||||
#define xl r26
|
#define xl r26
|
||||||
#define xh r27
|
#define xh r27
|
||||||
@ -24,7 +36,7 @@
|
|||||||
#define GCN64_DATA_DDR _SFR_IO_ADDR(DDRD)
|
#define GCN64_DATA_DDR _SFR_IO_ADDR(DDRD)
|
||||||
#define GCN64_DATA_PIN _SFR_IO_ADDR(PIND)
|
#define GCN64_DATA_PIN _SFR_IO_ADDR(PIND)
|
||||||
#endif
|
#endif
|
||||||
#define GCN64_DATA_BIT 0
|
;#define GCN64_DATA_BIT 0
|
||||||
|
|
||||||
#if F_CPU != 16000000L
|
#if F_CPU != 16000000L
|
||||||
#error Only 16MHz clock supported
|
#error Only 16MHz clock supported
|
||||||
@ -50,7 +62,7 @@
|
|||||||
; r24,r25 : dstbuf
|
; r24,r25 : dstbuf
|
||||||
; r22 : max bytes (for fututre use)
|
; r22 : max bytes (for fututre use)
|
||||||
; return: count in r24,r25 (0xff: Error, 0xfe: Overflow [max_bytes too low])
|
; return: count in r24,r25 (0xff: Error, 0xfe: Overflow [max_bytes too low])
|
||||||
gcn64_receiveBytes:
|
FUNCTION(gcn64_receiveBytes, SUFFIX):
|
||||||
clr xl
|
clr xl
|
||||||
clr xh
|
clr xh
|
||||||
mov zl, r24
|
mov zl, r24
|
||||||
@ -149,7 +161,7 @@ rxdone:
|
|||||||
* A stop bit is added at thy end of the packet.
|
* A stop bit is added at thy end of the packet.
|
||||||
*
|
*
|
||||||
************************************************/
|
************************************************/
|
||||||
gcn64_sendBytes:
|
FUNCTION(gcn64_sendBytes, SUFFIX):
|
||||||
; Move r23,r24 pointer to z
|
; Move r23,r24 pointer to z
|
||||||
mov zl, r24
|
mov zl, r24
|
||||||
mov zh, r25
|
mov zh, r25
|
||||||
|
10
gcn64txrx.h
10
gcn64txrx.h
@ -1,7 +1,10 @@
|
|||||||
#ifndef _gcn64txrx_h__
|
#ifndef _gcn64txrx_h__
|
||||||
#define _gcn64txrx_h__
|
#define _gcn64txrx_h__
|
||||||
|
|
||||||
void gcn64_sendBytes(const unsigned char *data, unsigned char n_bytes);
|
void gcn64_sendBytes0(const unsigned char *data, unsigned char n_bytes);
|
||||||
|
void gcn64_sendBytes1(const unsigned char *data, unsigned char n_bytes);
|
||||||
|
void gcn64_sendBytes2(const unsigned char *data, unsigned char n_bytes);
|
||||||
|
void gcn64_sendBytes3(const unsigned char *data, unsigned char n_bytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Receive up to \max_bytes bytes
|
* \brief Receive up to \max_bytes bytes
|
||||||
@ -9,6 +12,9 @@ void gcn64_sendBytes(const unsigned char *data, unsigned char n_bytes);
|
|||||||
* \param max_bytes The maximum number of bytes
|
* \param max_bytes The maximum number of bytes
|
||||||
* \return The number of received bytes. 0xFF in case of error, 0xFE in case of overflow (max_bytes too small)
|
* \return The number of received bytes. 0xFF in case of error, 0xFE in case of overflow (max_bytes too small)
|
||||||
*/
|
*/
|
||||||
unsigned char gcn64_receiveBytes(unsigned char *dstbuf, unsigned char max_bytes);
|
unsigned char gcn64_receiveBytes0(unsigned char *dstbuf, unsigned char max_bytes);
|
||||||
|
unsigned char gcn64_receiveBytes1(unsigned char *dstbuf, unsigned char max_bytes);
|
||||||
|
unsigned char gcn64_receiveBytes2(unsigned char *dstbuf, unsigned char max_bytes);
|
||||||
|
unsigned char gcn64_receiveBytes3(unsigned char *dstbuf, unsigned char max_bytes);
|
||||||
|
|
||||||
#endif // _gcn64txrx_h__
|
#endif // _gcn64txrx_h__
|
||||||
|
@ -76,7 +76,7 @@ uint8_t hiddata_set_report(const struct usb_request *rq, const uint8_t *dat, uin
|
|||||||
|
|
||||||
static void hiddata_processCommandBuffer(void)
|
static void hiddata_processCommandBuffer(void)
|
||||||
{
|
{
|
||||||
//unsigned char channel;
|
unsigned char channel;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
@ -95,8 +95,8 @@ static void hiddata_processCommandBuffer(void)
|
|||||||
case RQ_GCN64_RAW_SI_COMMAND:
|
case RQ_GCN64_RAW_SI_COMMAND:
|
||||||
// TODO : Range checking
|
// TODO : Range checking
|
||||||
// cmdbuf[] : RQ, CHN, LEN, data[]
|
// cmdbuf[] : RQ, CHN, LEN, data[]
|
||||||
//channel = cmdbuf[1];
|
channel = cmdbuf[1];
|
||||||
cmdbuf_len = gcn64_transaction(cmdbuf+3, cmdbuf[2], cmdbuf + 3, CMDBUF_SIZE-3);
|
cmdbuf_len = gcn64_transaction(channel, cmdbuf+3, cmdbuf[2], cmdbuf + 3, CMDBUF_SIZE-3);
|
||||||
cmdbuf[2] = cmdbuf_len;
|
cmdbuf[2] = cmdbuf_len;
|
||||||
cmdbuf_len += 3; // Answer: RQ, CHN, LEN, data[]
|
cmdbuf_len += 3; // Answer: RQ, CHN, LEN, data[]
|
||||||
break;
|
break;
|
||||||
|
2
main.c
2
main.c
@ -235,7 +235,7 @@ unsigned char current_pad_type = CONTROLLER_IS_ABSENT;
|
|||||||
|
|
||||||
Gamepad *detectPad(void)
|
Gamepad *detectPad(void)
|
||||||
{
|
{
|
||||||
current_pad_type = gcn64_detectController();
|
current_pad_type = gcn64_detectController(GCN64_CHANNEL_0);
|
||||||
|
|
||||||
switch (current_pad_type)
|
switch (current_pad_type)
|
||||||
{
|
{
|
||||||
|
10
n64.c
10
n64.c
@ -60,7 +60,7 @@ static char initRumble(void)
|
|||||||
tmpdata[2] = 0x01;
|
tmpdata[2] = 0x01;
|
||||||
memset(tmpdata+3, 0x80, 32);
|
memset(tmpdata+3, 0x80, 32);
|
||||||
|
|
||||||
count = gcn64_transaction(tmpdata, 35, data, sizeof(data));
|
count = gcn64_transaction(GCN64_CHANNEL_0, tmpdata, 35, data, sizeof(data));
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ static char controlRumble(char enable)
|
|||||||
tmpdata[1] = 0xc0;
|
tmpdata[1] = 0xc0;
|
||||||
tmpdata[2] = 0x1b;
|
tmpdata[2] = 0x1b;
|
||||||
memset(tmpdata+3, enable ? 0x01 : 0x00, 32);
|
memset(tmpdata+3, enable ? 0x01 : 0x00, 32);
|
||||||
count = gcn64_transaction(tmpdata, 35, data, sizeof(data));
|
count = gcn64_transaction(GCN64_CHANNEL_0, tmpdata, 35, data, sizeof(data));
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ static char n64Update(void)
|
|||||||
* Bit 1 tells is if there was something connected that has been removed.
|
* Bit 1 tells is if there was something connected that has been removed.
|
||||||
*/
|
*/
|
||||||
tmpdata[0] = N64_GET_CAPABILITIES;
|
tmpdata[0] = N64_GET_CAPABILITIES;
|
||||||
count = gcn64_transaction(tmpdata, 1, caps, sizeof(caps));
|
count = gcn64_transaction(GCN64_CHANNEL_0, tmpdata, 1, caps, sizeof(caps));
|
||||||
if (count != N64_CAPS_REPLY_LENGTH) {
|
if (count != N64_CAPS_REPLY_LENGTH) {
|
||||||
// a failed read could mean the pack or controller was gone. Init
|
// a failed read could mean the pack or controller was gone. Init
|
||||||
// will be necessary next time we detect a pack is present.
|
// will be necessary next time we detect a pack is present.
|
||||||
@ -172,7 +172,7 @@ static char n64Update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmpdata[0] = N64_GET_STATUS;
|
tmpdata[0] = N64_GET_STATUS;
|
||||||
count = gcn64_transaction(tmpdata, 1, status, sizeof(status));
|
count = gcn64_transaction(GCN64_CHANNEL_0, tmpdata, 1, status, sizeof(status));
|
||||||
if (count != N64_GET_STATUS_REPLY_LENGTH) {
|
if (count != N64_GET_STATUS_REPLY_LENGTH) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ static char n64Probe(void)
|
|||||||
_delay_ms(30);
|
_delay_ms(30);
|
||||||
|
|
||||||
tmp = N64_GET_CAPABILITIES;
|
tmp = N64_GET_CAPABILITIES;
|
||||||
count = gcn64_transaction(&tmp, 1, data, sizeof(data));
|
count = gcn64_transaction(GCN64_CHANNEL_0, &tmp, 1, data, sizeof(data));
|
||||||
|
|
||||||
if (count == N64_CAPS_REPLY_LENGTH) {
|
if (count == N64_CAPS_REPLY_LENGTH) {
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user