mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 14:58:51 -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:
|
||||
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
|
||||
$(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_SHORT=\"3.2\"
|
||||
|
@ -118,7 +118,7 @@ static char gamecubeUpdate()
|
||||
tmpdata[1] = GC_GETSTATUS2;
|
||||
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) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -31,13 +31,19 @@
|
||||
#define GCN64_DATA_PORT PORTD
|
||||
#define GCN64_DATA_DDR DDRD
|
||||
#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
|
||||
#else
|
||||
#define GCN64_DATA_PORT PORTA
|
||||
#define GCN64_DATA_DDR DDRA
|
||||
#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
|
||||
#endif
|
||||
|
||||
@ -46,11 +52,11 @@
|
||||
void gcn64protocol_hwinit(void)
|
||||
{
|
||||
// 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
|
||||
// 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) */
|
||||
DDRB |= 0x10;
|
||||
@ -59,11 +65,15 @@ void gcn64protocol_hwinit(void)
|
||||
|
||||
/**
|
||||
* \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;
|
||||
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
|
||||
cli();
|
||||
#endif
|
||||
gcn64_sendBytes(tx, tx_len);
|
||||
count = gcn64_receiveBytes(rx, rx_max);
|
||||
gcn64_sendBytes0(tx, tx_len);
|
||||
count = gcn64_receiveBytes0(rx, rx_max);
|
||||
SREG = sreg;
|
||||
|
||||
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)
|
||||
#error N64 vs GC detection commnad broken
|
||||
#endif
|
||||
int gcn64_detectController(void)
|
||||
int gcn64_detectController(unsigned char chn)
|
||||
{
|
||||
unsigned char tmp = GC_GETID;
|
||||
unsigned char count;
|
||||
unsigned short id;
|
||||
unsigned char data[4];
|
||||
|
||||
count = gcn64_transaction(&tmp, 1, data, sizeof(data));
|
||||
count = gcn64_transaction(chn, &tmp, 1, data, sizeof(data));
|
||||
if (count == 0) {
|
||||
return CONTROLLER_IS_ABSENT;
|
||||
}
|
||||
|
@ -160,7 +160,12 @@
|
||||
#define GC_KEY_ENTER 0x61
|
||||
|
||||
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__
|
||||
|
22
gcn64txrx.S
22
gcn64txrx.S
@ -1,8 +1,20 @@
|
||||
#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
|
||||
.global gcn64_sendBytes
|
||||
.global gcn64_receiveBytes
|
||||
EXPORT_SYMBOL(gcn64_sendBytes, SUFFIX)
|
||||
EXPORT_SYMBOL(gcn64_receiveBytes, SUFFIX)
|
||||
|
||||
#define xl r26
|
||||
#define xh r27
|
||||
@ -24,7 +36,7 @@
|
||||
#define GCN64_DATA_DDR _SFR_IO_ADDR(DDRD)
|
||||
#define GCN64_DATA_PIN _SFR_IO_ADDR(PIND)
|
||||
#endif
|
||||
#define GCN64_DATA_BIT 0
|
||||
;#define GCN64_DATA_BIT 0
|
||||
|
||||
#if F_CPU != 16000000L
|
||||
#error Only 16MHz clock supported
|
||||
@ -50,7 +62,7 @@
|
||||
; r24,r25 : dstbuf
|
||||
; r22 : max bytes (for fututre use)
|
||||
; return: count in r24,r25 (0xff: Error, 0xfe: Overflow [max_bytes too low])
|
||||
gcn64_receiveBytes:
|
||||
FUNCTION(gcn64_receiveBytes, SUFFIX):
|
||||
clr xl
|
||||
clr xh
|
||||
mov zl, r24
|
||||
@ -149,7 +161,7 @@ rxdone:
|
||||
* A stop bit is added at thy end of the packet.
|
||||
*
|
||||
************************************************/
|
||||
gcn64_sendBytes:
|
||||
FUNCTION(gcn64_sendBytes, SUFFIX):
|
||||
; Move r23,r24 pointer to z
|
||||
mov zl, r24
|
||||
mov zh, r25
|
||||
|
10
gcn64txrx.h
10
gcn64txrx.h
@ -1,7 +1,10 @@
|
||||
#ifndef _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
|
||||
@ -9,6 +12,9 @@ void gcn64_sendBytes(const unsigned char *data, unsigned char n_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)
|
||||
*/
|
||||
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__
|
||||
|
@ -76,7 +76,7 @@ uint8_t hiddata_set_report(const struct usb_request *rq, const uint8_t *dat, uin
|
||||
|
||||
static void hiddata_processCommandBuffer(void)
|
||||
{
|
||||
//unsigned char channel;
|
||||
unsigned char channel;
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
#endif
|
||||
@ -95,8 +95,8 @@ static void hiddata_processCommandBuffer(void)
|
||||
case RQ_GCN64_RAW_SI_COMMAND:
|
||||
// TODO : Range checking
|
||||
// cmdbuf[] : RQ, CHN, LEN, data[]
|
||||
//channel = cmdbuf[1];
|
||||
cmdbuf_len = gcn64_transaction(cmdbuf+3, cmdbuf[2], cmdbuf + 3, CMDBUF_SIZE-3);
|
||||
channel = cmdbuf[1];
|
||||
cmdbuf_len = gcn64_transaction(channel, cmdbuf+3, cmdbuf[2], cmdbuf + 3, CMDBUF_SIZE-3);
|
||||
cmdbuf[2] = cmdbuf_len;
|
||||
cmdbuf_len += 3; // Answer: RQ, CHN, LEN, data[]
|
||||
break;
|
||||
|
2
main.c
2
main.c
@ -235,7 +235,7 @@ unsigned char current_pad_type = CONTROLLER_IS_ABSENT;
|
||||
|
||||
Gamepad *detectPad(void)
|
||||
{
|
||||
current_pad_type = gcn64_detectController();
|
||||
current_pad_type = gcn64_detectController(GCN64_CHANNEL_0);
|
||||
|
||||
switch (current_pad_type)
|
||||
{
|
||||
|
10
n64.c
10
n64.c
@ -60,7 +60,7 @@ static char initRumble(void)
|
||||
tmpdata[2] = 0x01;
|
||||
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)
|
||||
return 0;
|
||||
|
||||
@ -76,7 +76,7 @@ static char controlRumble(char enable)
|
||||
tmpdata[1] = 0xc0;
|
||||
tmpdata[2] = 0x1b;
|
||||
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)
|
||||
return 0;
|
||||
|
||||
@ -101,7 +101,7 @@ static char n64Update(void)
|
||||
* Bit 1 tells is if there was something connected that has been removed.
|
||||
*/
|
||||
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) {
|
||||
// a failed read could mean the pack or controller was gone. Init
|
||||
// will be necessary next time we detect a pack is present.
|
||||
@ -172,7 +172,7 @@ static char n64Update(void)
|
||||
}
|
||||
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
@ -274,7 +274,7 @@ static char n64Probe(void)
|
||||
_delay_ms(30);
|
||||
|
||||
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) {
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user