sample project, write 512 bytes to controller

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
ageurtse
Posts: 4
Joined: Sun Jan 08, 2012 10:39 am

sample project, write 512 bytes to controller

Post by ageurtse » Sun Jan 08, 2012 10:51 am

Hello,

i'm a newby on this forum.
I read and search the forum but i can't find some answers on my problem's

i build a test project around an ATmega8 running on 12Mhz attached is an lcd, backlight goes through the pwm. (schematic by lcd2usb project)

1) is it possible to send 512 bytes of data to the controller? (this is becaus i wan't to make an interface to a glcd)
2) is it possible to send more than 8 bytes at once to the controller ?
3) when i write 255 bytes, according to the output to the display all datapackets are writen. but when i use buffer[255] to control the backlight this won't work, what could be the cause of this?


you have to see this project, more as a learning project. I'm pretty new in C++ normaly i am a hobby programmer in Delphi. so the program on windows side is written in Delphi :)


Code: Select all

/* Name: main.c
 * Project: custom-class, a basic USB example
 * Author: Christian Starkjohann
 * Creation Date: 2008-04-09
 * Tabsize: 4
 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
 */

/*
This example should run on most AVRs with only little changes. No special
hardware resources except INT0 are used. You may have to change usbconfig.h for
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
at least be connected to INT0 as well.
We assume that an LED is connected to port B bit 0. If you connect it to a
different port or bit, change the macros below:
*/

#include <avr/eeprom.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>  /* for sei() */
#include <util/delay.h>     /* for _delay_ms() */

#include <avr/pgmspace.h>   /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h"        /* This is also an example for using debug macros */
#include "requests.h"       /* The custom request numbers we use */

#include "lcd.h"

#ifndef EEMEM
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif
 
/* bitmask of detected lcd controllers */
uchar controller = 0;

/* ------------------------------------------------------------------------- */
/* PWM units are used for contrast and backlight brightness */

/* contrast and brightness are stored in eeprom */
uchar eeprom_valid EEMEM;
uchar eeprom_contrast EEMEM;
uchar eeprom_brightness EEMEM;

static uchar buffer[512];
static uchar currentPosition, bytesRemaining;

struct {
  uchar report_id;
  unsigned short offset;
  uchar len;
} cmd_state;


void pwm_init(void) {

  /* check if eeprom is valid and set default values if not */
  /* initial values: full contrast and full brightness */
  if(eeprom_read_byte(&eeprom_valid) != 0x42) {

    /* write magic "eeprom is valid" marker 0x42 and default values */
    eeprom_write_byte(&eeprom_valid, 0x42);
    eeprom_write_byte(&eeprom_contrast, 0xff);
    eeprom_write_byte(&eeprom_brightness, 0xff);
  }

  /* PortB: set DDB1 and DDB2 => PORTB1 and PORTB2 are output */
  DDRB |= _BV(1) | _BV(2);
 
  /* Set Timer1:
    - Fast PWM,8bit => Mode 5 (WGM13=0,WGM12=1,WGM11=0,WGM10=1)
    - Output-Mode: lower voltage is higher contrast
      => Set OC1A on Compare Match, clear OC1A at BOTTOM, (inverting mode)
    COM1A1=1,COM1A0=1
    higher voltage is higher brightness
      => Clear OC1B on Compare Match, set OC1B at BOTTOM, (non-inverting mode)
    COM1B1=1,COM1B0=0
    - Timer runs at inernal clock with no prescaling => CS12=0,CS11=0,CS10=1
  */
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM10);
  TCCR1B = _BV(WGM12) | _BV(CS10);

  TIMSK &=( (~_BV(2)) & (~_BV(3)) & (~_BV(4)) & (~_BV(5)));

  OCR1A = eeprom_read_byte(&eeprom_contrast);
  OCR1B = eeprom_read_byte(&eeprom_brightness);
}

void set_contrast(uchar value) {
  /* store value in eeprom if it actually changed */
  if(value != eeprom_read_byte(&eeprom_contrast))
    eeprom_write_byte(&eeprom_contrast, value);

  OCR1A = value;  // lower voltage is higher contrast
}

void set_brightness(uchar value) {
  /* store value in eeprom if it actually changed */
  if(value != eeprom_read_byte(&eeprom_brightness))
    eeprom_write_byte(&eeprom_brightness, value);

  OCR1B = value;  // higher voltage is higher brightness
}



/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;
static uchar    dataBuffer[4];  /* buffer must stay valid when usbFunctionSetup returns */


    if(rq->bRequest == CUSTOM_RQ_ECHO){ /* echo -- used for reliability tests */
        dataBuffer[0] = rq->wValue.bytes[0];
        dataBuffer[1] = rq->wValue.bytes[1];
        dataBuffer[2] = rq->wIndex.bytes[0];
        dataBuffer[3] = rq->wIndex.bytes[1];
        usbMsgPtr = dataBuffer;         /* tell the driver which data to return */
        return 4;
    }

   if(rq->bRequest == 1){
      currentPosition = 0;                // initialize position index
          lcd_clrscr(LCD_CTRL_0);
        lcd_puts(LCD_CTRL_0, "start ");


      bytesRemaining = rq->wLength.word;  // store the amount of data requested
        if(bytesRemaining > sizeof(buffer)) // limit to buffer size
            bytesRemaining = sizeof(buffer);
        return USB_NO_MSG;        // tell driver to use usbFunctionWrite()   
      }

   if(rq->bRequest == 2){
      lcd_clrscr (LCD_CTRL_0);
        return 0;        // tell driver to use usbFunctionWrite()   
      }

    return 0x00;   /* default for not implemented requests: return no data back to host */
}


uchar usbFunctionWrite(uchar *data, uchar len)
{
    uchar i;
 
   if(len > bytesRemaining)            // if this is the last incomplete chunk
       len = bytesRemaining;               // limit to the amount we can store


   lcd_puts(LCD_CTRL_0, ".");   

    bytesRemaining -= len;
    for(i = 0; i < len; i++)
        buffer[currentPosition++] = data[i];

   if (bytesRemaining ==0)
   lcd_puts(LCD_CTRL_0, " stop");   

   return bytesRemaining == 0;             // return 1 if we have all data


     

}






/* ------------------------------------------------------------------------- */

int __attribute__((noreturn)) main(void)
{
uchar   i;

    wdt_enable(WDTO_1S);
    /* Even if you don't use the watchdog, turn it off here. On newer devices,
     * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
     */
    /* RESET status: all port bits are inputs without pull-up.
     * That's the way we need D+ and D-. Therefore we don't need any
     * additional hardware initialization.
     */
    odDebugInit();
    DBG1(0x00, 0, 0);       /* debug output: main starts */
    lcd_init(LCD_CTRL_0);
   usbInit();


   pwm_init();

    lcd_puts(LCD_CTRL_0, "LCD2USB v1.2");


    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();
   
    sei();
    DBG1(0x01, 0, 0);       /* debug output: main loop starts */
    for(;;){                /* main event loop */
        wdt_reset();
        usbPoll();
      set_brightness(buffer[63]);
    }
}

/* ------------------------------------------------------------------------- */


ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: sample project, write 512 bytes to controller

Post by ulao » Tue Jan 10, 2012 6:14 am

you can set it in chunks like so.

while (!usbInterruptIsReady()){ usbPoll(); } usbSetInterrupt((void *)&reportBuffer + 0, 8);
while (!usbInterruptIsReady()){ usbPoll(); } usbSetInterrupt((void *)&reportBuffer + 8, 8);
while (!usbInterruptIsReady()){ usbPoll(); } usbSetInterrupt((void *)&reportBuffer + 16, 8);
while (!usbInterruptIsReady()){ usbPoll(); } usbSetInterrupt((void *)&reportBuffer + 24, 8);
while (!usbInterruptIsReady()){ usbPoll(); } usbSetInterrupt((void *)&reportBuffer + 32, 8); ...

if you want to send more at once you need to abuse 1.0 standards. You would need to try this
viewtopic.php?f=8&t=4776&p=16050#p16050

Maybe using bulk in will allow it but I dont have any experience with that.

512 maybe pushing it a bit....

Post Reply