by on
Avr Development

It seems like all I do nowadays is to try to decipher other peoples code.

Which make a body feel a lot like a teething toddler.

One of my projects is an an avr programmer based on the new AT90USB  using Dean Camera’s MyUSB library. In it there are two examples using the driverless serial class (CDC/ACM). The examples are deceptively straightforward.

I was able to bring up a functioning serial port which works on OSX, Windows, and Linux in a very short time. The problem was that I needed to implement the DTR and what I eventually want to wind up with is a reset pulse where the DTR pin used to be.

My present understanding of the way that the USB CDC Modem class handles RTS and DTR is that the host computer sends a control packet to the device telling it the state of those lines. This is described in  the document entitled “Universal Serial Bus Class Definitions for Communication Devices”
http://www.usb.org/developers/devclass_docs/usbcdc11.pdf. and should be handled in the USBtoSerial code in the file USBtoSerial.c

After much wrestling to understand Deans implementation of “handlers” I came up with the following fragment of code  which turns on led3 when the dtr line should be pulled low.

#define SET_CONTROL_LINE_STATE_RTS_MASK 0x0002
#define SET_CONTROL_LINE_STATE_DTR_MASK 0x0001
EVENT_HANDLER(USB_UnhandledControlPacket)
{
uint8_t* LineCodingData = (uint8_t*)&LineCoding;
uint16_t wValue;
//Endpoint_Ignore_Word(); <- cant do this
wValue = Endpoint_Read_Word_LE();
/* Process CDC specific control requests */
switch (Request)
{
 case ....
 .... break;
 case SET_CONTROL_LINE_STATE:
 if (RequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 {
  if (wValue & SET_CONTROL_LINE_STATE_DTR_MASK) {
    LEDs_TurnOnLEDs(LEDS_LED3); //handle DTR
  } else {
    LEDs_TurnOffLEDs(LEDS_LED3);
  }
  if (wValue & SET_CONTROL_LINE_STATE_RTS_MASK) {
     LEDs_TurnOnLEDs(LEDS_LED1); //handle RTS
  } else {
     LEDs_TurnOffLEDs(LEDS_LED1);
  }
  Endpoint_ClearSetupReceived();
  Endpoint_Setup_In_Clear();
  while (!(Endpoint_Setup_In_IsReady()));
 }
 break;
}

Two problems I had with grocking the original code were the presence of the mystery variables “Request” and “RequestType”. These variables are created by the macro EVENT_HANDLER(USB_UnhandledControlPacket). As this is a new library the documentation doesnt cover the nuances of the public interfaces build into it.

The other was finding the data. I never did really figure out how I was supposed to figure this out but what I did find in the file DevChapter9.c was a comment

Endpoint_Ignore_Word(); // Ignore unused Value word

Which I realized was the wValue word from the usb documentation.

Now I need to figure out enough about MyUSBs task manager to make a pulse and let the blinking lights stay on long enough to see them when sending and receiving data.

Leave a Reply

  • (will not be published)