ATMega 16u2 UNOJoy, no joy

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My foray into more complicated AVR usage (after a lot of Arduino fiddling) I have built a PCB that is based somewhat on the UNO3.  As I plan on using HID, I have the USB being handled by the 16u2.  That section of schema is 'pretty similar' to the UNO R3:

16u2 schema snapshot

 

The layout has slightly longer traces from the USB plug to the chip, but not by much.

The issue I am having is that the device is never recognized by the PC, when the UNO was with the same firmware.  I know the firmware is running, and I know where it is stalling.  If I debug the UNOJoy project, it seems the SET_CONFIGURATION request is not forthcoming....   Standard UNOJoy USB interrupt handler:

 

// USB Endpoint Interrupt - endpoint 0 is handled here.  The
// other endpoints are manipulated by the user-callable
// functions, and the start-of-frame interrupt.

ISR(USB_COM_vect)
{
	uint8_t intbits;
	const uint8_t *list;
	const uint8_t *cfg;
	uint8_t i, n, len, en;
	uint8_t bmRequestType;
	uint8_t bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
	uint16_t desc_val;
	const uint8_t *desc_addr;
	uint8_t	desc_length;
	
	uint8_t rep_id;
	uint8_t rep_type;

	UENUM = 0;
	intbits = UEINTX;
	if (intbits & (1<<RXSTPI)) {
		bmRequestType = UEDATX;
		bRequest = UEDATX;
		wValue = UEDATX;
		wValue |= (UEDATX << 8);
		wIndex = UEDATX;
		wIndex |= (UEDATX << 8);
		wLength = UEDATX;
		wLength |= (UEDATX << 8);
		UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
		if (bRequest == GET_DESCRIPTOR) {
			list = (const uint8_t *)descriptor_list;
			for (i=0; ; i++) {
				if (i >= NUM_DESC_LIST) {
					UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
					return;
				}
				desc_val = pgm_read_word(list);
				if (desc_val != wValue) {
					list += sizeof(struct descriptor_list_struct);
					continue;
				}
				list += 2;
				desc_val = pgm_read_word(list);
				if (desc_val != wIndex) {
					list += sizeof(struct descriptor_list_struct)-2;
					continue;
				}
				list += 2;
				desc_addr = (const uint8_t *)pgm_read_word(list);
				list += 2;
				desc_length = pgm_read_byte(list);
				break;
			}
			len = (wLength < 256) ? wLength : 255;
			if (len > desc_length) len = desc_length;
			do {
				// wait for host ready for IN packet
				do {
					i = UEINTX;
				} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
				if (i & (1<<RXOUTI)) return;	// abort
				// send IN packet
				n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
				for (i = n; i; i--) {
					UEDATX = pgm_read_byte(desc_addr++);
				}
				len -= n;
				usb_send_in();
			} while (len || n == ENDPOINT0_SIZE);
			return;
		}
		if (bRequest == SET_ADDRESS) {
			usb_send_in();
			usb_wait_in_ready();
			UDADDR = wValue | (1<<ADDEN);
			return;
		}
		if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
			usb_configuration = wValue;
			usb_send_in();
			cfg = endpoint_config_table;
			for (i=1; i<5; i++) {
				UENUM = i;
				en = pgm_read_byte(cfg++);
				UECONX = en;
				if (en) {
					UECFG0X = pgm_read_byte(cfg++);
					UECFG1X = pgm_read_byte(cfg++);
				}
			}
			UERST = 0x1E;
			UERST = 0;
			return;
		}
		if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
			usb_wait_in_ready();
			UEDATX = usb_configuration;
			usb_send_in();
			return;
		}

		if (bRequest == GET_STATUS) {
			usb_wait_in_ready();
			i = 0;
			#ifdef SUPPORT_ENDPOINT_HALT
			if (bmRequestType == 0x82) {
				UENUM = wIndex;
				if (UECONX & (1<<STALLRQ)) i = 1;
				UENUM = 0;
			}
			#endif
			UEDATX = i;
			UEDATX = 0;
			usb_send_in();
			return;
		}
		#ifdef SUPPORT_ENDPOINT_HALT
		if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
		  && bmRequestType == 0x02 && wValue == 0) {
			i = wIndex & 0x7F;
			if (i >= 1 && i <= MAX_ENDPOINT) {
				usb_send_in();
				UENUM = i;
				if (bRequest == SET_FEATURE) {
					UECONX = (1<<STALLRQ)|(1<<EPEN);
				} else {
					UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
					UERST = (1 << i);
					UERST = 0;
				}
				return;
			}
		}
		#endif
		if (wIndex == GAMEPAD_INTERFACE) {
			if (bmRequestType == 0xA1) {
				if (bRequest == HID_GET_REPORT) {
					rep_type=(wValue>>8);
					rep_id=wValue&0xFF;
					switch(rep_type) {
						
					}
					usb_wait_in_ready();
					usb_send_in();
					return;
				}
				if (bRequest == HID_GET_IDLE) {
					usb_wait_in_ready();
					UEDATX = gamepad_idle_config;
					usb_send_in();
					return;
				}
				if (bRequest == HID_GET_PROTOCOL) {
					usb_wait_in_ready();
					UEDATX = gamepad_protocol;
					usb_send_in();
					return;
				}
			}
			if (bmRequestType == 0x21) {
				if (bRequest == HID_SET_REPORT) {
					rep_type=(wValue>>8);
					rep_id=wValue&0xFF;
					switch(rep_type) {
						// set OUTPUT report
						case 0x02:
						// handle the SetControlValue report
						if (rep_id == UCOM_RPTID_SET_CONTROL_VALUE)
						{
							uint8_t tmp=UEDATX;
....
						}
						break;
						default: break;
					}
					usb_wait_receive_out();
					
					usb_ack_out();
					usb_send_in();
					return;
				}
				if (bRequest == HID_SET_IDLE) {
					gamepad_idle_config = (wValue >> 8);
					usb_send_in();
					return;
				}
				if (bRequest == HID_SET_PROTOCOL) {
					gamepad_protocol = wValue;
					usb_send_in();
					return;
				}
			}
		}
	}
	UECONX = (1<<STALLRQ) | (1<<EPEN);	// stall
}

