Update gcn64txrx code for multiple channels

This commit is contained in:
Raphael Assenat 2016-10-09 16:17:56 -04:00
parent 0c8dc9e7de
commit fb43524d34
10 changed files with 76 additions and 31 deletions

View File

@ -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 $@

View File

@ -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\"

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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__

View File

@ -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

View File

@ -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__

View File

@ -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
View File

@ -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
View File

@ -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;