<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
	<link rel="self" type="application/atom+xml" href="https://forums.obdev.at/app.php/feed/topic/6481" />

	<title>Objective Development Forums</title>
	
	<link href="https://forums.obdev.at/index.php" />
	<updated>2012-03-01T21:19:21+02:00</updated>

	<author><name><![CDATA[Objective Development Forums]]></name></author>
	<id>https://forums.obdev.at/app.php/feed/topic/6481</id>

		<entry>
		<author><name><![CDATA[Anonymous]]></name></author>
		<updated>2012-03-01T21:19:21+02:00</updated>

		<published>2012-03-01T21:19:21+02:00</published>
		<id>https://forums.obdev.at/viewtopic.php?t=6481&amp;p=21072#p21072</id>
		<link href="https://forums.obdev.at/viewtopic.php?t=6481&amp;p=21072#p21072"/>
		<title type="html"><![CDATA[Communication problem]]></title>

		
		<content type="html" xml:base="https://forums.obdev.at/viewtopic.php?t=6481&amp;p=21072#p21072"><![CDATA[
I'm working on a project using V-USB and have a problem with communication with the host (Win XP, C#). Every report ID is working except one that is not transmitted properly. That contains an uint32_t and an uint16_t. The uint32_t represents the seconds of a software RTC and the uint16_t the milliseconds of the same RTC.<br /><br />When I read that report with my host application it works fine up to 429 seconds, but when the RTC reaches 430 seconds I read 0. Then it counts up to 429 again, again wrapping around to 0 and so on. The problem stays the same when I change the starting value, so I assume it's not an issue that appears when the device ran for more than 429 seconds.<br /><br />On PB1 a LED is connected that shall light when 429 seconds have passed. This LED turns on as it should and stays on afterwards until I disconnect (pull the USB-plug) and reconnect the device. So I assume the content of the variable is higher than 429, but I still read 0.<br /><br />Does somebody have an idea what could cause that behaviour?<br /><br />Down below you can find the code which I reduced to a minimum, but the problem still remains. <br /><div class="codebox"><p>Code: </p><pre><code>#include &lt;avr/io.h&gt;<br />#include &lt;avr/wdt.h&gt;          /* watchdog */<br />#include &lt;avr/interrupt.h&gt;    /* for sei() */<br />#include &lt;util/delay.h&gt;       /* for _delay_ms() */<br />#include &lt;string.h&gt;           /* for memcpy */<br /><br />#include &lt;avr/pgmspace.h&gt;     /* required by usbdrv.h */<br />#include &quot;usbdrv.h&quot;           /* v-usb driver */<br /><br />#include &quot;configUSBIRRemoteReceiver.h&quot; /* USB-IRRR config file */<br /><br />#ifndef F_CPU<br />   #error F_CPU unknown<br />#endif<br /><br />#ifdef USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH<br />   #undef USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH<br />#endif<br />#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    134<br /><br />#define F_INTERRUPTS                            10000<br /><br />#define CPU_CYCLES_BETWEEN_INTERRUPTS  (F_CPU/F_INTERRUPTS)<br /><br />/* const for V-USB feature report ID handling */<br />enum ReportID {<br />   noReport             = 0,<br />   NewIRCodeAvailable   = 1,<br />   ReadPowerOnEnabled   = 2,<br />   ReadTrainedIRCode    = 3,<br />   SetPowerOnEnabled    = 4,<br />   SetTrainedIRCode     = 5,<br />   repIRPollingTime     = 6,<br />   ReadIrmpVersion      = 7,<br />   repMinRepeats        = 8,<br /><br />// keep some spare report IDs for future use of USB-IRRR<br />   repCurrentTime       = 50,<br />   repXtalFrequency     = 51,<br />   repWakeupTime        = 52,<br />   repWakeupTimeSpan    = 53,<br />   repPowerOffIRCode    = 55,<br />};<br /><br />/* ------------------------------------------------------------------------- */<br />/* ----------------------------- USB interface ----------------------------- */<br />/* ------------------------------------------------------------------------- */<br />PROGMEM char usbHidReportDescriptor&#91;USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH&#93; = {<br />    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)<br />    0x0b, 0x01, 0x00, 0x00, 0xff,  // USAGE (Vendor Defined Page 1:Vendor Usage 1)<br />    0xa1, 0x01,                    // COLLECTION (Application)<br />    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)<br />    0x75, 0x08,                    //   REPORT_SIZE (8)<br />    0x85, NewIRCodeAvailable,      //   REPORT_ID<br />    0x95, 0x06,                    //   REPORT_COUNT (6)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0x82, 0x00, 0x01,              //   INPUT (Data,Ary,Abs,Buf)<br />    0x85, ReadPowerOnEnabled,      //   REPORT_ID<br />    0x95, 0x01,                    //   REPORT_COUNT (1)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, ReadTrainedIRCode,       //   REPORT_ID<br />    0x95, 0x06,                    //   REPORT_COUNT (6)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, SetPowerOnEnabled,       //   REPORT_ID<br />    0x95, 0x01,                    //   REPORT_COUNT (1)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, SetTrainedIRCode,        //   REPORT_ID<br />    0x95, 0x06,                    //   REPORT_COUNT (6)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repIRPollingTime,        //   REPORT_ID<br />    0x95, 0x02,                    //   REPORT_COUNT (2)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, ReadIrmpVersion,         //   REPORT_ID<br />    0x95, 0x0A,                    //   REPORT_COUNT (10)   // works only when reading from device<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repMinRepeats,           //   REPORT_ID<br />    0x95, 0x01,                    //   REPORT_COUNT (1)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repCurrentTime,          //   REPORT_ID           // Current date<br />    0x95, 0x07,                    //   REPORT_COUNT (6)    // time in seconds (element 1-4) and msec (element 5&amp;6)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repXtalFrequency,        //   REPORT_ID           // XTAL frequency<br />    0x95, 0x04,                    //   REPORT_COUNT (4)    // Data format: uint32/Hz<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repWakeupTime,           //   REPORT_ID           // Wakeup Date and time<br />    0x95, 0x04,                    //   REPORT_COUNT (4)    // time in seconds<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repWakeupTimeSpan,       //   REPORT_ID           // span of wakeup time<br />    0x95, 0x01,                    //   REPORT_COUNT (1)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0x85, repPowerOffIRCode,       //   REPORT_ID           // IR code for shutting the PC down<br />    0x95, 0x06,                    //   REPORT_COUNT (6)<br />    0x09, 0x00,                    //   USAGE (Undefined)<br />    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)<br />    0xc0                           // END_COLLECTION<br />};  // don't forget to update USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH when you change this array<br /><br /><br />/* The following variables store the status of the current data transfer */<br />static uchar   currentAddress    = 0;<br />static uchar   bytesRemaining    = 0;<br />enum ReportID  DoWriteReport     = noReport;<br />enum ReportID  DoReadReport      = noReport;<br /><br /><br />/* global variables */<br />static uint32_t   CurrentTime          = 415;<br />static uint16_t   InterruptTicks       = 0;  // count how often timer ISR was executed each second<br />static int16_t    ClockDeviation       = 0;<br /><br />/* reply buffer should be big enough to cover also the irmp version ! */<br />static uchar      replyBuf&#91;16&#93;;<br /><br /><br />/* ------------------------------------------------------------------------- */<br />/* main functions for irmp                                                   */<br />/* ------------------------------------------------------------------------- */<br />void init_timer1 (void)<br />{<br />   /* IR polling timer */<br />   TCCR1B  = (1 &lt;&lt; WGM12) | (1 &lt;&lt; CS10);     // switch CTC Mode on, set prescaler to 1<br /><br />   // may adjust IR polling rate here to optimize IR receiving:<br />   OCR1A   =  (F_CPU / F_INTERRUPTS) - 1;    // compare value: 1/15000 of CPU frequency<br /><br />   // enable Timer1 for IR polling<br />   #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) \<br />    || defined (__AVR_ATmega64__) || defined (__AVR_ATmega162__)<br />      TIMSK = 1 &lt;&lt; OCIE1A;       // Timer1A ISR activate<br />   #else<br />      TIMSK1  = 1 &lt;&lt; OCIE1A;     // Timer1A ISR activate<br />   #endif   // __AVR...<br />}<br /><br /><br />/*-----------------------------------------------------------------------------------------------------------------<br /> * init all io pins of the AVR, first all to input with pullups. then config USB and output pin<br /> *---------------------------------------------------------------------------------------------------------------*/<br />void init_io(void) <br />{<br />   /* USB pins */<br />   USBOUT ^= _BV(USB_CFG_DMINUS_BIT) | _BV(USB_CFG_DPLUS_BIT);    /* deactivate pull-ups on USB lines */<br />   <br />   PORTB &amp;= ~ (1 &lt;&lt; PB1);<br />   DDRB = (1 &lt;&lt; PB1);<br />}<br /> <br /><br />/*-----------------------------------------------------------------------------------------------------------------<br /> * timer 1 compare handler, should be called every 1/10000 sec<br /> *---------------------------------------------------------------------------------------------------------------*/<br />void TIMER1_COMPA_vect(void) __attribute__((interrupt));<br />void TIMER1_COMPA_vect(void)<br />{<br />   static int16_t TimeError = 0;    // RTC error compensation<br /><br />   // RTC error correction<br />   if ( TimeError &gt;= CPU_CYCLES_BETWEEN_INTERRUPTS )        // RTC too fast<br />   {<br />      //InterruptTicks += 0  // add zero ticks<br />      TimeError -= CPU_CYCLES_BETWEEN_INTERRUPTS;<br />   }<br />   else if ( TimeError &lt;= -CPU_CYCLES_BETWEEN_INTERRUPTS )  // RTC too slow<br />   {<br />      InterruptTicks += 2; // add two ticks<br />      TimeError += CPU_CYCLES_BETWEEN_INTERRUPTS;     <br />   }<br />   else<br />   {<br />      InterruptTicks += 1; // add one ticks<br />   }<br /><br />   // compute time every second<br />   if ( InterruptTicks &gt;= F_INTERRUPTS )  // one second has passed<br />   {<br />      CurrentTime++;                      // add one second<br />      TimeError += ClockDeviation;        // accumulate deviation<br />      InterruptTicks -= F_INTERRUPTS;     // subtract number of interrupts per second<br />   }<br />}<br /><br /><br />/* ------------------------------------------------------------------------- */<br />/* usbFunctionRead() is called when the host requests a chunk of data from<br /> * the device. For more information see the documentation in usbdrv/usbdrv.h.<br /> */<br />uchar usbFunctionRead(uchar *data, uchar len)<br />{<br />   if(len &gt; bytesRemaining)<br />      len = bytesRemaining;<br /><br />   if ( DoReadReport == repCurrentTime )<br />   {<br />      uint16_t temp;<br />      cli();                                                  // don't allow any interrupts here<br />      temp = InterruptTicks / (F_INTERRUPTS / 1000);          // scale InterruptTicks to msec<br />      memcpy(&amp;data&#91;1&#93;, &amp;CurrentTime, sizeof(CurrentTime));    // copy data to buffer<br />      memcpy(&amp;data&#91;5&#93;, &amp;temp, sizeof(InterruptTicks));        // copy data to buffer<br />      sei();<br />   }<br /><br />   currentAddress += len;<br />   bytesRemaining -= len;<br />   return len;<br />}<br /><br /><br />/* ------------------------------------------------------------------------- */<br />/* usbFunctionWrite() is called when the host sends a chunk of data to the<br /> * device. For more information see the documentation in usbdrv/usbdrv.h.<br /> */<br />uchar usbFunctionWrite(uchar *data, uchar len)<br />{<br />   if(bytesRemaining == 0)<br />      return 1;               /* end of transfer */<br />   if(len &gt; bytesRemaining)<br />      len = bytesRemaining;<br /><br />   if ( DoWriteReport == repCurrentTime )<br />   {<br />/*      cli();                                          // don't allow any interrupts here<br />      memcpy(&amp;CurrentTime, &amp;data&#91;1&#93;, sizeof(CurrentTime)); // update CurrentTime with received data<br />      memcpy(&amp;InterruptTicks, &amp;data&#91;5&#93;, sizeof(InterruptTicks)); // update Int.Ticks with received data<br />      InterruptTicks = InterruptTicks * (F_INTERRUPTS / 1000); // scale InterruptsTicks<br />      sei();<br />*/   }<br />   <br />   currentAddress += len;<br />   bytesRemaining -= len;<br />   return bytesRemaining == 0;                                          /* return 1 if this was the last chunk */<br />}<br /><br /><br />/* ------------------------------------------------------------------------- */<br />usbMsgLen_t usbFunctionSetup(uchar data&#91;8&#93;)<br />{<br />   usbRequest_t   *rq = (void *)data;<br /><br />   if((rq-&gt;bmRequestType &amp; USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)        // HID class request<br />   {<br />/* ----------------------------------------------------------- GET REPORT (device -&gt; host) -- */<br />      if(rq-&gt;bRequest == USBRQ_HID_GET_REPORT)              // wValue: ReportType (highbyte), ReportID (lowbyte)<br />      {<br />         usbMsgPtr = replyBuf;<br /><br />         memcpy(&amp;replyBuf&#91;0&#93;, &amp;rq-&gt;wValue.bytes&#91;0&#93;, sizeof(uchar));     // copy report id<br /><br />         if(rq-&gt;wValue.bytes&#91;0&#93; == repCurrentTime)                 /* Report: Current Time */<br />         {<br />            bytesRemaining = sizeof(CurrentTime) + sizeof(InterruptTicks) + sizeof(uchar);<br />            DoReadReport = repCurrentTime;<br />            return USB_NO_MSG;<br />         }<br />      }<br />/* ----------------------------------------------------------- SET REPORT (host -&gt; device) -- */<br />      else if(rq-&gt;bRequest == USBRQ_HID_SET_REPORT)<br />      {<br />         if(rq-&gt;wValue.bytes&#91;0&#93; == repCurrentTime)           /* Report: Current Date */<br />         {<br />/*            bytesRemaining = sizeof(CurrentTime) + sizeof(InterruptTicks);<br />            DoWriteReport = repCurrentTime;<br />            return USB_NO_MSG;<br />*/         }<br />      }<br />   }<br />   else<br />   {<br />      // ignore vendor type requests, we don't use any<br />   }<br />   return 0;<br />}<br /><br /><br />/* ------------------------------------------------------------------------- */<br />/* main function<br />*/<br />int main(void)<br />{<br />   uchar i = 0;<br /><br />   wdt_disable();             // disable watchdog<br /><br />   init_io();<br />   init_timer1();             // initialize timer<br /><br />   usbDeviceDisconnect();     /* enforce re-enumeration, do this while interrupts are disabled! */<br />   while(--i){                /* fake USB disconnect for &gt; 500 ms */<br />      _delay_ms(5);<br />   }<br />   usbDeviceConnect();<br /><br />   usbInit();                 // initialize v-usb<br />   sei();                     // enable global int<br />   <br />   for(;;)  /* main event loop */<br />   {<br />      uint32_t temptime;<br />      <br />      usbPoll();              // do a USB poll<br /><br />      cli();<br />      temptime = CurrentTime;<br />      sei();<br />      <br />      if (temptime &gt; 429)<br />      {<br />         PORTB |= (1 &lt;&lt; PB1);<br />      }<br />      else<br />      {<br />         PORTB &amp;= ~(1 &lt;&lt; PB1);<br />      }<br />      <br />      _delay_ms(255);<br />   }<br />   return 0;<br />}<br /></code></pre></div><p>Statistics: Posted by Guest — Thu Mar 01, 2012 9:19 pm</p><hr />
]]></content>
	</entry>
	</feed>
