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

View File

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

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

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

2
n64.h
View File

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