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

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_SHORT=\"3.2\"

View File

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

View File

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

View File

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

View File

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

View File

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

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)
{
//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
View File

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

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