mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 14:58:51 -05:00
Merge branch 'performance'
This commit is contained in:
commit
eeb2ecbae4
6
Makefile
6
Makefile
@ -7,7 +7,7 @@ include Makefile.inc
|
||||
PROGNAME=gcn64usb
|
||||
OBJDIR=objs-$(PROGNAME)
|
||||
CPU=atmega32u2
|
||||
CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DVERSIONSTR=$(VERSIONSTR) -DVERSIONSTR_SHORT=$(VERSIONSTR_SHORT)
|
||||
CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DVERSIONSTR=$(VERSIONSTR) -DVERSIONSTR_SHORT=$(VERSIONSTR_SHORT) -std=gnu99
|
||||
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
|
||||
HEXFILE=$(PROGNAME).hex
|
||||
|
||||
@ -58,3 +58,7 @@ chip_erase:
|
||||
|
||||
reset:
|
||||
dfu-programmer atmega32u2 reset
|
||||
|
||||
restart:
|
||||
- ./scripts/enter_bootloader.sh
|
||||
./scripts/start.sh $(CPU)
|
||||
|
@ -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 gcn64txrx0.o gcn64txrx1.o gcn64txrx2.o gcn64txrx3.o gamepads.o
|
||||
VERSIONSTR=\"3.3.2\"
|
||||
VERSIONSTR_SHORT=\"3.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 gcn64txrx0.o gcn64txrx1.o gcn64txrx2.o gcn64txrx3.o gamepads.o stkchk.o
|
||||
VERSIONSTR=\"3.4.0\"
|
||||
VERSIONSTR_SHORT=\"3.4\"
|
||||
|
@ -7,7 +7,7 @@ include Makefile.inc
|
||||
PROGNAME=gcn64usb-stk500
|
||||
OBJDIR=objs-$(PROGNAME)
|
||||
CPU=at90usb1287
|
||||
CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DSTK525 -DVERSIONSTR=$(VERSIONSTR) -DVERSIONSTR_SHORT=$(VERSIONSTR_SHORT)
|
||||
CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DSTK525 -DVERSIONSTR=$(VERSIONSTR) -DVERSIONSTR_SHORT=$(VERSIONSTR_SHORT) -std=gnu99
|
||||
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
|
||||
HEXFILE=$(PROGNAME).hex
|
||||
|
||||
|
@ -24,7 +24,7 @@ const uint8_t dataHidReport[] PROGMEM = {
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 40, // REPORT_COUNT (40)
|
||||
0x95, 63, // REPORT_COUNT (63)
|
||||
0x09, 0x01, // USAGE (Vendor defined)
|
||||
0xB1, 0x00, // FEATURE (Data,Ary,Abs)
|
||||
0xc0 // END_COLLECTION
|
||||
|
52
hiddata.c
52
hiddata.c
@ -25,8 +25,8 @@
|
||||
#include "version.h"
|
||||
#include "main.h"
|
||||
|
||||
// dataHidReport is 40 bytes.
|
||||
#define CMDBUF_SIZE 41
|
||||
// dataHidReport is 63 bytes. Endpoint is 64 bytes.
|
||||
#define CMDBUF_SIZE 64
|
||||
|
||||
#define STATE_IDLE 0
|
||||
#define STATE_NEW_COMMAND 1 // New command in buffer
|
||||
@ -74,6 +74,51 @@ uint8_t hiddata_set_report(void *ctx, const struct usb_request *rq, const uint8_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t processBlockIO(void)
|
||||
{
|
||||
uint8_t requestCopy[CMDBUF_SIZE];
|
||||
int i, rx_offset = 0, rx;
|
||||
uint8_t chn, n_tx, n_rx;
|
||||
|
||||
memcpy(requestCopy, cmdbuf, CMDBUF_SIZE);
|
||||
memset(cmdbuf + 1, 0xff, CMDBUF_SIZE-1);
|
||||
|
||||
for (rx_offset = 1, i=1; i<CMDBUF_SIZE; ) {
|
||||
if (i + 3 >= CMDBUF_SIZE)
|
||||
break;
|
||||
|
||||
chn = requestCopy[i];
|
||||
if (chn == 0xff)
|
||||
break;
|
||||
i++;
|
||||
n_tx = requestCopy[i];
|
||||
i++;
|
||||
n_rx = requestCopy[i];
|
||||
i++;
|
||||
if (n_tx == 0)
|
||||
continue;
|
||||
|
||||
if (rx_offset + 1 + n_rx >= CMDBUF_SIZE) {
|
||||
break;
|
||||
}
|
||||
|
||||
rx = gcn64_transaction(chn, requestCopy + i, n_tx, cmdbuf + rx_offset + 1, n_rx);
|
||||
cmdbuf[rx_offset] = n_rx;
|
||||
if (rx <= 0) {
|
||||
// timeout
|
||||
cmdbuf[rx_offset] |= 0x80;
|
||||
} else if (rx < n_rx) {
|
||||
// less than expected
|
||||
cmdbuf[rx_offset] |= 0x40;
|
||||
}
|
||||
rx_offset += n_rx + 1;
|
||||
|
||||
i += n_tx;
|
||||
}
|
||||
|
||||
return 63;
|
||||
}
|
||||
|
||||
static void hiddata_processCommandBuffer(struct hiddata_ops *ops)
|
||||
{
|
||||
unsigned char channel;
|
||||
@ -147,6 +192,9 @@ static void hiddata_processCommandBuffer(struct hiddata_ops *ops)
|
||||
}
|
||||
cmdbuf_len = 3;
|
||||
break;
|
||||
case RQ_GCN64_BLOCK_IO:
|
||||
cmdbuf_len = processBlockIO();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
50
main.c
50
main.c
@ -37,16 +37,17 @@
|
||||
#include "usbstrings.h"
|
||||
#include "intervaltimer.h"
|
||||
#include "requests.h"
|
||||
#include "stkchk.h"
|
||||
|
||||
#define MAX_PLAYERS 2
|
||||
|
||||
#define GCN64_USB_PID 0x001D
|
||||
#define N64_USB_PID 0x0020
|
||||
#define GC_USB_PID 0x0021
|
||||
#define GCN64_USB_PID 0x0032
|
||||
#define N64_USB_PID 0x0033
|
||||
#define GC_USB_PID 0x0034
|
||||
|
||||
#define DUAL_GCN64_USB_PID 0x0022
|
||||
#define DUAL_N64_USB_PID 0x0030
|
||||
#define DUAL_GC_USB_PID 0x0031
|
||||
#define DUAL_GCN64_USB_PID 0x0035
|
||||
#define DUAL_N64_USB_PID 0x0036
|
||||
#define DUAL_GC_USB_PID 0x0037
|
||||
|
||||
/* Those .c files are included rather than linked for we
|
||||
* want the sizeof() operator to work on the arrays */
|
||||
@ -54,6 +55,7 @@
|
||||
#include "dataHidReport.c"
|
||||
|
||||
#define MAX_READ_ERRORS 30
|
||||
static uint8_t error_count[MAX_PLAYERS] = { };
|
||||
|
||||
struct cfg0 {
|
||||
struct usb_configuration_descriptor configdesc;
|
||||
@ -402,15 +404,6 @@ void eeprom_app_ready(void)
|
||||
g_usb_strings[USB_STRING_SERIAL_IDX] = serial_from_eeprom;
|
||||
}
|
||||
|
||||
|
||||
void pollDelay(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<g_eeprom_data.cfg.poll_interval[0]; i++) {
|
||||
_delay_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbpad usbpads[MAX_PLAYERS];
|
||||
static char g_polling_suspended = 0;
|
||||
|
||||
@ -442,36 +435,37 @@ int main(void)
|
||||
{
|
||||
Gamepad *pads[MAX_PLAYERS] = { };
|
||||
gamepad_data pad_data;
|
||||
unsigned char gamepad_vibrate = 0;
|
||||
unsigned char state = STATE_WAIT_POLLTIME;
|
||||
int error_count[MAX_PLAYERS] = { };
|
||||
int i;
|
||||
int channel;
|
||||
int num_players = 1;
|
||||
uint8_t gamepad_vibrate = 0;
|
||||
uint8_t state = STATE_WAIT_POLLTIME;
|
||||
uint8_t channel;
|
||||
uint8_t num_players = 1;
|
||||
uint8_t i;
|
||||
|
||||
hwinit();
|
||||
usart1_init();
|
||||
eeprom_init();
|
||||
intervaltimer_init();
|
||||
stkchk_init();
|
||||
|
||||
switch (g_eeprom_data.cfg.mode)
|
||||
{
|
||||
default:
|
||||
case CFG_MODE_STANDARD:
|
||||
usbstrings_changeProductString_P(PSTR("GC/N64 to USB v"VERSIONSTR_SHORT));
|
||||
break;
|
||||
|
||||
case CFG_MODE_N64_ONLY:
|
||||
usbstrings_changeProductString(L"N64 to USB v"VERSIONSTR_SHORT);
|
||||
usbstrings_changeProductString_P(PSTR("N64 to USB v"VERSIONSTR_SHORT));
|
||||
device_descriptor.idProduct = N64_USB_PID;
|
||||
break;
|
||||
|
||||
case CFG_MODE_GC_ONLY:
|
||||
usbstrings_changeProductString(L"Gamecube to USB v"VERSIONSTR_SHORT);
|
||||
usbstrings_changeProductString_P(PSTR("Gamecube to USB v"VERSIONSTR_SHORT));
|
||||
device_descriptor.idProduct = GC_USB_PID;
|
||||
break;
|
||||
|
||||
case CFG_MODE_2P_STANDARD:
|
||||
usbstrings_changeProductString(L"Dual GC/N64 to USB v"VERSIONSTR_SHORT);
|
||||
usbstrings_changeProductString_P(PSTR("Dual GC/N64 to USB v"VERSIONSTR_SHORT));
|
||||
device_descriptor.idProduct = DUAL_GCN64_USB_PID;
|
||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
||||
@ -480,7 +474,7 @@ int main(void)
|
||||
break;
|
||||
|
||||
case CFG_MODE_2P_N64_ONLY:
|
||||
usbstrings_changeProductString(L"Dual N64 to USB v"VERSIONSTR_SHORT);
|
||||
usbstrings_changeProductString_P(PSTR("Dual N64 to USB v"VERSIONSTR_SHORT));
|
||||
device_descriptor.idProduct = DUAL_N64_USB_PID;
|
||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
||||
@ -489,7 +483,7 @@ int main(void)
|
||||
break;
|
||||
|
||||
case CFG_MODE_2P_GC_ONLY:
|
||||
usbstrings_changeProductString(L"Dual Gamecube to USB v"VERSIONSTR_SHORT);
|
||||
usbstrings_changeProductString_P(PSTR("Dual Gamecube to USB v"VERSIONSTR_SHORT));
|
||||
device_descriptor.idProduct = DUAL_GC_USB_PID;
|
||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
||||
@ -520,6 +514,10 @@ int main(void)
|
||||
{
|
||||
static char last_v[MAX_PLAYERS] = { };
|
||||
|
||||
if (stkchk_verify()) {
|
||||
enterBootLoader();
|
||||
}
|
||||
|
||||
usb_doTasks();
|
||||
hiddata_doTask(&hiddata_ops);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define RQ_GCN64_GET_CONTROLLER_TYPE 0x06
|
||||
#define RQ_GCN64_SET_VIBRATION 0x07
|
||||
#define RQ_GCN64_RAW_SI_COMMAND 0x80
|
||||
#define RQ_GCN64_BLOCK_IO 0x81
|
||||
#define RQ_GCN64_JUMP_TO_BOOTLOADER 0xFF
|
||||
|
||||
/* Configuration parameters and constants */
|
||||
|
21
scripts/start.sh
Executable file
21
scripts/start.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Syntax: ./start.sh CPU"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
CPU=$1
|
||||
|
||||
echo "Polling for chip..."
|
||||
while true; do
|
||||
dfu-programmer $1 start
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Chip found. Started."
|
||||
break;
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
60
stkchk.c
Normal file
60
stkchk.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/atomic.h>
|
||||
#include "stkchk.h"
|
||||
|
||||
extern uint16_t __stack;
|
||||
extern uint16_t _end;
|
||||
|
||||
/** Write a canary at the end of the stack. */
|
||||
void stkchk_init(void)
|
||||
{
|
||||
*((&_end)-1) = 0xDEAD;
|
||||
}
|
||||
|
||||
/** Check if the canary is still alive.
|
||||
*
|
||||
* Call this perdiocally to check if the
|
||||
* stack grew too large.
|
||||
**/
|
||||
char stkchk_verify(void)
|
||||
{
|
||||
if (*((&_end)-1) != 0xDEAD) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In order to get an approximate idea of how
|
||||
* much stack you are using, this can be called
|
||||
* at strategic places where you know the
|
||||
* call stack is deep or where large automatic
|
||||
* buffers are used.
|
||||
*/
|
||||
#ifdef STKCHK_WITH_STATUS_CHECK
|
||||
void stkchk(const char *fname)
|
||||
{
|
||||
static int max_usage = 0;
|
||||
uint16_t end = ((uint16_t)&_end);
|
||||
uint16_t s_top = ((uint16_t)&__stack);
|
||||
uint16_t s_cur = SPL | SPH<<8;
|
||||
uint16_t used, s_size;
|
||||
uint8_t grew = 0;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
used = s_top - s_cur;
|
||||
s_size = s_top - end;
|
||||
if (used > max_usage) {
|
||||
max_usage = used;
|
||||
grew = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (grew) {
|
||||
printf("[stkchk] %s: %d/%d\r\n", fname, used, s_size);
|
||||
}
|
||||
}
|
||||
#endif
|
16
stkchk.h
Normal file
16
stkchk.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _stkchk_h__
|
||||
#define _stkchk_h__
|
||||
|
||||
#undef STKCHK_WITH_STATUS_CHECK
|
||||
|
||||
#ifdef STKCHK_WITH_STATUS_CHECK
|
||||
#define stkcheck() stkchk(__FUNCTION__);
|
||||
void stkchk(const char *label);
|
||||
#else
|
||||
#define stkcheck()
|
||||
#endif
|
||||
|
||||
void stkchk_init(void);
|
||||
char stkchk_verify(void);
|
||||
|
||||
#endif // _stkchk_h__
|
25
usbstrings.c
25
usbstrings.c
@ -17,13 +17,32 @@
|
||||
#include <stdlib.h> // for wchar_t
|
||||
#include "usbstrings.h"
|
||||
|
||||
static wchar_t product_string[PRODUCT_STRING_MAXCHARS]; // = L"GC/N64 to USB v"VERSIONSTR_SHORT;
|
||||
|
||||
const wchar_t *g_usb_strings[] = {
|
||||
[0] = L"raphnet technologies", // 1 : Vendor
|
||||
[1] = L"GC/N64 to USB v"VERSIONSTR_SHORT, // 2: Product
|
||||
[1] = product_string, // 2: Product
|
||||
[2] = L"123456", // 3 : Serial
|
||||
};
|
||||
|
||||
void usbstrings_changeProductString(const wchar_t *str)
|
||||
void usbstrings_changeProductString_P(const char *str)
|
||||
{
|
||||
g_usb_strings[1] = str;
|
||||
const char *s = str;
|
||||
wchar_t *d = product_string;
|
||||
uint8_t c;
|
||||
int n = 0;
|
||||
|
||||
do {
|
||||
/* Make sure target is always NUL terminated. */
|
||||
n++;
|
||||
if (n == PRODUCT_STRING_MAXCHARS) {
|
||||
*d = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
c = pgm_read_byte(s);
|
||||
|
||||
*d = c;
|
||||
s++; d++;
|
||||
} while (c);
|
||||
}
|
||||
|
10
usbstrings.h
10
usbstrings.h
@ -1,13 +1,21 @@
|
||||
#ifndef _usbstrings_h__
|
||||
#define _usbstrings_h__
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
extern const wchar_t *g_usb_strings[];
|
||||
|
||||
/* Sample: "Dual Gamecube to USB v3.4" (25) */
|
||||
#define PRODUCT_STRING_MAXCHARS 32
|
||||
|
||||
#define NUM_USB_STRINGS 3
|
||||
|
||||
/* Array indexes (i.e. zero-based0 */
|
||||
#define USB_STRING_SERIAL_IDX 2
|
||||
|
||||
void usbstrings_changeProductString(const wchar_t *str);
|
||||
/**
|
||||
* \param str Must be in PROGMEM
|
||||
*/
|
||||
void usbstrings_changeProductString_P(const char *str);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user