From fb43524d34048e0f4c83a2663b2474d5065179aa Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Sun, 9 Oct 2016 16:17:56 -0400 Subject: [PATCH] Update gcn64txrx code for multiple channels --- Makefile | 12 ++++++++++++ Makefile.inc | 2 +- gamecube.c | 2 +- gcn64_protocol.c | 32 +++++++++++++++++++++----------- gcn64_protocol.h | 9 +++++++-- gcn64txrx.S | 22 +++++++++++++++++----- gcn64txrx.h | 10 ++++++++-- hiddata.c | 6 +++--- main.c | 2 +- n64.c | 10 +++++----- 10 files changed, 76 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 11cfe4a..661ec02 100644 --- a/Makefile +++ b/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 $@ diff --git a/Makefile.inc b/Makefile.inc index 4f94f84..596653b 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -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\" diff --git a/gamecube.c b/gamecube.c index a900cc1..8625205 100644 --- a/gamecube.c +++ b/gamecube.c @@ -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; } diff --git a/gcn64_protocol.c b/gcn64_protocol.c index 56e2ebf..b879c17 100644 --- a/gcn64_protocol.c +++ b/gcn64_protocol.c @@ -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; } diff --git a/gcn64_protocol.h b/gcn64_protocol.h index 0c3ba24..f6617a4 100644 --- a/gcn64_protocol.h +++ b/gcn64_protocol.h @@ -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__ diff --git a/gcn64txrx.S b/gcn64txrx.S index 41d3b00..fcaa273 100644 --- a/gcn64txrx.S +++ b/gcn64txrx.S @@ -1,8 +1,20 @@ #include +; 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 diff --git a/gcn64txrx.h b/gcn64txrx.h index 8c7ae63..3069d16 100644 --- a/gcn64txrx.h +++ b/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__ diff --git a/hiddata.c b/hiddata.c index 047e620..5f53127 100644 --- a/hiddata.c +++ b/hiddata.c @@ -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; diff --git a/main.c b/main.c index 44f2b3b..2bbda14 100644 --- a/main.c +++ b/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) { diff --git a/n64.c b/n64.c index 9c84278..9c4823d 100644 --- a/n64.c +++ b/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;