I got the initialization working finally.. So I'm guessing the hardware side should be allright. I did add a resistor and measured the D lines. D- = 3.3V
D+ = 0V.. For some reason I am getting a hunch the 0V is not right for the D+? Should this be switched around?
*crosspost, wanted to post it here*
I am trying to get reports sent to the PC, but the avr doesn't seem to be sending anything.. For the record, I am using an atmega16, but that shouldn't change anything..
It's strange because the device is recognized by windows, gamecontrollers shows this:
I'm guessing this means the enumeration is going correct, but the interrupts after are not received correctly?
I also added a usbtrace log on my webserver, the device desciption it gives and a list of transfers received and sent. This is a cycle which keeps repeating itself..
http://www.waazaa.net/usb/
I'm just adding my code here..
Code: Select all
/**********************Global Variables****************************************/
/* Originally used as a mask for the modifier bits, but now also
used for other x -> 2^x conversions (lookup table). */
const char modmask[8] PROGMEM = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar adcData[8] ={0,0,0,0,0,0,0,0}; //int to store the AD conversion results in.
uchar newDataFound;
uchar updateNeeded = 0;
/* The ReportBuffer contains the USB report sent to the PC */
static uchar reportBuffer[8] = {0,0,0,0,0,0,0,0}; /* buffer for HID reports */
static uchar idleRate; /* in 4 ms units */
/* Device serial number (length is defined in usbconfig.h) */
int usbCfgSerialNumberStringDescriptor[USB_CFG_SERIAL_NUMBER_LENGTH+1] PROGMEM =
{
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LENGTH),
'1', '3',
};
/* USB report descriptor (length is defined in usbconfig.h)*/
const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH]
PROGMEM = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255)
0x09, 0x31, // USAGE (Y)
0x09, 0x30, // USAGE (X)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x09, 0x35, // USAGE (Rz)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x45, 0x01, // PHYSICAL_MAXIMUM (1)
0xc0, // END_COLLECTION
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x08, // USAGE_MAXIMUM (Button 8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
/**********************||Global Variables||****************************************/
static void hardwareInit(void) {
uchar i, j;
/* 1101 1000 bin: activate pull-ups except on USB lines
*
* USB signals are on bit 0 and 2.
*
* */
PORTD = 0xf8;
/* Usb pin are init as outputs */
DDRD = 0x01 | 0x04;
j = 0;
while(--j){ /* USB Reset by device only required on Watchdog Reset */
i = 0;
while(--i); /* delay >10ms for USB reset */
}
DDRD = 0x00; /* 0000 0000 bin: remove USB reset condition */
/* configure timer 0 for a rate of 12M/(1024 * 256) = 45.78 Hz (~22ms) */
TCCR0 = 5; /* timer 0 prescaler: 1024 */
TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
OCR2 = 196; // for 60 hz
}
//Initialize the AD converter.
void Init_ADC( void )
{
// enable * prescaler = 128 *
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);
}
uchar usbFunctionSetup(uchar data[8]) {
usbRequest_t *rq = (void *)data;
usbMsgPtr = reportBuffer;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
/* we only have one report type, so don't look at wValue */
return sizeof(reportBuffer);
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
usbMsgPtr = &idleRate;
return 1;
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
idleRate = rq->wValue.bytes[1];
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
void inDecoderPoll(void)
{
for (unsigned int i = 0; i < 8; i++)
{
ADMUX = i; // select ADC channel
ADMUX |= (0<<REFS1)|(1<<REFS0)|(1<<ADLAR);
ADCSRA |= (1<<ADSC); // start conversion
while (ADCSRA & (1<<ADSC)){;} // wait for result (fast, not a problem for USB driver)
adcData[i] = ADCH; // save to data buffer
}
// set new data flag
newDataFound = 1;
}
void buildReport(void)
{
for (unsigned int i =0; i<7; i++)
{
//just using channel 7 value for now.
reportBuffer[i+1] = adcData[7];
}
}
void testMeth(void)
{
if(usbInterruptIsReady())
{
// led on
PORTB = 0x00;
DDRB = 0x01;
}
else
{
//led off.
DDRB = 0x00;
}
}
int main(void) {
wdt_enable(WDTO_2S); /* Enable watchdog timer 2s */
hardwareInit(); /* Initialize hardware (I/O) */
Init_ADC();
usbInit(); /* Initialize USB stack processing */
sei(); /* Enable global interrupts */
for(;;)
{ /* Main loop */
wdt_reset(); /* Reset the watchdog */
usbPoll(); /* Poll the USB stack */
inDecoderPoll();
/* If an update is needed, send the report */
if(usbInterruptIsReady())
{
buildReport();
testMeth();
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
}
}
return 0;
}