LCDInfo.com http://forum.lcdinfo.com/ |
|
Using Cairo to draw on the USBD480 display http://forum.lcdinfo.com/viewtopic.php?f=19&t=2564 |
Page 1 of 1 |
Author: | Henri [ Fri Jan 02, 2009 17:40 ] |
Post subject: | Using Cairo to draw on the USBD480 display |
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; } |
Author: | Henri [ Fri Jan 02, 2009 17:47 ] |
Post subject: | |
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; } |
Author: | Curtis Newton [ Mon Oct 11, 2010 9:39 ] |
Post subject: | Re: Using Cairo to draw on the USBD480 display |
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. |
Author: | Henri [ Thu Oct 14, 2010 19:13 ] |
Post subject: | Re: Using Cairo to draw on the USBD480 display |
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. |
Author: | yo1dog [ Sun Mar 03, 2013 0:47 ] |
Post subject: | Re: Using Cairo to draw on the USBD480 display |
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. |
Page 1 of 1 | All times are UTC + 2 hours |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |