Use new gampad data and usbpad

This commit is contained in:
Raphael Assenat 2015-08-20 23:39:54 -04:00
parent 6e0dd383b3
commit a07c8cbd70
6 changed files with 75 additions and 139 deletions

View File

@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
HEXFILE=$(PROGNAME).hex 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) all: $(HEXFILE)

View File

@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DSTK525
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
HEXFILE=$(PROGNAME).hex 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) all: $(HEXFILE)

View File

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

@ -10,10 +10,11 @@
#include "util.h" #include "util.h"
#include "usart1.h" #include "usart1.h"
#include "usb.h" #include "usb.h"
#include "gamepad.h" #include "gamepads.h"
#include "gcn64_protocol.h" #include "gcn64_protocol.h"
#include "n64.h" #include "n64.h"
#include "bootloader.h" #include "bootloader.h"
#include "usbpad.h"
uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat); 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); 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 #define LOOP_MAX 0xFFFF
static unsigned int _loop_count; static unsigned int _loop_count;
#if 0
static void effect_loop() static void effect_loop()
{ {
if (_loop_count) { if (_loop_count) {
@ -253,11 +255,12 @@ static void effect_loop()
} }
} }
} }
#endif
static void decideVibration(void) static void decideVibration(void)
{ {
if (!_loop_count) // if (!_loop_count)
vibration_on = 0; // vibration_on = 0;
if (!vibration_on) { if (!vibration_on) {
gamepad_vibrate = 0; 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: case HID_REPORT_TYPE_FEATURE:
if (report_id == PID_BLOCK_LOAD_REPORT) { if (report_id == PID_BLOCK_LOAD_REPORT) {
hid_report_data[0] = report_id; hid_report_data[0] = report_id;
hid_report_data[1] = 0x1; hid_report_data[1] = 0x1; // Effect block index
hid_report_data[2] = 0x1; hid_report_data[2] = 0x1; // (1: success, 2: oom, 3: load error)
hid_report_data[3] = 10; hid_report_data[3] = 10;
hid_report_data[4] = 10; hid_report_data[4] = 10;
printf_P(PSTR("block load\r\n")); 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]) switch(data[0])
{ {
case REPORT_SET_STATUS: 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; break;
case REPORT_EFFECT_BLOCK_IDX: 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; break;
case REPORT_DISABLE_ACTUATORS: case REPORT_DISABLE_ACTUATORS:
printf_P(PSTR("disable actuators\r\n")); 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; break;
case REPORT_SET_PERIODIC: case REPORT_SET_PERIODIC:
magnitude = data[2]; magnitude = data[2];
decideVibration(); // decideVibration();
printf_P(PSTR("periodic mag: %d"), data[2]); printf_P(PSTR("periodic mag: %d"), data[2]);
break; break;
case REPORT_SET_CONSTANT_FORCE: 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: case REPORT_EFFECT_OPERATION:
if (len != 4) if (len != 4)
return -1; return -1;
printf_P(PSTR("EFFECT OP\n"));
/* Byte 0 : report ID /* Byte 0 : report ID
* Byte 1 : bit 7=rom flag, bits 6-0=effect block index * Byte 1 : bit 7=rom flag, bits 6-0=effect block index
* Byte 2 : Effect operation * Byte 2 : Effect operation
* Byte 3 : Loop count */ * Byte 3 : Loop count */
_loop_count = data[3]<<3; _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 switch(data[1] & 0x7F) // Effect block index
{ {
case 1: // constant force 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 switch (data[2]) // effect operation
{ {
case EFFECT_OP_START: case EFFECT_OP_START:
printf_P(PSTR("Start\r\n"));
vibration_on = 1; vibration_on = 1;
decideVibration(); decideVibration();
break; break;
case EFFECT_OP_START_SOLO: case EFFECT_OP_START_SOLO:
printf_P(PSTR("Start solo\r\n"));
vibration_on = 1; vibration_on = 1;
decideVibration(); decideVibration();
break; break;
case EFFECT_OP_STOP: case EFFECT_OP_STOP:
printf_P(PSTR("Stop\r\n"));
vibration_on = 0; vibration_on = 0;
decideVibration(); decideVibration();
break; break;
@ -475,6 +482,7 @@ uint8_t hid_set_report_data(const struct usb_request *rq, const uint8_t *dat, ui
int main(void) int main(void)
{ {
Gamepad *pad = NULL; Gamepad *pad = NULL;
gamepad_data pad_data;
hwinit(); hwinit();
usart1_init(); usart1_init();
@ -491,7 +499,7 @@ int main(void)
usb_doTasks(); usb_doTasks();
_delay_ms(5); _delay_ms(5);
effect_loop(); //effect_loop();
decideVibration(); decideVibration();
if (last_v != gamepad_vibrate) { if (last_v != gamepad_vibrate) {
@ -502,10 +510,12 @@ int main(void)
} }
pad->update(); pad->update();
if (pad->changed(1)) { if (pad->changed()) {
int report_size; 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); usb_interruptSend(gamepad_report0, report_size);
} }
} }

149
n64.c
View File

@ -18,31 +18,30 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <util/delay.h> #include <util/delay.h>
#include <string.h> #include <string.h>
#include "gamepad.h" #include "gamepads.h"
#include "n64.h" #include "n64.h"
#include "gcn64_protocol.h" #include "gcn64_protocol.h"
#define GCN64_REPORT_SIZE 15
#undef BUTTON_A_RUMBLE_TEST #undef BUTTON_A_RUMBLE_TEST
/*********** prototypes *************/ /*********** prototypes *************/
static void n64Init(void); static void n64Init(void);
static char n64Update(void); static char n64Update(void);
static char n64Changed(int id); static char n64Changed(void);
static int n64BuildReport(unsigned char *reportBuffer, int id); static void n64GetReport(gamepad_data *dst);
static void n64SetVibration(int value); static void n64SetVibration(char enable);
static char must_rumble = 0; static char must_rumble = 0;
#ifdef BUTTON_A_RUMBLE_TEST #ifdef BUTTON_A_RUMBLE_TEST
static char force_rumble = 0; static char force_rumble = 0;
#endif #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 */ /* What was most recently read from the controller */
static unsigned char last_sent_report[GCN64_REPORT_SIZE]; static gamepad_data last_built_report;
/* What was most recently reported through getReport */
static gamepad_data last_sent_report;
static void n64Init(void) static void n64Init(void)
{ {
@ -92,11 +91,9 @@ static char controlRumble(char enable)
static char n64Update(void) static char n64Update(void)
{ {
int i;
unsigned char count; unsigned char count;
unsigned char x,y; unsigned char x,y;
unsigned char btns1, btns2; unsigned char btns1, btns2;
unsigned char rb1, rb2;
unsigned char caps[3]; unsigned char caps[3];
/* Pad answer to N64_GET_CAPABILITIES /* Pad answer to N64_GET_CAPABILITIES
@ -224,84 +221,40 @@ static char n64Update(void)
} }
#endif #endif
// Remap buttons as they always were by this last_built_report.pad_type = PAD_TYPE_N64;
// adapter. Might change in v3 when a N64 last_built_report.n64.buttons = (btns1 << 8) | btns2;
// specific report descriptor will be used. last_built_report.n64.x = x;
// last_built_report.n64.y = y;
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;
// analog joystick /* Copy all the data as-is for the raw field */
last_built_report[0] = 1; // ID 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) { /* Some cheap non-official controllers
int16_t xval, yval; * use the full 8 bit range instead of the
* normal +-80 observed on official controllers. In
xval = (char)x; * particular, some units (but not all!) produced
yval = (char)y; * by TTX. The symptom is usually "The joystick
* left direction does not work".
if (xval>80) xval = 80; else if (xval<-80) xval = -80; *
if (yval>80) yval = 80; else if (yval<-80) yval = -80; * So I limit values to the -127 to +127 range,
* otherwise it causes problem later
// Scale -80 ... +80 to -16000 ... +16000 * when the sign is inverted. Using 16 bit
* signed numbers instead of 8 bit would solve
xval *= 200; * this, but this is only for cheap, not
yval *= 200; * even worth using controllers so I don't
yval = -yval; * care.
*
xval += 16000; * The joystick will now "work" as bad as it would
yval += 16000; * on a N64, or maybe a little better. This should
* help people realise they got what the paid for
last_built_report[1] = ((uint8_t*)&xval)[0]; * instead of suspecting the adapter. */
last_built_report[2] = ((uint8_t*)&xval)[1]; if (last_built_report.n64.x == -128)
last_built_report.n64.x = -127;
last_built_report[3] = ((uint8_t*)&yval)[0]; if (last_built_report.n64.y == -128)
last_built_report[4] = ((uint8_t*)&yval)[1]; last_built_report.n64.y = -127;
}
#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;
return 0; return 0;
} }
@ -338,32 +291,30 @@ static char n64Probe(void)
return 0; 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) if (dst)
memcpy(reportBuffer, last_built_report, GCN64_REPORT_SIZE); memcpy(dst, &last_built_report, sizeof(gamepad_data));
memcpy( last_sent_report, last_built_report, GCN64_REPORT_SIZE); memcpy(&last_sent_report, &last_built_report, sizeof(gamepad_data));
return GCN64_REPORT_SIZE;
} }
static void n64SetVibration(int value) static void n64SetVibration(char enable)
{ {
must_rumble = value; must_rumble = enable;
} }
static Gamepad N64Gamepad = { static Gamepad N64Gamepad = {
.init = n64Init, .init = n64Init,
.update = n64Update, .update = n64Update,
.changed = n64Changed, .changed = n64Changed,
.buildReport = n64BuildReport, .getReport = n64GetReport,
.probe = n64Probe, .probe = n64Probe,
.num_reports = 1,
.setVibration = n64SetVibration, .setVibration = n64SetVibration,
}; };

2
n64.h
View File

@ -1,4 +1,4 @@
#include "gamepad.h" #include "gamepads.h"
Gamepad *n64GetGamepad(void); Gamepad *n64GetGamepad(void);