LCDInfo.com

http://www.lcdinfo.com
It is currently Sun Apr 30, 2017 1:26

All times are UTC + 2 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Fri Jan 02, 2009 17:40 
Offline

Joined: Sun May 05, 2002 22:05
Posts: 2063
Location: Lappeenranta, Finland
Here is an example of using the Cairo graphics library to draw simple shapes on the display.

http://www.cairographics.org/
http://www.cairographics.org/samples/

Code:
#include <cairo-win32.h>
#include "USBD480_lib.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

DisplayInfo DisplayProperties;

int main(int argc, char* argv[])
{
   int width = 480;
   int height = 272;
   int i;

   int displays = USBD480_GetNumberOfDisplays();
   if(displays < 1)
   {
      printf("No displays found\n\r");
      return 0;
   }
   else
   {
      printf("%d display(s) found\n\r", displays);   
   }

   for(i=0; i<displays; i++)
   {
      int ret = USBD480_GetDisplayConfiguration(i, &DisplayProperties);
      
      if(ret == USBD480_OK)
         printf("Display: %s, %s, %d, %d, %d\n\r", DisplayProperties.Name,
               DisplayProperties.Username, DisplayProperties.Width, DisplayProperties.Height,
               DisplayProperties.Version);
      else
         printf("Unable to get display info\n\r");
   }

   int ret = USBD480_Open(&DisplayProperties,  0);
   if(ret == USBD480_OK)
   {      
      cairo_surface_t * surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
      cairo_t * cr = cairo_create (surface);

      /* Normalize our context to a (width, height) of (1.0, 1.0) by scaling by our window width and height. */
      //cairo_scale (cr, height, height);
      //cairo_scale (cr, 1, 1);

      /* draw the entire context white. */
      cairo_set_source_rgba (cr, 1, 1, 1, 1);
      cairo_paint(cr);
   
      /* who doesn't want all those nice line settings :) */
        //cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
        //cairo_set_line_width(cr, 0.1);
      cairo_set_line_width(cr, 1);

      cairo_set_source_rgba (cr, 0, 0, 1, 1);
        cairo_move_to(cr, 0, 0);
        //cairo_line_to(cr, 0.5, 0.5);
      cairo_line_to(cr, 100, 100);
        cairo_stroke (cr);

      static unsigned int count = 0;

      static double const trs[8][8] = {
        { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
        { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
        { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
        { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
        { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
        { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
        { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
        { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
      };

      cairo_translate(cr, width / 2, height /2);

      int i = 0;
      for (i = 0; i < 8; i++)
      {
         cairo_set_line_width(cr, 3);
         cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
         cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);

         cairo_move_to(cr, 0.0, -10.0);
         cairo_line_to(cr, 0.0, -40.0);
         cairo_rotate(cr, M_PI/4);

         cairo_stroke(cr);
      }

      cairo_set_source_rgba (cr, 0, 0, 0, 1);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 30, 30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 480-30, 30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 480-30, 272-30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 30, 272-30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);


      // some text
      cairo_select_font_face(cr, "Georgia", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
      cairo_set_font_size (cr, 0.10);
      cairo_show_text (cr, "Hello world!");


      // now draw cairo surface to the display
      USBD480_DrawFullScreenBGRA32(&DisplayProperties, (uint32_t*)cairo_image_surface_get_data(surface));

      cairo_destroy (cr);
      cairo_surface_destroy (surface);

      USBD480_Close(&DisplayProperties);

   }
   else
   {
      printf("Unable to open display\n");
   }

   return 0;
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 02, 2009 17:47 
Offline

Joined: Sun May 05, 2002 22:05
Posts: 2063
Location: Lappeenranta, Finland
Here is the same example modified to use direct Libusb commands for handling the display instead of the Windows DLL. This should be quite portable for different environments.

Code:
#include "usb.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define USBD480_VID 0x16C0
#define USBD480_PID 0x08A6

#define USBD480_SET_ADDRESS  0xC0 // set sdram address
#define USBD480_SET_FRAME_START_ADDRESS 0xC4 // set frame start address

static struct usb_device *find_usbd480(void)
{
    struct usb_bus *usb_bus;
    struct usb_device *dev;
   
    usb_find_busses();
    usb_find_devices();
    for (usb_bus = usb_busses; usb_bus; usb_bus = usb_bus->next) {
        for (dev = usb_bus->devices; dev; dev = dev->next) {
            if ((dev->descriptor.idVendor == USBD480_VID) &&
                (dev->descriptor.idProduct == USBD480_PID))
                return dev;
        }
    }
    return NULL;
}


int main(int argc, char* argv[])
{
   struct usb_device *usbdev;
   usb_dev_handle *usb_handle = NULL;

   int result;
   unsigned int addr;
   unsigned int writesize;

   int width = 480;
   int height = 272;

   usb_init();
   usbdev = find_usbd480();
   
   if(usbdev)
   {
      usb_handle = usb_open(usbdev);
   
      if(usb_handle==NULL)
         printf("error: usb_open\n");
      
      if(usb_set_configuration(usb_handle, 1) < 0)
      {
         printf("error: setting config 1 failed\n");
         printf("%s\n", usb_strerror() );
         usb_close(usb_handle);
         return 0;
      }
      
      if(usb_claim_interface(usb_handle, 0) < 0)
      {
         printf("error: claiming interface 0 failed\n");
         printf("%s\n", usb_strerror() );
         usb_close(usb_handle);
         return 0;
      }

      cairo_surface_t * surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
      cairo_t * cr = cairo_create (surface);

      /* Normalize our context to a (width, height) of (1.0, 1.0) by scaling by our window width and height. */
      //cairo_scale (cr, height, height);
      //cairo_scale (cr, 1, 1);

      /* draw the entire context white. */
      cairo_set_source_rgba (cr, 1, 1, 1, 1);
      cairo_paint(cr);
   
      /* who doesn't want all those nice line settings :) */
        //cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
        //cairo_set_line_width(cr, 0.1);
      cairo_set_line_width(cr, 1);

      cairo_set_source_rgba (cr, 0, 0, 1, 1);
        cairo_move_to(cr, 0, 0);
        //cairo_line_to(cr, 0.5, 0.5);
      cairo_line_to(cr, 100, 100);
        cairo_stroke (cr);

      static unsigned int count = 0;

      static double const trs[8][8] = {
        { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
        { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
        { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
        { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
        { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
        { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
        { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
        { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
      };

      cairo_translate(cr, width / 2, height /2);

      int i = 0;
      for (i = 0; i < 8; i++)
      {
         cairo_set_line_width(cr, 3);
         cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
         cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);

         cairo_move_to(cr, 0.0, -10.0);
         cairo_line_to(cr, 0.0, -40.0);
         cairo_rotate(cr, M_PI/4);

         cairo_stroke(cr);
      }

      cairo_set_source_rgba (cr, 0, 0, 0, 1);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 30, 30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 480-30, 30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 480-30, 272-30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);

      cairo_identity_matrix(cr);
      cairo_translate(cr, 30, 272-30);
      cairo_move_to(cr, 0.0, 20.0);
      cairo_line_to(cr, 0.0, -20.0);
      cairo_stroke(cr);
      cairo_move_to(cr, 20.0, 0.0);
      cairo_line_to(cr, -20.0, 0.0);
      cairo_stroke(cr);


      // some text
      cairo_select_font_face(cr, "Georgia", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
      cairo_set_font_size (cr, 0.10);
      cairo_show_text (cr, "Hello world!");


      // now draw cairo buffer to display
        unsigned char* surface_data;
      unsigned char rgb565_buf[262144];
      unsigned short *outbuf;
      int r2,g2,b2;

      outbuf = (unsigned short *)&rgb565_buf;
      surface_data = cairo_image_surface_get_data (surface);

      // conversion from 32 bit RGB to 16 bit RGB565
      for(int i=0; i<480*272; i++)
      {
            b2 = (*surface_data++ & 0xf8) >> 3;
            g2 = (*surface_data++ & 0xfc) << 3;
            r2 = (*surface_data++ & 0xf8) << 8;
            *surface_data++;

            *outbuf++ = r2 | g2 | b2;
      }

      writesize = 262144;
      addr = 0;

      result = usb_control_msg( usb_handle, 0x40, USBD480_SET_ADDRESS, addr, (addr>>16)&0xffff, NULL, 0, 500);

      if(result = usb_bulk_write( usb_handle, 0x02, (char*)rgb565_buf, writesize, 500) != writesize)
         printf("bulk_write error %d\n", result);


      cairo_destroy (cr);
      cairo_surface_destroy (surface);


      usb_release_interface(usb_handle, 0);
      usb_close(usb_handle);
   }
   else
   {
      printf("No USBD480 device found\n");
   }

   return 0;
}


Top
 Profile  
 
PostPosted: Mon Oct 11, 2010 9:39 
Offline

Joined: Tue Apr 27, 2010 15:06
Posts: 2
Hi,

why is writesize = 262144 when (480*272*2)=261120?

Also, int find_usbd480, should the dev also be static:

static struct usb_device *find_usbd480(void)
{
struct usb_bus *usb_bus;
static struct usb_device *dev;
...

C.


Top
 Profile  
 
PostPosted: Thu Oct 14, 2010 19:13 
Offline

Joined: Sun May 05, 2002 22:05
Posts: 2063
Location: Lappeenranta, Finland
Curtis Newton wrote:
why is writesize = 262144 when (480*272*2)=261120?

In this case looks like it has just been rounded up to full 256KB. There's really no reason for that and the more correct value would be the exact 261120. Sending that extra 1024 bytes shouldn't be an issue in most cases though.

Curtis Newton wrote:
Also, int find_usbd480, should the dev also be static:

static struct usb_device *find_usbd480(void)
{
struct usb_bus *usb_bus;
static struct usb_device *dev;
...

C.

I don't really see why the pointer would need to be static in this case. The old value is not needed if the function is executed again.


Top
 Profile  
 
PostPosted: Sun Mar 03, 2013 0:47 
Offline

Joined: Tue Feb 12, 2013 17:47
Posts: 2
Henri wrote:
Curtis Newton wrote:
why is writesize = 262144 when (480*272*2)=261120?

In this case looks like it has just been rounded up to full 256KB. There's really no reason for that and the more correct value would be the exact 261120. Sending that extra 1024 bytes shouldn't be an issue in most cases though.

Actually Curtis is correct. Sending over the incorrect size can result in an error in the USB bulk write. Before seeing this post I was using 262144 and I would sporadically get:
Code:
bulk_write error. -14
USB error: error submitting URB: Bad address

It would also not draw the last 10 or so lines on the LCD. After I set it to the correct size I no longer get this error.

To reiterate: use 261120 NOT 262144.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 2 hours


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group