(I am apparently a newb that has no idea why the <code> tag has decided my code is all commented)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

will.s.owen wrote:

(I am apparently a newb that has no idea why the <code> tag has decided my code is all commented)

 

But I'm not sure what you're saying?  What comments?

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Jul 9, 2019 - 02:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did use that...  I may be incorrectly assuming it would color the code in a meaningful way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

will.s.owen wrote:
I may be incorrectly assuming it would color the code in a meaningful way.
Yup!  The editor happily colours your code, but the viewer does not.  Long-standing complaint around here...

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, thanks.

I also forgot to mention that the fuses are identical (e-0xf4,h-0xd9,l-0xff)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What happens if you load the unmodified uno code on the chip, does it work then?

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
https://www.onegold.com/join/7134f67c2b814c5ca8144a458eccfd61

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As it's a 16U2 have you considered something LUFA based for starters? As the code is guaranteed to work then any mis-behaviour is almost certainly a fault in your hardware.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim, if you mean dumping a working UNO's 16u2 into file and flashing my board's 16u2 with it; then 'yes, I have done that' and 'no, it doesn't work'

I am guessing there is a "everyone knows you have to ____ first, duh" that is in no document anywhere that I can find.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

will.s.owen wrote:
dumping a working UNO's 16u2 into file and flashing my board's 16u2 with it
And fuses?

 

If the UNO's 16u2 was locked, then it won't work anyway.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Jul 9, 2019 - 05:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The fuses are identical to a working UNO, as previously mentioned.  As to ' If the UNO's 16u2 was locked, then it won't work anyway. '  I am unsure what you are saying.  Can't read a locked chip?  Or what...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

will.s.owen wrote:
Can't read a locked chip
This.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, yes, I had confirmed that it isn't locked and that the file actually contains binary as expected.  Also, I have used many other firmware files for the 16u2 as provided in most UNO projects (for 'going back to an Arduino') and, of course,  ......\arduino-1.8.5\hardware\arduino\avr\firmwares\atmegaxxu2\.... 

I have multiple examples of my board, bread boarded UNO layouts, and minimal 16u2 layouts...  none of them will be recognized by a PC as a USB device when flashed with known-good firmware, and fuses are set to what a working UNO is set to.  There is almost certainly a missing, simple thing that I do not know.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

...or some repeated error I am making in each and every iteration.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps there is data in the EEPROM that is needed as well, perhaps VID/PID or configuration data???

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
https://www.onegold.com/join/7134f67c2b814c5ca8144a458eccfd61

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

That is certainly the case with my project (and I do write it).  When I read a working UNO, though, the eep appears blank.  If that is not *supposed* to be the case, it could certainly be the issue...  as I do not write the eep when testing the working UNO firmware.  Anyone know for sure?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have checked many times now... it is not the eep.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

[deleted]

 

Last Edited: Thu. Jul 11, 2019 - 09:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may be a stupid question but did you put the Zeners on the right way? If you put them the wrong way they'd short D+/D- to GND which would prevent USB from working. 

They should be oriented with the Cathode on the D+/- side and the anode to GND

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LIV2, not a stupid question as it would be an answer to the issue.   I also had not confirmed that on every board.  I have now, though, and it is not the issue.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still stalled on this...  hiring smarter people than me to take a look.  I will post my error when it is figured out.