mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 06:48:52 -05:00
Use new gampad data and usbpad
This commit is contained in:
parent
6e0dd383b3
commit
a07c8cbd70
2
Makefile
2
Makefile
@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT
|
||||
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
|
||||
HEXFILE=$(PROGNAME).hex
|
||||
|
||||
OBJS=main.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o
|
||||
OBJS=main.o usbpad.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o
|
||||
|
||||
all: $(HEXFILE)
|
||||
|
||||
|
@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DSTK525
|
||||
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
|
||||
HEXFILE=$(PROGNAME).hex
|
||||
|
||||
OBJS=main.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o
|
||||
OBJS=main.o usbpad.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o
|
||||
|
||||
all: $(HEXFILE)
|
||||
|
||||
|
25
gamepad.h
25
gamepad.h
@ -1,25 +0,0 @@
|
||||
#ifndef _gamepad_h__
|
||||
#define _gamepad_h__
|
||||
|
||||
typedef struct {
|
||||
int num_reports;
|
||||
|
||||
int reportDescriptorSize;
|
||||
void *reportDescriptor; // must be in flash
|
||||
|
||||
int deviceDescriptorSize; // if 0, use default
|
||||
void *deviceDescriptor; // must be in flash
|
||||
|
||||
void (*init)(void);
|
||||
char (*update)(void);
|
||||
char (*changed)(int id);
|
||||
int (*buildReport)(unsigned char *buf, int id);
|
||||
void (*setVibration)(int value);
|
||||
|
||||
/* Check for the controller */
|
||||
char (*probe)(void); /* return true if found */
|
||||
} Gamepad;
|
||||
|
||||
#endif // _gamepad_h__
|
||||
|
||||
|
34
main.c
34
main.c
@ -10,10 +10,11 @@
|
||||
#include "util.h"
|
||||
#include "usart1.h"
|
||||
#include "usb.h"
|
||||
#include "gamepad.h"
|
||||
#include "gamepads.h"
|
||||
#include "gcn64_protocol.h"
|
||||
#include "n64.h"
|
||||
#include "bootloader.h"
|
||||
#include "usbpad.h"
|
||||
|
||||
uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat);
|
||||
uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
|
||||
@ -245,6 +246,7 @@ static unsigned char _FFB_effect_index;
|
||||
#define LOOP_MAX 0xFFFF
|
||||
static unsigned int _loop_count;
|
||||
|
||||
#if 0
|
||||
static void effect_loop()
|
||||
{
|
||||
if (_loop_count) {
|
||||
@ -253,11 +255,12 @@ static void effect_loop()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void decideVibration(void)
|
||||
{
|
||||
if (!_loop_count)
|
||||
vibration_on = 0;
|
||||
// if (!_loop_count)
|
||||
// vibration_on = 0;
|
||||
|
||||
if (!vibration_on) {
|
||||
gamepad_vibrate = 0;
|
||||
@ -305,8 +308,8 @@ uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat)
|
||||
case HID_REPORT_TYPE_FEATURE:
|
||||
if (report_id == PID_BLOCK_LOAD_REPORT) {
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 0x1;
|
||||
hid_report_data[2] = 0x1;
|
||||
hid_report_data[1] = 0x1; // Effect block index
|
||||
hid_report_data[2] = 0x1; // (1: success, 2: oom, 3: load error)
|
||||
hid_report_data[3] = 10;
|
||||
hid_report_data[4] = 10;
|
||||
printf_P(PSTR("block load\r\n"));
|
||||
@ -353,10 +356,10 @@ uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, u
|
||||
switch(data[0])
|
||||
{
|
||||
case REPORT_SET_STATUS:
|
||||
printf_P(PSTR("eff. set stat\r\n"));
|
||||
printf_P(PSTR("eff. set stat 0x%02x 0x%02x\r\n"),data[1],data[2]);
|
||||
break;
|
||||
case REPORT_EFFECT_BLOCK_IDX:
|
||||
printf_P(PSTR("eff. blk. idx\r\n"));
|
||||
printf_P(PSTR("eff. blk. idx %d\r\n"), data[1]);
|
||||
break;
|
||||
case REPORT_DISABLE_ACTUATORS:
|
||||
printf_P(PSTR("disable actuators\r\n"));
|
||||
@ -370,7 +373,7 @@ uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, u
|
||||
break;
|
||||
case REPORT_SET_PERIODIC:
|
||||
magnitude = data[2];
|
||||
decideVibration();
|
||||
// decideVibration();
|
||||
printf_P(PSTR("periodic mag: %d"), data[2]);
|
||||
break;
|
||||
case REPORT_SET_CONSTANT_FORCE:
|
||||
@ -383,13 +386,14 @@ uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, u
|
||||
case REPORT_EFFECT_OPERATION:
|
||||
if (len != 4)
|
||||
return -1;
|
||||
printf_P(PSTR("EFFECT OP\n"));
|
||||
/* Byte 0 : report ID
|
||||
* Byte 1 : bit 7=rom flag, bits 6-0=effect block index
|
||||
* Byte 2 : Effect operation
|
||||
* Byte 3 : Loop count */
|
||||
_loop_count = data[3]<<3;
|
||||
|
||||
printf_P(PSTR("EFFECT OP: rom=%s, idx=0x%02x"), data[1] & 0x80 ? "Yes":"No", data[1] & 0x7F);
|
||||
|
||||
switch(data[1] & 0x7F) // Effect block index
|
||||
{
|
||||
case 1: // constant force
|
||||
@ -398,16 +402,19 @@ uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, u
|
||||
switch (data[2]) // effect operation
|
||||
{
|
||||
case EFFECT_OP_START:
|
||||
printf_P(PSTR("Start\r\n"));
|
||||
vibration_on = 1;
|
||||
decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_START_SOLO:
|
||||
printf_P(PSTR("Start solo\r\n"));
|
||||
vibration_on = 1;
|
||||
decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_STOP:
|
||||
printf_P(PSTR("Stop\r\n"));
|
||||
vibration_on = 0;
|
||||
decideVibration();
|
||||
break;
|
||||
@ -475,6 +482,7 @@ uint8_t hid_set_report_data(const struct usb_request *rq, const uint8_t *dat, ui
|
||||
int main(void)
|
||||
{
|
||||
Gamepad *pad = NULL;
|
||||
gamepad_data pad_data;
|
||||
|
||||
hwinit();
|
||||
usart1_init();
|
||||
@ -491,7 +499,7 @@ int main(void)
|
||||
|
||||
usb_doTasks();
|
||||
_delay_ms(5);
|
||||
effect_loop();
|
||||
//effect_loop();
|
||||
decideVibration();
|
||||
|
||||
if (last_v != gamepad_vibrate) {
|
||||
@ -502,10 +510,12 @@ int main(void)
|
||||
}
|
||||
|
||||
pad->update();
|
||||
if (pad->changed(1)) {
|
||||
if (pad->changed()) {
|
||||
int report_size;
|
||||
|
||||
report_size = pad->buildReport(gamepad_report0, 1);
|
||||
pad->getReport(&pad_data);
|
||||
usbpad_buildReport(&pad_data, gamepad_report0);
|
||||
report_size = usbpad_getReportSize();
|
||||
usb_interruptSend(gamepad_report0, report_size);
|
||||
}
|
||||
}
|
||||
|
149
n64.c
149
n64.c
@ -18,31 +18,30 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <string.h>
|
||||
#include "gamepad.h"
|
||||
#include "gamepads.h"
|
||||
#include "n64.h"
|
||||
#include "gcn64_protocol.h"
|
||||
|
||||
#define GCN64_REPORT_SIZE 15
|
||||
|
||||
#undef BUTTON_A_RUMBLE_TEST
|
||||
|
||||
/*********** prototypes *************/
|
||||
static void n64Init(void);
|
||||
static char n64Update(void);
|
||||
static char n64Changed(int id);
|
||||
static int n64BuildReport(unsigned char *reportBuffer, int id);
|
||||
static void n64SetVibration(int value);
|
||||
static char n64Changed(void);
|
||||
static void n64GetReport(gamepad_data *dst);
|
||||
static void n64SetVibration(char enable);
|
||||
|
||||
static char must_rumble = 0;
|
||||
#ifdef BUTTON_A_RUMBLE_TEST
|
||||
static char force_rumble = 0;
|
||||
#endif
|
||||
|
||||
/* What was most recently read from the controller */
|
||||
static unsigned char last_built_report[GCN64_REPORT_SIZE];
|
||||
|
||||
/* What was most recently sent to the host */
|
||||
static unsigned char last_sent_report[GCN64_REPORT_SIZE];
|
||||
/* What was most recently read from the controller */
|
||||
static gamepad_data last_built_report;
|
||||
|
||||
/* What was most recently reported through getReport */
|
||||
static gamepad_data last_sent_report;
|
||||
|
||||
static void n64Init(void)
|
||||
{
|
||||
@ -92,11 +91,9 @@ static char controlRumble(char enable)
|
||||
|
||||
static char n64Update(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char count;
|
||||
unsigned char x,y;
|
||||
unsigned char btns1, btns2;
|
||||
unsigned char rb1, rb2;
|
||||
unsigned char caps[3];
|
||||
|
||||
/* Pad answer to N64_GET_CAPABILITIES
|
||||
@ -224,84 +221,40 @@ static char n64Update(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remap buttons as they always were by this
|
||||
// adapter. Might change in v3 when a N64
|
||||
// specific report descriptor will be used.
|
||||
//
|
||||
rb1 = rb2 = 0;
|
||||
for (i=0; i<4; i++) // A B Z START
|
||||
rb1 |= (btns1 & (0x80 >> i)) ? (0x01<<i) : 0;
|
||||
for (i=0; i<4; i++) // C-UP C-DOWN C-LEFT C-RIGHT
|
||||
rb1 |= btns2 & (0x08 >> i) ? (0x10<<i) : 0;
|
||||
for (i=0; i<2; i++) // L R
|
||||
rb2 |= btns2 & (0x20 >> i) ? (0x01<<i) : 0;
|
||||
for (i=0; i<4; i++) // Up down left right
|
||||
rb2 |= btns1 & (0x08 >> i) ? (0x04<<i) : 0;
|
||||
last_built_report.pad_type = PAD_TYPE_N64;
|
||||
last_built_report.n64.buttons = (btns1 << 8) | btns2;
|
||||
last_built_report.n64.x = x;
|
||||
last_built_report.n64.y = y;
|
||||
|
||||
// analog joystick
|
||||
last_built_report[0] = 1; // ID
|
||||
/* Copy all the data as-is for the raw field */
|
||||
last_built_report.n64.raw_data[0] = btns1;
|
||||
last_built_report.n64.raw_data[1] = btns2;
|
||||
last_built_report.n64.raw_data[2] = x;
|
||||
last_built_report.n64.raw_data[3] = y;
|
||||
|
||||
if (1) {
|
||||
int16_t xval, yval;
|
||||
|
||||
xval = (char)x;
|
||||
yval = (char)y;
|
||||
|
||||
if (xval>80) xval = 80; else if (xval<-80) xval = -80;
|
||||
if (yval>80) yval = 80; else if (yval<-80) yval = -80;
|
||||
|
||||
// Scale -80 ... +80 to -16000 ... +16000
|
||||
|
||||
xval *= 200;
|
||||
yval *= 200;
|
||||
yval = -yval;
|
||||
|
||||
xval += 16000;
|
||||
yval += 16000;
|
||||
|
||||
last_built_report[1] = ((uint8_t*)&xval)[0];
|
||||
last_built_report[2] = ((uint8_t*)&xval)[1];
|
||||
|
||||
last_built_report[3] = ((uint8_t*)&yval)[0];
|
||||
last_built_report[4] = ((uint8_t*)&yval)[1];
|
||||
}
|
||||
#ifdef CLASSIC_MODE // Adapter V1/V2 which required calibration
|
||||
if (1) {
|
||||
// Convert to unsigned
|
||||
x = (x ^ 0x80) - 1;
|
||||
y = ((y ^ 0x80) ) ^ 0xFF;
|
||||
|
||||
// The following helps a cheap TTX controller
|
||||
// which uses the full 8 bit range instead
|
||||
// of +/- 80. The specific test here prevents
|
||||
// receiving a value of 128 (instead of -127).
|
||||
//
|
||||
// This will have no effect on "normal" controllers.
|
||||
if (x == 0xFF)
|
||||
x = 0;
|
||||
|
||||
last_built_report[1] = 0;
|
||||
last_built_report[2] = x;
|
||||
|
||||
last_built_report[3] = 0;
|
||||
last_built_report[4] = y;
|
||||
}
|
||||
#endif
|
||||
last_built_report[5] = 0x80;
|
||||
last_built_report[6] = 0x3e;
|
||||
|
||||
last_built_report[7] = 0x80;
|
||||
last_built_report[8] = 0x3e;
|
||||
|
||||
last_built_report[9] = 0x80;
|
||||
last_built_report[10] = 0x3e;
|
||||
|
||||
last_built_report[11] = 0x80;
|
||||
last_built_report[12] = 0x3e;
|
||||
|
||||
// buttons
|
||||
last_built_report[13] = rb1;
|
||||
last_built_report[14] = rb2;
|
||||
/* Some cheap non-official controllers
|
||||
* use the full 8 bit range instead of the
|
||||
* normal +-80 observed on official controllers. In
|
||||
* particular, some units (but not all!) produced
|
||||
* by TTX. The symptom is usually "The joystick
|
||||
* left direction does not work".
|
||||
*
|
||||
* So I limit values to the -127 to +127 range,
|
||||
* otherwise it causes problem later
|
||||
* when the sign is inverted. Using 16 bit
|
||||
* signed numbers instead of 8 bit would solve
|
||||
* this, but this is only for cheap, not
|
||||
* even worth using controllers so I don't
|
||||
* care.
|
||||
*
|
||||
* The joystick will now "work" as bad as it would
|
||||
* on a N64, or maybe a little better. This should
|
||||
* help people realise they got what the paid for
|
||||
* instead of suspecting the adapter. */
|
||||
if (last_built_report.n64.x == -128)
|
||||
last_built_report.n64.x = -127;
|
||||
if (last_built_report.n64.y == -128)
|
||||
last_built_report.n64.y = -127;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -338,32 +291,30 @@ static char n64Probe(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char n64Changed(int id)
|
||||
static char n64Changed(void)
|
||||
{
|
||||
return memcmp(last_built_report, last_sent_report, GCN64_REPORT_SIZE);
|
||||
return memcmp(&last_built_report, &last_sent_report, sizeof(gamepad_data));
|
||||
}
|
||||
|
||||
static int n64BuildReport(unsigned char *reportBuffer, int id)
|
||||
static void n64GetReport(gamepad_data *dst)
|
||||
{
|
||||
if (reportBuffer)
|
||||
memcpy(reportBuffer, last_built_report, GCN64_REPORT_SIZE);
|
||||
if (dst)
|
||||
memcpy(dst, &last_built_report, sizeof(gamepad_data));
|
||||
|
||||
memcpy( last_sent_report, last_built_report, GCN64_REPORT_SIZE);
|
||||
return GCN64_REPORT_SIZE;
|
||||
memcpy(&last_sent_report, &last_built_report, sizeof(gamepad_data));
|
||||
}
|
||||
|
||||
static void n64SetVibration(int value)
|
||||
static void n64SetVibration(char enable)
|
||||
{
|
||||
must_rumble = value;
|
||||
must_rumble = enable;
|
||||
}
|
||||
|
||||
static Gamepad N64Gamepad = {
|
||||
.init = n64Init,
|
||||
.update = n64Update,
|
||||
.changed = n64Changed,
|
||||
.buildReport = n64BuildReport,
|
||||
.getReport = n64GetReport,
|
||||
.probe = n64Probe,
|
||||
.num_reports = 1,
|
||||
.setVibration = n64SetVibration,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user