1
\$\begingroup\$

I'm working UART data transfer from one ATmega8 to other while the receiver runs VUSB acting as HID Mouse to the PC.

UART though init with 9600 , later is set to max speed - > UBRR = 0;

Problems :

  1. VUSB isnt stable on both interrupt based comm. or non interrupt based comm.
  2. I was succesfull to have it stable only once .. but the data received was garbage.

How do I overcome these problems ..

made a small protocol for data ..

SYNC_START X Y END_SYNC

the transmitter code:

//////////////////////////////////////////////////////////////////////////
//Defines
//////////////////////////////////////////////////////////////////////////
#define F_CPU       16000000UL
#define true        0x01
#define false       0x00
#define uchar       unsigned char
#define uint        unsigned int

#define START_SYNC_BYTE 0b10101010
#define END_SYNC_BYTE   0b01010101
//////////////////////////////////////////////////////////////////////////

#include <avr/io.h>
#include <util/delay.h>

#include "uart/UART.h"
#include "IMU.h"

//////////////////////////////////////////////////////////////////////////
//GLOBAL VARIABLES
//////////////////////////////////////////////////////////////////////////
uint X=0,Y=0;
//////////////////////////////////////////////////////////////////////////


int main(void)
{
    i2c_init();
    WakeUpIMU();

    UART_Init(9600,true,false,false);

    UBRRH = 0;
    UBRRL = 0;


    while(1)
    {
        X = Get16Bits(MPU6050_RA_ACCEL_XOUT_H);
        Y = Get16Bits(MPU6050_RA_ACCEL_YOUT_H);

        BlockingTransmitt(START_SYNC_BYTE);
        BlockingTransmitt(START_SYNC_BYTE);
        BlockingTransmitt(X);
        BlockingTransmitt(Y);
        BlockingTransmitt(END_SYNC_BYTE);

        _delay_ms(5);
    }
}

The receiver Code :

//////////////////////////////////////////////////////////////////////////
//Defines
//////////////////////////////////////////////////////////////////////////
#define F_CPU       16000000UL
#define true        0x01
#define false       0x00
#define uchar       unsigned char
#define uint        unsigned int

#define START_SYNC_BYTE 0b10101010
#define END_SYNC_BYTE   0b01010101
//////////////////////////////////////////////////////////////////////////

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <util/delay.h>

#include "uart/UART.h"
#include "usbdrv/usbdrv.h"

//////////////////////////////////////////////////////////////////////////
//GLOBAL VARIABLES
//////////////////////////////////////////////////////////////////////////
uint X,Y;
bool WaitingForX=false,WaitingForY=false;
bool TransmissionComplete = false;
//////////////////////////////////////////////////////////////////////////



PROGMEM const char usbHidReportDescriptor[52] =
{ /* USB report descriptor, size must match usbconfig.h */
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xA1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM
    0x29, 0x03,                    //     USAGE_MAXIMUM
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Const,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x09, 0x38,                    //     USAGE (Wheel)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7F,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xC0,                          //   END_COLLECTION
    0xC0,                          // END COLLECTION
};

typedef struct{
    uchar   buttonMask;
    char    dx;
    char    dy;
    char    dWheel;
}report_t;


static report_t reportBuffer;
static uchar    idleRate;

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
    usbRequest_t    *rq = (void *)data;

    /* The following requests are never used. But since they are required by
    * the specification, we implement them in this example.
    */
    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 */
            usbMsgPtr = (void *)&reportBuffer;
            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;   /* default for not implemented requests: return no data back to host */
}



int main(void)
{
    uchar i;

    wdt_enable(WDTO_1S);

    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    i = 0;
    while(--i){             /* fake USB disconnect for > 250 ms */
        wdt_reset();
        _delay_ms(1);
    }
    usbDeviceConnect();

    UART_Init(9600 , false , true , false);
    UBRRH = 0;
    UBRRL = 0;

    sei();

    while(1)
    {
        wdt_reset();

        usbPoll();

        RecieveUARTdata();


        if(TransmissionComplete && usbInterruptIsReady()){
            /* called after every poll of the interrupt endpoint */
            usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
        }

    }
    return 0;
}

void ResetValues(){
    X=0;Y=0;
    WaitingForX=false;
    WaitingForY=false;
}



void RecieveUARTdata(){
    //Get the data is available by checking the RXC in UCSRA
    if ( UCSRA & (1<<RXC) )
    {
        uint data = UDR;
        //if the data received is START SYNC DATA
        if(data==START_SYNC_BYTE){
            WaitingForX = true;return;
        }

        else {
            if(WaitingForX){
                X=data; WaitingForX=false;
                WaitingForY=true;return;
            }
            else if(WaitingForY && !WaitingForX){
                Y=data; WaitingForY=false;return;
            }
            else if(!WaitingForX && !WaitingForY && (UDR==END_SYNC_BYTE)){
                reportBuffer.dx = X;
                reportBuffer.dy = Y;
                TransmissionComplete = true;return;
            }else ResetValues();
            return;
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ I doubt that the UARt module is intended to work with a baud-rate divisor of 0. Try setting it to 1 or 2 at least. \$\endgroup\$ – brhans Apr 18 '16 at 16:30
  • \$\begingroup\$ @brhans UBRR = 0 is fine. \$Baud = Fosc/(16(UBRR+1))\$ \$\endgroup\$ – Tom Carpenter Apr 18 '16 at 16:33
  • \$\begingroup\$ @Akash, you should only read the UBR register once, not multiple times. There is a FIFO on the UART block and when you read the register it moves on to the next value in the FIFO. \$\endgroup\$ – Tom Carpenter Apr 18 '16 at 16:39
  • 2
    \$\begingroup\$ if(UDR==START_SYNC_BYTE){ reads the value then forgets it. ...X=UDR; reads it a second time which can corrupt the value. You should do uint8_t in = UDR; and then if(in==START_SYNC_BYTE){...X=in; \$\endgroup\$ – Tom Carpenter Apr 18 '16 at 16:39
  • 1
    \$\begingroup\$ The other thing is you appear to be sending a 16bit value for X and another for Y. But then you are receiving an 8bit value for X and Y. Where did the other two bytes go? \$\endgroup\$ – Tom Carpenter Apr 18 '16 at 17:41
1
\$\begingroup\$

There is one main issue that has been pointed in comments:

if ( UCSRA & (1<<RXC) )
{
    uint data = UDR;
    ...
        else if(!WaitingForX && !WaitingForY && (UDR==END_SYNC_BYTE)){
            ...
    }
}

In this part you are reading from empty UDR as the END_SYNC_BYTE is stored earlier, so this statement is about to be always false.

The less complicated way is to store each incoming byte into FIFO buffer (or even use interrupt based lib that can deal with v-usb) and process entire message in one run.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.