Merge branch 'master' into newmouse

ugfx_release_2.6
inmarket 2014-08-12 16:45:06 +10:00
commit 5460a923ab
65 changed files with 2285 additions and 865 deletions

View File

@ -194,7 +194,7 @@ static void createWidgets(void) {
wi.g.width = ScrWidth/2 - 2*border;
ghConsole = gwinConsoleCreate(0, &wi.g);
gwinSetColor(ghConsole, Black);
gwinSetBgColor(ghConsole, 0xF0F0F0);
gwinSetBgColor(ghConsole, HTML2COLOR(0xF0F0F0));
// Buttons
wi.g.parent = ghPgButtons;

View File

@ -15,6 +15,15 @@ FEATURE: Added support for eCos
FEATURE: Added PCF8812 gdisp driver
FEATURE: Added PCD8544 gdisp driver
FEATURE: Added Raspberry Pi board support
FEATURE: Added R61505U gdisp driver
FIX: Fix threading issues in GEvent for callbacks
FEATURE: Added geventEventComplete()
FEATURE: Added support for the RawOS real time operating system
FEATURE: Operating System initialisation is now optional
FEATURE: Added optional transparency to container
FEATURE: Prevent mouse events going to obscured widgets
FEATURE: Add GFILE support for file lists
FEATURE: Add GFILE support for C strings as files
*** Release 2.1 ***

View File

@ -0,0 +1,60 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef GDISP_LLD_BOARD_H
#define GDISP_LLD_BOARD_H
static inline void init_board(GDisplay *g) {
(void) g;
}
static inline void post_init_board(GDisplay *g) {
(void) g;
}
static inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;
(void) state;
}
static inline void set_backlight(GDisplay *g, uint8_t percent) {
(void) g;
(void) percent;
}
static inline void acquire_bus(GDisplay *g) {
(void) g;
}
static inline void release_bus(GDisplay *g) {
(void) g;
}
static inline void write_index(GDisplay *g, uint16_t index) {
(void) g;
(void) index;
}
static inline void write_data(GDisplay *g, uint16_t data) {
(void) g;
(void) data;
}
static inline void setreadmode(GDisplay *g) {
(void) g;
}
static inline void setwritemode(GDisplay *g) {
(void) g;
}
static inline uint16_t read_data(GDisplay *g) {
(void) g;
return 0;
}
#endif /* GDISP_LLD_BOARD_H */

View File

@ -0,0 +1,2 @@
GFXINC += $(GFXLIB)/drivers/gdisp/R61505U
GFXSRC += $(GFXLIB)/drivers/gdisp/R61505U/gdisp_lld_R61505U.c

View File

@ -0,0 +1,385 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GDISP
/* This controller is only ever used with a 240 x 320 display */
#if defined(GDISP_SCREEN_HEIGHT)
#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
#undef GDISP_SCREEN_HEIGHT
#endif
#if defined(GDISP_SCREEN_WIDTH)
#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
#undef GDISP_SCREEN_WIDTH
#endif
#define GDISP_DRIVER_VMT GDISPVMT_R61505U
#include "drivers/gdisp/R61505U/gdisp_lld_config.h"
#include "src/gdisp/driver.h"
#include "board_R61505U.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 320
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 240
#endif
#ifndef GDISP_INITIAL_CONTRAST
#define GDISP_INITIAL_CONTRAST 50
#endif
#ifndef GDISP_INITIAL_BACKLIGHT
#define GDISP_INITIAL_BACKLIGHT 100
#endif
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#define dummy_read(g) { volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
#define write_reg(g, reg, data) { write_index(g, reg); write_data(g, data); }
static void set_cursor(GDisplay *g) {
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
write_reg(g, 0x20, g->p.x);
write_reg(g, 0x21, g->p.y);
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
write_reg(g, 0x20, g->p.y);
write_reg(g, 0x21, g->p.x);
break;
}
write_index(g, 0x22);
}
static void set_viewport(GDisplay *g) {
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
write_reg(g, 0x50, g->p.x);
write_reg(g, 0x51, g->p.x + g->p.cx - 1);
write_reg(g, 0x52, g->p.y);
write_reg(g, 0x53, g->p.y + g->p.cy - 1);
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
write_reg(g, 0x50, g->p.y);
write_reg(g, 0x51, g->p.y + g->p.cy - 1);
write_reg(g, 0x52, g->p.x);
write_reg(g, 0x53, g->p.x + g->p.cx - 1);
break;
}
}
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
uint16_t cver;
// No private area for this controller
g->priv = 0;
// Initialise the board interface
init_board(g);
/* Hardware reset */
setpin_reset(g, TRUE);
gfxSleepMicroseconds(1000);
setpin_reset(g, FALSE);
gfxSleepMicroseconds(1000);
acquire_bus(g);
write_index(g, 0); // Get controller version
setreadmode(g);
dummy_read(g);
cver = read_data(g);
setwritemode(g);
/* initializing funciton */
write_reg(g, 0xe5,0x8000); /* Set the internal vcore voltage */
write_reg(g, 0x00,0x0001); /* start OSC */
write_reg(g, 0x2b,0x0010); /* Set the frame rate as 80 when the internal resistor is used for oscillator circuit */
write_reg(g, 0x01,0x0100); /* s720 to s1 ; G1 to G320 */
write_reg(g, 0x02,0x0700); /* set the line inversion */
write_reg(g, 0x03,0x1018); /* 65536 colors */
write_reg(g, 0x04,0x0000);
write_reg(g, 0x08,0x0202); /* specify the line number of front and back porch periods respectively */
write_reg(g, 0x09,0x0000);
write_reg(g, 0x0a,0x0000);
write_reg(g, 0x0c,0x0000); /* select internal system clock */
write_reg(g, 0x0d,0x0000);
write_reg(g, 0x0f,0x0000);
write_reg(g, 0x50,0x0000); /* set windows adress */
write_reg(g, 0x51,0x00ef);
write_reg(g, 0x52,0x0000);
write_reg(g, 0x53,0x013f);
write_reg(g, 0x60,0x2700);
write_reg(g, 0x61,0x0001);
write_reg(g, 0x6a,0x0000);
write_reg(g, 0x80,0x0000);
write_reg(g, 0x81,0x0000);
write_reg(g, 0x82,0x0000);
write_reg(g, 0x83,0x0000);
write_reg(g, 0x84,0x0000);
write_reg(g, 0x85,0x0000);
write_reg(g, 0x90,0x0010);
write_reg(g, 0x92,0x0000);
write_reg(g, 0x93,0x0003);
write_reg(g, 0x95,0x0110);
write_reg(g, 0x97,0x0000);
write_reg(g, 0x98,0x0000);
/* power setting function */
write_reg(g, 0x10,0x0000);
write_reg(g, 0x11,0x0000);
write_reg(g, 0x12,0x0000);
write_reg(g, 0x13,0x0000);
gfxSleepMicroseconds(100);
write_reg(g, 0x10,0x17b0);
write_reg(g, 0x11,0x0004);
gfxSleepMicroseconds(50);
write_reg(g, 0x12,0x013e);
gfxSleepMicroseconds(50);
write_reg(g, 0x13,0x1f00);
write_reg(g, 0x29,0x000f);
gfxSleepMicroseconds(50);
write_reg(g, 0x20,0x0000);
write_reg(g, 0x21,0x0000);
/* initializing function */
write_reg(g, 0x30,0x0204);
write_reg(g, 0x31,0x0001);
write_reg(g, 0x32,0x0000);
write_reg(g, 0x35,0x0206);
write_reg(g, 0x36,0x0600);
write_reg(g, 0x37,0x0500);
write_reg(g, 0x38,0x0505);
write_reg(g, 0x39,0x0407);
write_reg(g, 0x3c,0x0500);
write_reg(g, 0x3d,0x0503);
/* display on */
write_reg(g, 0x07,0x0173);
gfxSleepMicroseconds(50);
// Finish Init
post_init_board(g);
// Release the bus
release_bus(g);
// Turn on the backlight
set_backlight(g, GDISP_INITIAL_BACKLIGHT);
/* Initialise the GDISP structure */
g->g.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
g->g.Contrast = GDISP_INITIAL_CONTRAST;
return TRUE;
}
#if GDISP_HARDWARE_STREAM_WRITE
LLDSPEC void gdisp_lld_write_start(GDisplay *g) {
acquire_bus(g);
set_viewport(g);
#if !GDISP_HARDWARE_STREAM_POS
set_cursor(g);
#endif
}
LLDSPEC void gdisp_lld_write_color(GDisplay *g) {
write_data(g, gdispColor2Native(g->p.color));
}
LLDSPEC void gdisp_lld_write_stop(GDisplay *g) {
release_bus(g);
}
#if GDISP_HARDWARE_STREAM_POS
LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
set_cursor(g);
}
#endif
#endif
#if GDISP_HARDWARE_STREAM_READ
LLDSPEC void gdisp_lld_read_start(GDisplay *g) {
acquire_bus(g);
set_viewport(g);
set_cursor(g);
setreadmode(g);
dummy_read(g);
}
LLDSPEC color_t gdisp_lld_read_color(GDisplay *g) {
uint16_t data;
data = read_data(g);
return gdispNative2Color(data);
}
LLDSPEC void gdisp_lld_read_stop(GDisplay *g) {
setwritemode(g);
release_bus(g);
}
#endif
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay *g) {
switch(g->p.x) {
case GDISP_CONTROL_POWER:
if (g->g.Powermode == (powermode_t)g->p.ptr)
return;
switch((powermode_t)g->p.ptr) {
case powerOff:
acquire_bus(g);
write_reg(g, 0x07, 0x0000);
write_reg(g, 0x10, 0x0000);
write_reg(g, 0x11, 0x0000);
write_reg(g, 0x12, 0x0000);
write_reg(g, 0x13, 0x0000);
release_bus(g);
set_backlight(g, 0);
break;
case powerOn:
//*************Power On sequence ******************//
acquire_bus(g);
write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
gfxSleepMicroseconds(500);
write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
gfxSleepMicroseconds(500);
write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
gfxSleepMicroseconds(500);
write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
release_bus(g);
set_backlight(g, g->g.Backlight);
break;
case powerSleep:
acquire_bus(g);
write_reg(g, 0x07, 0x0000); /* display OFF */
write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
release_bus(g);
set_backlight(g, 0);
break;
case powerDeepSleep:
acquire_bus(g);
write_reg(g, 0x07, 0x0000); /* display OFF */
write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
release_bus(g);
set_backlight(g, 0);
break;
default:
return;
}
g->g.Powermode = (powermode_t)g->p.ptr;
return;
case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0:
acquire_bus(g);
write_reg(g, 0x01, 0x0100);
write_reg(g, 0x03, 0x1038);
write_reg(g, 0x60, 0x2700);
release_bus(g);
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
break;
case GDISP_ROTATE_90:
acquire_bus(g);
write_reg(g, 0x01, 0x0000);
write_reg(g, 0x03, 0x1030);
write_reg(g, 0x60, 0x2700);
release_bus(g);
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
break;
case GDISP_ROTATE_180:
acquire_bus(g);
write_reg(g, 0x01, 0x0000);
write_reg(g, 0x03, 0x1030);
write_reg(g, 0x60, 0x2700);
release_bus(g);
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
break;
case GDISP_ROTATE_270:
acquire_bus(g);
write_reg(g, 0x01, 0x0100);
write_reg(g, 0x03, 0x1038);
write_reg(g, 0x60, 0xA700);
release_bus(g);
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
break;
default:
return;
}
g->g.Orientation = (orientation_t)g->p.ptr;
return;
case GDISP_CONTROL_BACKLIGHT:
if ((unsigned)g->p.ptr > 100)
g->p.ptr = (void *)100;
set_backlight(g, (unsigned)g->p.ptr);
g->g.Backlight = (unsigned)g->p.ptr;
return;
default:
return;
}
}
#endif
#endif /* GFX_USE_GDISP */

View File

@ -0,0 +1,26 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef GDISP_LLD_CONFIG_H
#define GDISP_LLD_CONFIG_H
#if GFX_USE_GDISP
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
#define GDISP_HARDWARE_STREAM_WRITE TRUE
#define GDISP_HARDWARE_STREAM_READ TRUE
//#define GDISP_HARDWARE_STREAM_POS TRUE
#define GDISP_HARDWARE_CONTROL TRUE
#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
#endif /* GFX_USE_GDISP */
#endif /* _GDISP_LLD_CONFIG_H */

View File

@ -16,6 +16,7 @@
#define CALC_PERIOD(w,b,f,p) (p+b+w+f)
#define CALC_FPR(w,h,hb,hf,hp,vb,vf,vp,fps) ((fps * CALC_PERIOD(w,hb,hf,hp) * CALC_PERIOD(h,vb,vf,vp) * 1048576)/100000000)
typedef struct LCD_Parameters {
coord_t width, height; // Panel width and height
uint16_t hbporch; // Horizontal Back Porch
@ -27,6 +28,26 @@ typedef struct LCD_Parameters {
uint16_t vpulse; // Vertical Pulse
uint16_t vperiod; // Vertical Period (Total)
uint32_t fpr; // Calculated FPR
uint16_t flags; // For command "SSD1963_SET_GDISP_MODE"
/* Set the pannel data width */
#define LCD_PANEL_DATA_WIDTH_24BIT (1<<5) // 18bit default
/* Set the color deeph enhancement */
#define LCD_PANEL_ENABLE_FRC ((1<<3) | (1<<4))
#define LCD_PANEL_ENABLE_DITHERING (1<<4) // no enhancement default
/* Set the dot clock pulse polarity */
#define LCD_PANEL_LSHIFT_FALLING_EDGE (1<<2) // default rising edge
/* Set the horizontal sync pulse polarity */
#define LCD_PANEL_LLINE_ACTIVE_HIGH (1<<1) // default active low
/* Set the vertical sync pulse polarity */
#define LCD_PANEL_LFRAME_ACTIVE_HIGH (1<0) // default active low
/* Set the lcd panel mode */
#define LCD_PANEL_MODE_TTL ((1<<7) << 8) // default mode is Hsync+Vsync +DE
/* Set the lcd panel interface type */ // default TFT mode
#define LCD_PANEL_TYPE_SERIAL_RGB_MODE ((1<<6) << 8) // Serial RGB mode
#define LCD_PANEL_TYPE_SERIAL_RGB_DUMMY_MODE (((1<<5) | (1<<6)) << 8) // Serial RGB+dummy mode
} LCD_Parameters;
#include "board_SSD1963.h"
@ -48,17 +69,55 @@ typedef struct LCD_Parameters {
#include "drivers/gdisp/SSD1963/ssd1963.h"
#define dummy_read(g) { volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
#define write_reg(g, reg, data) { write_index(g, reg); write_data(g, data); }
#define write_data16(g, data) { write_data(g, (data)>>8); write_data(g, (data) & 0xFF); }
static inline void set_viewport(GDisplay* g) {
write_index(g, SSD1963_SET_PAGE_ADDRESS);
write_data16(g, g->p.y);
write_data16(g, g->p.y+g->p.cy-1);
write_index(g, SSD1963_SET_COLUMN_ADDRESS);
write_data16(g, g->p.x);
write_data16(g, g->p.x+g->p.cx-1);
write_index(g, SSD1963_WRITE_MEMORY_START);
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
write_index(g, SSD1963_SET_COLUMN_ADDRESS);
write_data16(g, g->p.x);
write_data16(g, g->p.x+g->p.cx-1);
write_index(g, SSD1963_SET_PAGE_ADDRESS);
write_data16(g, g->p.y);
write_data16(g, g->p.y+g->p.cy-1);
write_index(g, SSD1963_WRITE_MEMORY_START);
break;
case GDISP_ROTATE_90:
write_index(g, SSD1963_SET_COLUMN_ADDRESS);
write_data16(g, g->p.y);
write_data16(g, g->p.y+g->p.cy-1);
write_index(g, SSD1963_SET_PAGE_ADDRESS);
write_data16(g, GDISP_SCREEN_HEIGHT-1 - (g->p.x+g->p.cx-1) );
write_data16(g, GDISP_SCREEN_HEIGHT-1 - (g->p.x));
write_index(g, SSD1963_WRITE_MEMORY_START);
break;
case GDISP_ROTATE_180:
write_index(g, SSD1963_SET_COLUMN_ADDRESS);
write_data16(g, GDISP_SCREEN_WIDTH-1 - (g->p.x+g->p.cx-1));
write_data16(g, GDISP_SCREEN_WIDTH-1 - (g->p.x));
write_index(g, SSD1963_SET_PAGE_ADDRESS);
write_data16(g, GDISP_SCREEN_HEIGHT-1 - (g->p.y+g->p.cy-1));
write_data16(g, GDISP_SCREEN_HEIGHT-1 - (g->p.y));
write_index(g, SSD1963_WRITE_MEMORY_START);
break;
case GDISP_ROTATE_270:
write_index(g, SSD1963_SET_COLUMN_ADDRESS);
write_data16(g, GDISP_SCREEN_WIDTH-1 - (g->p.y+g->p.cy-1));
write_data16(g, GDISP_SCREEN_WIDTH-1 - (g->p.y));
write_index(g, SSD1963_SET_PAGE_ADDRESS);
write_data16(g, g->p.x);
write_data16(g, g->p.x+g->p.cx-1);
write_index(g, SSD1963_WRITE_MEMORY_START);
break;
}
}
/**
@ -71,12 +130,18 @@ static inline void set_backlight(GDisplay *g, uint8_t percent) {
//Check your LCD's hardware, the PWM connection is default left open and instead
//connected to a LED connection on the breakout board
write_index(g, SSD1963_SET_PWM_CONF); //set PWM for BackLight
write_data(g, 0x01);
write_data(g, (55+percent*2) & 0x00FF);
write_data(g, 0x01); //controlled by host (not DBC), enabled
write_data(g, 0xFF);
write_data(g, 0x60); //don't let it go too dark, avoid a useless LCD
write_data(g, 0x0F); //prescaler ???
write_data(g, 4); // PWMF[7:0] = 4,
// PWM signal frequency = PLL clock / (256 * (PWMF[7:0] + 1)) / 256
// = aprox 366Hz for a PLL freq = 120MHz
if ( percent==0xFF ) // use percent==0xFF to turn off SSD1963 pwm in power SLEEP or DEEP SLEEP mode
write_data(g, 0x00);
else
write_data(g, (55+percent*2) & 0x00FF);
write_data(g, 0x01); // controlled by host (not DBC), enabled
write_data(g, 0x00); // DBC manual brightness; Set the brightness level: 00 Dimmest, FF Brightest
write_data(g, 0x00); // DBC minimum brightness; Set the minimum brightness level: 00 Dimmest, FF Brightest
write_data(g, 0x00); // Brightness prescaler of Transition Effect; Set the brightness prescaler: 0 Dimmest, F Brightest
}
/*===========================================================================*/
@ -121,10 +186,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
write_index(g, SSD1963_SOFT_RESET);
gfxSleepMilliseconds(5);
/* Screen size */
/* LCD panel parameters */
write_index(g, SSD1963_SET_GDISP_MODE);
write_data(g, 0x18); //Enabled dithering
write_data(g, 0x00);
write_data(g, lcdp->flags & 0xFF);
write_data(g, (lcdp->flags >> 8) & 0xFF);
write_data16(g, lcdp->width-1);
write_data16(g, lcdp->height-1);
write_data(g, 0x00); // RGB
@ -155,9 +220,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) */
write_reg(g, SSD1963_SET_TEAR_ON, 0x00);
/* Turn on */
write_index(g, SSD1963_SET_DISPLAY_ON);
/* Turn on the back-light */
set_backlight(g, GDISP_INITIAL_BACKLIGHT);
@ -190,8 +256,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
}
#endif
// Not implemented yet.
#if 0 && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay *g) {
switch(g->p.x) {
case GDISP_CONTROL_POWER:
@ -200,23 +265,34 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
switch((powermode_t)g->p.ptr) {
case powerOff:
acquire_bus(g);
write_index(g, SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
gfxSleepMilliseconds(5);
write_index(g, SSD1963_SET_DISPLAY_OFF);
write_index(g, SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
release_bus(g);
break;
case powerOn:
acquire_bus(g);
read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep
read_reg(0x0000); gfxSleepMilliseconds(5);
write_index(g, SSD1963_SET_DISPLAY_ON);
dummy_read(g);
dummy_read(g);
/* Wait for 1msec to let the PLL stable if was stopped by deep sleep mode */
gfxSleepMilliseconds(100);
write_index(g, SSD1963_EXIT_SLEEP_MODE);
gfxSleepMilliseconds(5);
/* Restore the back-light */
set_backlight(g, gdispGGetBacklight(g));
release_bus(g);
break;
case powerSleep:
acquire_bus(g);
write_index(g, SSD1963_SET_DISPLAY_OFF);
write_index(g, SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
/* Turn off the back-light pwm from SSD1963 */
set_backlight(g, 0xFF);
write_index(g, SSD1963_ENTER_SLEEP_MODE);
gfxSleepMilliseconds(5);
release_bus(g);
break;
case powerDeepSleep:
acquire_bus(g);
/* Turn off the back-light pwm from SSD1963 */
set_backlight(g, 0xFF);
write_index(g, SSD1963_ENTER_SLEEP_MODE);
write_index(g, SSD1963_SET_DEEP_SLEEP);
release_bus(g);
break;
default:
@ -228,30 +304,35 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0:
acquire_bus(g);
/* Code here */
write_index(g, SSD1963_SET_ADDRESS_MODE);
write_data(g, 0x00);
release_bus(g);
g->g.Height = ((LCD_Parameters *)g->priv)->height;
g->g.Width = ((LCD_Parameters *)g->priv)->width;
break;
case GDISP_ROTATE_90:
acquire_bus(g);
/* Code here */
write_index(g, SSD1963_SET_ADDRESS_MODE);
write_data(g, SSD1963_ADDR_MODE_PAGE_ADDR_ORDER | SSD1963_ADDR_MODE_PAG_COL_ADDR_ORDER );
release_bus(g);
g->g.Height = ((LCD_Parameters *)g->priv)->width;
g->g.Width = ((LCD_Parameters *)g->priv)->height;
break;
case GDISP_ROTATE_180:
acquire_bus(g);
/* Code here */
write_index(g, SSD1963_SET_ADDRESS_MODE);
write_data(g, SSD1963_ADDR_MODE_PAGE_ADDR_ORDER | SSD1963_ADDR_MODE_COL_ADDR_ORDER);
release_bus(g);
g->g.Height = ((LCD_Parameters *)g->priv)->height;
g->g.Width = ((LCD_Parameters *)g->priv)->width;
break;
case GDISP_ROTATE_270:
acquire_bus(g);
/* Code here */
write_index(g, SSD1963_SET_ADDRESS_MODE);
write_data(g, SSD1963_ADDR_MODE_COL_ADDR_ORDER | SSD1963_ADDR_MODE_PAG_COL_ADDR_ORDER );
release_bus(g);
g->g.Height = ((LCD_Parameters *)g->priv)->width;
g->g.Width = ((LCD_Parameters *)g->priv)->height;
@ -259,7 +340,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
default:
return;
}
g->g.Orientation = (orientation_t)g->p.ptr;
g->g.Orientation = (orientation_t)g->p.ptr;
return;
case GDISP_CONTROL_BACKLIGHT:

View File

@ -15,7 +15,7 @@
/*===========================================================================*/
#define GDISP_HARDWARE_STREAM_WRITE TRUE
//#define GDISP_HARDWARE_CONTROL TRUE // Not Yet.
#define GDISP_HARDWARE_CONTROL TRUE
#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565

View File

@ -93,4 +93,13 @@
#define SSD1963_PDI_9BIT 6
#define SSD1963_GET_PIXEL_DATA_INTERFACE 0x00F1
#define SSD1963_ADDR_MODE_FLIP_VERT (1 << 0)
#define SSD1963_ADDR_MODE_FLIP_HORZ (1 << 1)
#define SSD1963_ADDR_MODE_LATCH_RIGHT_TO_LEFT (1 << 2)
#define SSD1963_ADDR_MODE_BGR (1 << 3)
#define SSD1963_ADDR_MODE_REFRESH_BOTTOM_UP (1 << 4)
#define SSD1963_ADDR_MODE_PAG_COL_ADDR_ORDER (1 << 5)
#define SSD1963_ADDR_MODE_COL_ADDR_ORDER (1 << 6)
#define SSD1963_ADDR_MODE_PAGE_ADDR_ORDER (1 << 7)
#endif

View File

@ -16,7 +16,14 @@ optionally a touchscreen driver, and optionally a toggle driver.
2. To your makefile add the following lines:
include $(GFXLIB)/gfx.mk
include $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.mk
include $(GFXLIB)/drivers/multiple/Win32/driver.mk
However, consider using the Win32 board file instead as this does include all
the possible drivers that can be used (eg. for the GAUDIO module) by using:
include $(GFXLIB)/gfx.mk
include $(GFXLIB)/boards/base/Win32/board.mk
3. Modify your makefile to add -lws2_32 and -lgdi32 to the DLIBS line. i.e.
DLIBS = -lws2_32 -lgdi32

View File

@ -38,6 +38,9 @@
// #define INTERRUPTS_OFF() optional_code
// #define INTERRUPTS_ON() optional_code
// Options that (should where relevant) apply to all operating systems
// #define GFX_NO_OS_INIT FALSE
///////////////////////////////////////////////////////////////////////////
// GDISP //
@ -166,6 +169,7 @@
// #define GWIN_NEED_PROGRESSBAR FALSE
// #define GWIN_PROGRESSBAR_AUTO FALSE
// #define GWIN_FLAT_STYLING FALSE
// #define GWIN_WIDGET_TAGS FALSE
//#define GWIN_NEED_CONTAINERS FALSE
// #define GWIN_NEED_CONTAINER FALSE
@ -220,10 +224,8 @@
//#define GFILE_NEED_PRINTG FALSE
//#define GFILE_NEED_SCANG FALSE
//#define GFILE_NEED_STRINGS FALSE
//#define GFILE_NEED_FILELISTS FALSE
//#define GFILE_NEED_STDIO FALSE
// #define GFILE_ALLOW_FLOATS FALSE
// #define GFILE_ALLOW_DEVICESPECIFIC FALSE
// #define GFILE_MAX_GFILES 3
//#define GFILE_NEED_NOAUTOMOUNT FALSE
//#define GFILE_NEED_NOAUTOSYNC FALSE
@ -234,6 +236,9 @@
//#define GFILE_NEED_NATIVEFS FALSE
//#define GFILE_NEED_CHBIOSFS FALSE
//#define GFILE_ALLOW_FLOATS FALSE
//#define GFILE_ALLOW_DEVICESPECIFIC FALSE
//#define GFILE_MAX_GFILES 3
///////////////////////////////////////////////////////////////////////////
// GADC //

View File

@ -2,7 +2,7 @@
<!-- saved from url=(0028)http://ugfx.org/license.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>GFX License, version 1.1</title>
<title>GFX License, version 1.2</title>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
@ -67,7 +67,7 @@
</style>
<style type="text/css"></style></head>
<body>
<h1>GFX License<br>Version 1.1</h1>
<h1>GFX License<br>Version 1.2</h1>
<h2>1. Definitions</h2>
<dl>
<dt>1.1. Works</dt>
@ -100,7 +100,7 @@
<dt>1.12. Commercial Use</dt>
<dd><p>means any use of the Works that may result in income or equivalent benefit in any form. Examples of Commercial Use include; selling an Application or Device containing the Works,
offering paid support to modify the Works, selling a library containing the Works. Examples of use that are NOT Commercial Use include; using the Works for Education, use of the Works in hobbyist projects that have no expectation of income, use of the Works in building what will later become a Commercial Use product.
Note that Commercial Use does not the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
Note that Commercial Use does not include the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
</dl>
<h2>2. Non Commercial Use</h2>
@ -116,7 +116,7 @@
<h3>2.2. Distribution of Executable form</h3>
<p>If You distribute the Works in an Executable form then:</p>
<ol type="a">
<li><p>and You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
<li><p>You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
<li><p>Any modification to the Works must be contributed to the License Owners as per Section 4 prior to distribution; and</p></li>
<li><p>You may distribute such Executable form under the terms of this License, or license it under different terms, provided that the license for the Executable form does not allow for Commercial Use of the Works or attempt to limit or alter the recipients' rights in the Source Code Form under this License.</p></li>
</ol>
@ -125,7 +125,7 @@
<h3>3.1. Commercial Use Agreement</h3>
<p>A "Commercial Use Agreement" explicitly signed by the License Owner will override any specified terms of this License for the party to the agreement under the terms of the agreement. All other terms of this License will still apply.</p>
<h3>3.2. Distribution</h3>
<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied; you are not permitted to distribute the Works, in any form, either in source code or Executable form,
<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied, you are not permitted to distribute the Works in any form, either in source code or Executable form,
either as software or on a device or in any other way.</p>
<h2>4. Contributions</h2>
@ -177,7 +177,8 @@
<p>You may distribute the Works under the terms of the version of the License under which You originally received the Works, or under the terms of any subsequent version published by the license steward.</p>
<h3>12.3. Modified Versions</h3>
<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the License Owner (except to note that such modified license differs from this License).</p>
<h3>13. Source Code License Notice</h3>
<p>Where ever possible the source code for the Works is to contain a header as per Exhibit A. Where this would be syntactically incorrect then modifications to allow syntactic parsing by a compiler are allowed but only to the extent that they allow correct syntactic parsing. If it is not possible to put the notice in a particular file, then You may include the notice in a location where a recipient would be likely to look for such a notice such as a “license.txt” file in a relevant directory.</p>
<h2>Exhibit A - Source Code Form License Notice</h2>
<pre>/*
* This file is subject to the terms of the GFX License. If a copy of
@ -186,7 +187,5 @@
* http://ugfx.com/license.html
*/
</pre>
<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>
</body></html>

View File

@ -21,7 +21,11 @@
#if 1
#undef INLINE
#define INLINE inline
#if defined(__KEIL__) || defined(__C51__)
#define INLINE __inline
#else
#define INLINE inline
#endif
#else
#undef INLINE
#define INLINE

View File

@ -90,7 +90,7 @@ gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
return GDISP_IMAGE_ERR_OK;
}
gdispImageError gdispImageGDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
coord_t mx, mcx;
size_t pos, len;

View File

@ -22,26 +22,40 @@
#define GEVENT_ASSERT(x)
#endif
/* Flags in the listener structure */
#define GLISTENER_EVENTBUSY 0x0001 // The event buffer is busy
#define GLISTENER_WAITING 0x0002 // The listener is waiting for a signal
#define GLISTENER_WITHSOURCE 0x0004 // The listener is being looked at by a source for a possible event
/* This mutex protects access to our tables */
static gfxMutex geventMutex;
/* Our table of listener/source pairs */
static GSourceListener Assignments[GEVENT_MAX_SOURCE_LISTENERS];
/* Send an exit event if possible. */
/* We already have the geventMutex */
static void doExitEvent(GListener *pl) {
// Don't do the exit if someone else currently has the event lock
if ((pl->flags & (GLISTENER_WAITING|GLISTENER_EVENTBUSY)) == GLISTENER_WAITING) {
pl->flags |= GLISTENER_EVENTBUSY; // Event buffer is in use
pl->event.type = GEVENT_EXIT; // Set up the EXIT event
pl->flags &= ~GLISTENER_WAITING; // Wake up the listener (with data)
gfxSemSignal(&pl->waitqueue);
}
}
/* Loop through the assignment table deleting this listener/source pair. */
/* Null is treated as a wildcard. */
/* We already have the geventMutex */
static void deleteAssignments(GListener *pl, GSourceHandle gsh) {
GSourceListener *psl;
for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
if ((!pl || psl->pListener == pl) && (!gsh || psl->pSource == gsh)) {
if (gfxSemCounter(&psl->pListener->waitqueue) < 0) {
gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE); // Obtain the buffer lock
psl->pListener->event.type = GEVENT_EXIT; // Set up the EXIT event
gfxSemSignal(&psl->pListener->waitqueue); // Wake up the listener
gfxSemSignal(&psl->pListener->eventlock); // Release the buffer lock
}
doExitEvent(psl->pListener);
psl->pListener = 0;
psl->pSource = 0;
}
}
}
@ -58,9 +72,9 @@ void _geventDeinit(void)
void geventListenerInit(GListener *pl) {
gfxSemInit(&pl->waitqueue, 0, MAX_SEMAPHORE_COUNT); // Next wait'er will block
gfxSemInit(&pl->eventlock, 1, 1); // Only one thread at a time looking at the event buffer
pl->callback = 0; // No callback active
pl->event.type = GEVENT_NULL; // Always safety
pl->flags = 0;
}
bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) {
@ -80,9 +94,7 @@ bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) {
if (pl == psl->pListener && gsh == psl->pSource) {
// Just update the flags
gfxSemWait(&pl->eventlock, TIME_INFINITE); // Safety first - just in case a source is using it
psl->listenflags = flags;
gfxSemSignal(&pl->eventlock); // Release this lock
gfxMutexExit(&geventMutex);
return TRUE;
}
@ -106,33 +118,37 @@ void geventDetachSource(GListener *pl, GSourceHandle gsh) {
if (pl) {
gfxMutexEnter(&geventMutex);
deleteAssignments(pl, gsh);
if (!gsh && gfxSemCounter(&pl->waitqueue) < 0) {
gfxSemWait(&pl->eventlock, TIME_INFINITE); // Obtain the buffer lock
pl->event.type = GEVENT_EXIT; // Set up the EXIT event
gfxSemSignal(&pl->waitqueue); // Wake up the listener
gfxSemSignal(&pl->eventlock); // Release the buffer lock
}
if (!gsh)
doExitEvent(pl);
gfxMutexExit(&geventMutex);
}
}
GEvent *geventEventWait(GListener *pl, delaytime_t timeout) {
if (pl->callback || gfxSemCounter(&pl->waitqueue) < 0)
gfxMutexEnter(&geventMutex);
// Don't allow waiting if we are on callbacks or if there is already a thread waiting
if (pl->callback || (pl->flags & GLISTENER_WAITING)) {
gfxMutexExit(&geventMutex);
return 0;
}
pl->flags &= ~GLISTENER_EVENTBUSY; // Event buffer is definitely not busy
pl->flags |= GLISTENER_WAITING; // We will now be waiting on the thread
gfxMutexExit(&geventMutex);
return gfxSemWait(&pl->waitqueue, timeout) ? &pl->event : 0;
}
void geventEventComplete(GListener *pl) {
pl->flags &= ~GLISTENER_EVENTBUSY;
}
void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) {
if (pl) {
gfxMutexEnter(&geventMutex);
gfxSemWait(&pl->eventlock, TIME_INFINITE); // Obtain the buffer lock
pl->param = param; // Set the param
pl->callback = fn; // Set the callback function
if (gfxSemCounter(&pl->waitqueue) < 0) {
pl->event.type = GEVENT_EXIT; // Set up the EXIT event
gfxSemSignal(&pl->waitqueue); // Wake up the listener
}
gfxSemSignal(&pl->eventlock); // Release the buffer lock
doExitEvent(pl);
pl->param = param; // Set the param
pl->callback = fn; // Set the callback function
if (fn)
pl->flags &= ~GLISTENER_EVENTBUSY; // The event buffer is immediately available
gfxMutexExit(&geventMutex);
}
}
@ -146,14 +162,13 @@ GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *las
gfxMutexEnter(&geventMutex);
// Unlock the last listener event buffer
if (lastlr)
gfxSemSignal(&lastlr->pListener->eventlock);
// Unlock the last listener event buffer if it wasn't used.
if (lastlr && lastlr->pListener && (lastlr->pListener->flags & GLISTENER_WITHSOURCE))
lastlr->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY);
// Loop through the table looking for attachments to this source
for(psl = lastlr ? (lastlr+1) : Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
if (gsh == psl->pSource) {
gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE); // Obtain a lock on the listener event buffer
gfxMutexExit(&geventMutex);
return psl;
}
@ -163,21 +178,38 @@ GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *las
}
GEvent *geventGetEventBuffer(GSourceListener *psl) {
// We already know we have the event lock
return &psl->pListener->callback || gfxSemCounter(&psl->pListener->waitqueue) < 0 ? &psl->pListener->event : 0;
gfxMutexEnter(&geventMutex);
if ((psl->pListener->flags & GLISTENER_EVENTBUSY)) {
// Oops - event buffer is still in use
gfxMutexExit(&geventMutex);
return 0;
}
// Allocate the event buffer
psl->pListener->flags |= (GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY);
gfxMutexExit(&geventMutex);
return &psl->pListener->event;
}
void geventSendEvent(GSourceListener *psl) {
gfxMutexEnter(&geventMutex);
if (psl->pListener->callback) { // This test needs to be taken inside the mutex
if (psl->pListener->callback) {
// Mark it back as free and as sent. This is early to be marking as free but it protects
// if the callback alters the listener in any way
psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY);
gfxMutexExit(&geventMutex);
// We already know we have the event lock
// Do the callback
psl->pListener->callback(psl->pListener->param, &psl->pListener->event);
} else {
// Wake up the listener
if (gfxSemCounter(&psl->pListener->waitqueue) <= 0)
if ((psl->pListener->flags & GLISTENER_WAITING)) {
psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_WAITING);
gfxSemSignal(&psl->pListener->waitqueue);
// The listener thread will free the event buffer when ready
}
gfxMutexExit(&geventMutex);
}
}

View File

@ -56,7 +56,7 @@ typedef void (*GEventCallbackFn)(void *param, GEvent *pe);
// The Listener Object
typedef struct GListener {
gfxSem waitqueue; // Private: Semaphore for the listener to wait on.
gfxSem eventlock; // Private: Protect against more than one sources trying to use this event lock at the same time
uint16_t flags; // Private: Flags for operation
GEventCallbackFn callback; // Private: Call back Function
void *param; // Private: Parameter for the callback function.
GEvent event; // Public: The event object into which the event information is stored.
@ -149,9 +149,11 @@ void geventDetachSource(GListener *pl, GSourceHandle gsh);
* timeout specifies the time to wait in system ticks.
* TIME_INFINITE means no timeout - wait forever for an event.
* TIME_IMMEDIATE means return immediately
* @note The GEvent buffer is staticly allocated within the GListener so the event does not
* need to be dynamicly freed however it will get overwritten by the next call to
* this routine.
* @note The returned GEvent is released when this routine is called again
* or when optionally @p geventEventComplete() is called. Calling @p geventEventComplete()
* allows the GEvent object to be reused earlier which can reduce missed events. The GEvent
* object MUST NOT be used after this function is called (and is blocked waiting for the next
* event) or after geventEventComplete() is called.
*
* @param[in] pl The listener
* @param[in] timeout The timeout
@ -160,6 +162,17 @@ void geventDetachSource(GListener *pl, GSourceHandle gsh);
*/
GEvent *geventEventWait(GListener *pl, delaytime_t timeout);
/**
* @brief Release the GEvent buffer associated with a listener.
* @details The GEvent returned by @p geventEventWait() is released.
* @note The GEvent pointer returned by @p geventEventWait() is released when @p geventEventWait()
* is called again or when this function is called. The GEvent
* object MUST NOT be used after this function is called.
*
* @param[in] pl The listener
*/
void geventEventComplete(GListener *pl);
/* @brief Register a callback for an event on a listener from an assigned source.
* @details The type of the event should be checked (pevent->type) and then pevent should be typecast to the
* actual event type if it needs to be processed.

View File

@ -35,6 +35,11 @@ struct GFILE {
long int pos;
};
struct gfileList {
const struct GFILEVMT * vmt;
bool_t dirs;
};
typedef struct GFILEVMT {
const struct GFILEVMT * next;
uint8_t flags;
@ -59,6 +64,11 @@ typedef struct GFILEVMT {
bool_t (*mount) (const char *drive);
bool_t (*unmount) (const char *drive);
bool_t (*sync) (GFILE *f);
#if GFILE_NEED_FILELISTS
gfileList * (*flopen) (const char *path, bool_t dirs);
const char *(*flread) (gfileList *pfl);
void (*flclose) (gfileList *pfl);
#endif
} GFILEVMT;
// The chain of FileSystems
@ -70,6 +80,9 @@ GFILE *gfileStdIn;
GFILE *gfileStdOut;
GFILE *gfileStdErr;
// Forward definition used by some special open calls
static GFILE *findemptyfile(const char *mode);
/**
* The order of the file-systems below determines the order
* that they are searched to find a file.
@ -118,6 +131,34 @@ GFILE *gfileStdErr;
#include "src/gfile/inc_romfs.c"
#endif
/********************************************************
* The virtual string file VMT
********************************************************/
#if GFILE_NEED_STRINGS
#include "src/gfile/inc_strings.c"
#endif
/********************************************************
* Printg Routines
********************************************************/
#if GFILE_NEED_PRINTG
#include "src/gfile/inc_printg.c"
#endif
/********************************************************
* Scang Routines
********************************************************/
#if GFILE_NEED_SCANG
#include "src/gfile/inc_scang.c"
#endif
/********************************************************
* Stdio Emulation Routines
********************************************************/
#if GFILE_NEED_STDIO
#include "src/gfile/inc_stdio.c"
#endif
/********************************************************
* IO routines
********************************************************/
@ -251,39 +292,48 @@ bool_t gfileRename(const char *oldname, const char *newname) {
return FALSE;
}
static uint16_t mode2flags(const char *mode) {
uint16_t flags;
static GFILE *findemptyfile(const char *mode) {
GFILE * f;
switch(mode[0]) {
case 'r':
flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST;
while (*++mode) {
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Get the flags
switch(mode[0]) {
case '+': flags |= GFILEFLG_WRITE; break;
case 'b': flags |= GFILEFLG_BINARY; break;
case 'r':
f->flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST;
while (*++mode) {
switch(mode[0]) {
case '+': f->flags |= GFILEFLG_WRITE; break;
case 'b': f->flags |= GFILEFLG_BINARY; break;
}
}
break;
case 'w':
f->flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
while (*++mode) {
switch(mode[0]) {
case '+': f->flags |= GFILEFLG_READ; break;
case 'b': f->flags |= GFILEFLG_BINARY; break;
case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
break;
case 'a':
f->flags = GFILEFLG_WRITE|GFILEFLG_APPEND;
while (*++mode) {
switch(mode[0]) {
case '+': f->flags |= GFILEFLG_READ; break;
case 'b': f->flags |= GFILEFLG_BINARY; break;
case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
break;
default:
return 0;
}
return f;
}
return flags;
case 'w':
flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
while (*++mode) {
switch(mode[0]) {
case '+': flags |= GFILEFLG_READ; break;
case 'b': flags |= GFILEFLG_BINARY; break;
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
return flags;
case 'a':
flags = GFILEFLG_WRITE|GFILEFLG_APPEND;
while (*++mode) {
switch(mode[0]) {
case '+': flags |= GFILEFLG_READ; break;
case 'b': flags |= GFILEFLG_BINARY; break;
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
return flags;
}
return 0;
}
@ -307,112 +357,34 @@ static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) {
}
GFILE *gfileOpen(const char *fname, const char *mode) {
uint16_t flags;
GFILE * f;
const GFILEVMT *p;
// Get the requested mode
if (!(flags = mode2flags(mode)))
// Get an empty file and set the flags
if (!(f = findemptyfile(mode)))
return 0;
#if GFILE_ALLOW_DEVICESPECIFIC
if (fname[0] && fname[1] == '|') {
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Try to open the file
f->flags = flags;
for(p = FsChain; p; p = p->next) {
if (p->prefix == fname[0])
return testopen(p, f, fname+2) ? f : 0;
}
// File not found
break;
}
for(p = FsChain; p; p = p->next) {
if (p->prefix == fname[0])
return testopen(p, f, fname+2) ? f : 0;
}
// No available slot
// File not found
return 0;
}
#endif
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Try to open the file
f->flags = flags;
for(p = FsChain; p; p = p->next) {
if (testopen(p, f, fname))
return f;
}
// File not found
break;
}
for(p = FsChain; p; p = p->next) {
if (testopen(p, f, fname))
return f;
}
// No available slot
// File not found
return 0;
}
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
GFILE * gfileOpenBaseFileStream(void *BaseFileStreamPtr, const char *mode) {
GFILE * f;
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Get the flags
if (!(f->flags = mode2flags(mode)))
return 0;
// If we want write but the fs doesn't allow it then return
if ((f->flags & GFILEFLG_WRITE) && !(FsCHIBIOSVMT.flags & GFSFLG_WRITEABLE))
return 0;
// File is open - fill in all the details
f->vmt = &FsCHIBIOSVMT;
f->obj = BaseFileStreamPtr;
f->pos = 0;
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
return f;
}
}
// No available slot
return 0;
}
#endif
#if GFILE_NEED_MEMFS
GFILE * gfileOpenMemory(void *memptr, const char *mode) {
GFILE * f;
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Get the flags
if (!(f->flags = mode2flags(mode)))
return 0;
// If we want write but the fs doesn't allow it then return
if ((f->flags & GFILEFLG_WRITE) && !(FsMemVMT.flags & GFSFLG_WRITEABLE))
return 0;
// File is open - fill in all the details
f->vmt = &FsMemVMT;
f->obj = memptr;
f->pos = 0;
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
return f;
}
}
// No available slot
return 0;
}
#endif
void gfileClose(GFILE *f) {
if (!f || !(f->flags & GFILEFLG_OPEN))
return;
@ -512,579 +484,35 @@ bool_t gfileSync(GFILE *f) {
return f->vmt->sync(f);
}
/********************************************************
* String VMT routines
********************************************************/
#if GFILE_NEED_STRINGS && (GFILE_NEED_PRINTG || GFILE_NEED_SCANG)
#include <string.h>
#if GFILE_NEED_FILELISTS
gfileList *gfileOpenFileList(char fs, const char *path, bool_t dirs) {
const GFILEVMT *p;
gfileList * pfl;
// Special String VMT
static int StringRead(GFILE *f, void *buf, int size) {
(void) size;
// size must be 1 for a complete read
if (!((char *)f->obj)[f->pos])
return 0;
((char *)buf)[0] = ((char *)f->obj)[f->pos];
return 1;
}
static int StringWrite(GFILE *f, const void *buf, int size) {
(void) size;
// size must be 1 for a complete write
((char *)f->obj)[f->pos] = ((char *)buf)[0];
return 1;
}
static const GFILEVMT StringVMT = {
0, // next
0, // flags
'_', // prefix
0, 0, 0, 0,
0, 0, StringRead, StringWrite,
0, 0, 0,
0, 0
};
#endif
/********************************************************
* printg routines
********************************************************/
#if GFILE_NEED_PRINTG
#include <stdarg.h>
#define MAX_FILLER 11
#define FLOAT_PRECISION 100000
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...) {
int res;
va_list ap;
va_start(ap, fmt);
res = vfnprintg(f, maxlen, fmt, ap);
va_end(ap);
return res;
}
static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) {
int i;
char * q;
if (!divisor) divisor = num;
q = p + MAX_FILLER;
do {
i = (int)(num % radix);
i += '0';
if (i > '9')
i += 'A' - '0' - 10;
*--q = i;
num /= radix;
} while ((divisor /= radix) != 0);
i = (int)(p + MAX_FILLER - q);
do {
*p++ = *q++;
} while (--i);
return p;
}
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg) {
int ret;
char *p, *s, c, filler;
int i, precision, width;
bool_t is_long, left_align;
long l;
#if GFILE_ALLOW_FLOATS
float f;
char tmpbuf[2*MAX_FILLER + 1];
#else
char tmpbuf[MAX_FILLER + 1];
#endif
ret = 0;
if (maxlen < 0)
return 0;
if (!maxlen)
maxlen = -1;
while (*fmt) {
if (*fmt != '%') {
gfileWrite(f, fmt, 1);
ret++; if (!--maxlen) return ret;
fmt++;
continue;
}
fmt++;
p = s = tmpbuf;
left_align = FALSE;
filler = ' ';
width = 0;
precision = 0;
if (*fmt == '-') {
fmt++;
left_align = TRUE;
}
if (*fmt == '.') {
fmt++;
filler = '0';
}
while (1) {
c = *fmt++;
if (c >= '0' && c <= '9') {
c -= '0';
width = width * 10 + c;
} else if (c == '*')
width = va_arg(arg, int);
else
break;
}
if (c == '.') {
while (1) {
c = *fmt++;
if (c >= '0' && c <= '9') {
c -= '0';
precision = precision * 10 + c;
} else if (c == '*')
precision = va_arg(arg, int);
else
break;
}
}
/* Long modifier.*/
if (c == 'l' || c == 'L') {
is_long = TRUE;
if (*fmt)
c = *fmt++;
}
else
is_long = (c >= 'A') && (c <= 'Z');
/* Command decoding.*/
switch (c) {
case 0:
return ret;
case 'c':
filler = ' ';
*p++ = va_arg(arg, int);
break;
case 's':
filler = ' ';
if ((s = va_arg(arg, char *)) == 0)
s = "(null)";
if (precision == 0)
precision = 32767;
for (p = s; *p && (--precision >= 0); p++);
break;
case 'D':
case 'd':
if (is_long)
l = va_arg(arg, long);
else
l = va_arg(arg, int);
if (l < 0) {
*p++ = '-';
l = -l;
}
p = ltoa_wd(p, l, 10, 0);
break;
#if GFILE_ALLOW_FLOATS
case 'f':
f = (float) va_arg(arg, double);
if (f < 0) {
*p++ = '-';
f = -f;
}
l = f;
p = ltoa_wd(p, l, 10, 0);
*p++ = '.';
l = (f - l) * FLOAT_PRECISION;
p = ltoa_wd(p, l, 10, FLOAT_PRECISION / 10);
break;
#endif
case 'X':
case 'x':
c = 16;
goto unsigned_common;
case 'U':
case 'u':
c = 10;
goto unsigned_common;
case 'O':
case 'o':
c = 8;
unsigned_common:
if (is_long)
l = va_arg(arg, long);
else
l = va_arg(arg, int);
p = ltoa_wd(p, l, c, 0);
break;
default:
*p++ = c;
break;
}
i = (int)(p - s);
if ((width -= i) < 0)
width = 0;
if (left_align == FALSE)
width = -width;
if (width < 0) {
if (*s == '-' && filler == '0') {
gfileWrite(f, s++, 1);
ret++; if (!--maxlen) return ret;
i--;
}
do {
gfileWrite(f, &filler, 1);
ret++; if (!--maxlen) return ret;
} while (++width != 0);
}
while (--i >= 0) {
gfileWrite(f, s++, 1);
ret++; if (!--maxlen) return ret;
}
while (width) {
gfileWrite(f, &filler, 1);
ret++; if (!--maxlen) return ret;
width--;
}
}
return ret;
}
#if GFILE_NEED_STRINGS
int snprintg(char *buf, int maxlen, const char *fmt, ...) {
int res;
GFILE f;
va_list ap;
if (maxlen <= 1) {
if (maxlen == 1) {
*buf = 0;
// Find the correct VMT
for(p = FsChain; p; p = p->next) {
if (p->prefix == fs) {
if (!p->flopen)
return 0;
pfl = p->flopen(path, dirs);
if (pfl) {
pfl->vmt = p;
pfl->dirs = dirs;
}
maxlen += 1;
}
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
f.vmt = &StringVMT;
f.pos = 0;
f.obj = buf;
va_start(ap, fmt);
res = vfnprintg(&f, maxlen-1, fmt, ap);
va_end(ap);
buf[res] = 0;
return res;
}
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg) {
int res;
GFILE f;
if (maxlen <= 1) {
if (maxlen == 1) {
*buf = 0;
return 0;
}
maxlen += 1;
}
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
f.vmt = &StringVMT;
f.pos = 0;
f.obj = buf;
res = vfnprintg(&f, maxlen-1, fmt, arg);
buf[res] = 0;
return res;
}
#endif
#endif
/********************************************************
* scang routines
********************************************************/
#if GFILE_NEED_SCANG
int fscang(GFILE *f, const char *fmt, ...) {
int res;
va_list ap;
va_start(ap, fmt);
res = vfscang(f, fmt, ap);
va_end(ap);
return res;
}
int vfscang(GFILE *f, const char *fmt, va_list arg) {
int res, width, size, base;
unsigned long num;
char c;
bool_t assign, negate;
char *p;
for(res = 0; *fmt; fmt++) {
switch(*fmt) {
case ' ': case '\t': case '\r': case '\n': case '\v': case '\f':
break;
case '%':
fmt++;
assign = TRUE;
negate = FALSE;
width = 0;
size = 1;
num = 0;
if (*fmt == '*') {
fmt++;
assign = FALSE;
}
while(*fmt >= '0' && *fmt <= '9')
width = width * 10 + (*fmt++ - '0');
if (*fmt == 'h') {
fmt++;
size = 0;
} else if (*fmt == 'l') {
fmt++;
size = 2;
} else if (*fmt == 'L') {
fmt++;
size = 3;
}
switch(*fmt) {
case 0:
return res;
case '%':
goto matchchar;
case 'c':
if (!width) {
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
width = 1;
} else {
if (!gfileRead(f, &c, 1)) return res;
}
if (assign) {
p = va_arg(arg, char *);
res++;
*p++ = c;
}
while(--width) {
if (!gfileRead(f, &c, 1)) return res;
if (assign) *p++ = c;
}
break;
case 's':
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (assign) {
p = va_arg(arg, char *);
res++;
*p++ = c;
}
if (width) {
while(--width) {
if (!gfileRead(f, &c, 1)) {
if (assign) *((char *)p) = 0;
return res;
}
if (assign) *p++ = c;
}
} else {
while(1) {
if (!gfileRead(f, &c, 1)) {
if (assign) *((char *)p) = 0;
return res;
}
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': break;
default:
if (assign) *p++ = c;
continue;
}
break;
}
//ungetch(c);
}
if (assign) *p = 0;
break;
case 'd': base = 10; goto getnum;
case 'i': base = -1; goto getnum;
case 'o': base = 8; goto getnum;
case 'u': base = 10; goto getnum;
case 'x': base = 16; goto getnum;
case 'b': base = 2;
getnum:
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (c == '-' && *fmt != 'u') {
negate = TRUE;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
}
if (base == -1) {
if (c == '0') {
if ((width && !--width) || !gfileRead(f, &c, 1)) goto assignnum;
switch(c) {
case 'x': case 'X':
base = 16;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
break;
case 'b': case 'B':
base = 2;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
break;
default:
base = 8;
break;
}
} else
base = 10;
}
while(1) {
if (c >= '0' && c <= '9' && c - '0' < base)
num = num * base + (c - '0');
else if (c >= 'A' && c <= 'F' && base == 16)
num = num * base + (c - ('A'-10));
else if (c >= 'a' && c <= 'f' && base == 16)
num = num * base + (c - ('a'-10));
else {
// ungetch(c)
break;
}
if ((width && !--width) || !gfileRead(f, &c, 1))
break;
}
assignnum:
if (negate)
num = -num;
if (assign) {
switch(size) {
case 0: // short
p = (char *)va_arg(arg, short *);
res++;
*((short *)p) = (short)num;
case 1: // int
p = (char *)va_arg(arg, int *);
res++;
*((int *)p) = (int)num;
case 2: case 3: // long
p = (char *)va_arg(arg, long *);
res++;
*((long *)p) = (long)num;
}
}
break;
#if GFILE_ALLOW_FLOATS
case 'e': case 'f': case 'g':
// TODO
#endif
default:
return res;
}
break;
default:
matchchar:
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (c != *fmt) return res;
break;
return pfl;
}
}
return res;
}
#if GFILE_NEED_STRINGS
int sscang(const char *buf, const char *fmt, ...) {
int res;
GFILE f;
va_list ap;
f.flags = GFILEFLG_OPEN|GFILEFLG_READ;
f.vmt = &StringVMT;
f.pos = 0;
f.obj = (void *)buf;
va_start(ap, fmt);
res = vfscang(&f, fmt, ap);
va_end(ap);
return res;
}
int vsscang(const char *buf, const char *fmt, va_list arg) {
int res;
GFILE f;
f.flags = GFILEFLG_OPEN|GFILEFLG_READ;
f.vmt = &StringVMT;
f.pos = 0;
f.obj = (void *)buf;
res = vfscang(&f, fmt, arg);
return res;
}
#endif
#endif
/********************************************************
* stdio emulation routines
********************************************************/
#if GFILE_NEED_STDIO
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f) {
return gfileRead(f, ptr, size*count)/size;
}
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f) {
return gfileWrite(f, ptr, size*count)/size;
}
int gstdioSeek(FILE *f, size_t offset, int origin) {
switch(origin) {
case SEEK_SET:
break;
case SEEK_CUR:
offset += f->pos;
break;
case SEEK_END:
offset += gfileGetSize(f);
break;
default:
return -1;
}
return gfileSetPos(f, offset) ? 0 : -1;
}
int gstdioGetpos(FILE *f, long int *pos) {
if (!(f->flags & GFILEFLG_OPEN))
return -1;
*pos = f->pos;
return 0;
}
const char *gfileReadFileList(gfileList *pfl) {
return pfl->vmt->flread ? pfl->vmt->flread(pfl) : 0;
}
void gfileCloseFileList(gfileList *pfl) {
if (pfl->vmt->flclose)
pfl->vmt->flclose(pfl);
}
#endif
#endif /* GFX_USE_GFILE */

View File

@ -27,22 +27,39 @@ static const GFILEVMT FsCHIBIOSVMT = {
0, 0, 0, 0,
0, ChibiOSBFSClose, ChibiOSBFSRead, ChibiOSBFSWrite,
ChibiOSBFSSetpos, ChibiOSBFSGetsize, ChibiOSBFSEof,
0, 0,
0
0, 0, 0,
#if GFILE_NEED_FILELISTS
0, 0, 0,
#endif
};
static void ChibiOSBFSClose(GFILE *f) {
chFileStreamClose(((BaseFileStream *)f->fd));
chFileStreamClose(((BaseFileStream *)f->obj));
}
static int ChibiOSBFSRead(GFILE *f, void *buf, int size) {
return chSequentialStreamRead(((BaseFileStream *)f->fd), (uint8_t *)buf, size);
return chSequentialStreamRead(((BaseFileStream *)f->obj), (uint8_t *)buf, size);
}
static int ChibiOSBFSWrite(GFILE *f, const void *buf, int size) {
return chSequentialStreamWrite(((BaseFileStream *)f->fd), (uint8_t *)buf, size);
return chSequentialStreamWrite(((BaseFileStream *)f->obj), (uint8_t *)buf, size);
}
static bool_t ChibiOSBFSSetpos(GFILE *f, long int pos) {
chFileStreamSeek(((BaseFileStream *)f->fd), pos);
chFileStreamSeek(((BaseFileStream *)f->obj), pos);
return TRUE;
}
static long int ChibiOSBFSGetsize(GFILE *f) { return chFileStreamGetSize(((BaseFileStream *)f->fd)); }
static bool_t ChibiOSBFSEof(GFILE *f) { return f->pos >= chFileStreamGetSize(((BaseFileStream *)f->fd)); }
static long int ChibiOSBFSGetsize(GFILE *f) { return chFileStreamGetSize(((BaseFileStream *)f->obj)); }
static bool_t ChibiOSBFSEof(GFILE *f) { return f->pos >= chFileStreamGetSize(((BaseFileStream *)f->obj)); }
GFILE * gfileOpenBaseFileStream(void *BaseFileStreamPtr, const char *mode) {
GFILE * f;
// Get an empty file and set the flags
if (!(f = findemptyfile(mode)))
return 0;
// File is open - fill in all the details
f->vmt = &FsCHIBIOSVMT;
f->obj = BaseFileStreamPtr;
f->pos = 0;
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
return f;
}

View File

@ -30,6 +30,11 @@ static bool_t fatfsEOF(GFILE* f);
static bool_t fatfsMount(const char* drive);
static bool_t fatfsUnmount(const char* drive);
static bool_t fatfsSync(GFILE* f);
#if _FS_MINIMIZE <= 1 && GFILE_NEED_FILELISTS
static gfileList *fatfsFlOpen(const char *path, bool_t dirs);
static const char *fatfsFlRead(gfileList *pfl);
static void fatfsFlClose(gfileList *pfl);
#endif
static const GFILEVMT FsFatFSVMT = {
GFILE_CHAINHEAD,
@ -46,14 +51,29 @@ static const GFILEVMT FsFatFSVMT = {
fatfsSetPos,
fatfsGetSize,
fatfsEOF,
fatfsMount,
fatfsUnmount,
fatfsSync
fatfsMount, fatfsUnmount, fatfsSync,
#if GFILE_NEED_FILELISTS
#if _FS_MINIMIZE <= 1
fatfsFlOpen, fatfsFlRead, fatfsFlClose
#else
0, 0, 0
#endif
#endif
};
#undef GFILE_CHAINHEAD
#define GFILE_CHAINHEAD &FsFatFSVMT
// Our directory list structure
typedef struct fatfsList {
gfileList fl; // This must be the first element.
DIR dir;
FILINFO fno;
#if _USE_LFN
char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */
#endif
} fatfsList;
// optimize these later on. Use an array to have multiple FatFS
static bool_t fatfs_mounted = FALSE;
static FATFS fatfs_fs;
@ -245,3 +265,58 @@ static bool_t fatfsSync(GFILE *f)
return TRUE;
}
#if _FS_MINIMIZE <= 1 && GFILE_NEED_FILELISTS
static gfileList *fatfsFlOpen(const char *path, bool_t dirs) {
fatfsList *p;
(void) dirs;
if (!(p = gfxAlloc(sizeof(fatfsList))))
return 0;
if (f_opendir(&p->dir, path) != FR_OK) {
gfxFree(p);
return 0;
}
return &p->fl;
}
static const char *fatfsFlRead(gfileList *pfl) {
#define ffl ((fatfsList *)pfl)
while(1) {
#if _USE_LFN
ffl->fno.lfname = ffl->lfn;
ffl->fno.lfsize = sizeof(ffl->lfn);
#endif
// Read the next entry
if (f_readdir(&ffl->dir, &ffl->fno) != FR_OK || !ffl->fno.fname[0])
return 0;
/* Ignore dot entries */
if (ffl->fno.fname[0] == '.') continue;
/* Is it a directory */
if (ffl->fl.dirs) {
if ((ffl->fno.fattrib & AM_DIR))
break;
} else {
if (!(ffl->fno.fattrib & AM_DIR))
break;
}
}
#if _USE_LFN
return ffl->fno.lfname[0] ? ffl->fno.lfname : ffl->fno.fname;
#else
return ffl->fno.fname;
#endif
#undef ffl
}
static void fatfsFlClose(gfileList *pfl) {
f_closedir(&((fatfsList *)pfl)->dir);
gfxFree(pfl);
}
#endif

View File

@ -26,8 +26,10 @@ static const GFILEVMT FsMemVMT = {
0, 0, 0, 0,
0, 0, MEMRead, MEMWrite,
MEMSetpos, 0, 0,
0, 0,
0
0, 0, 0,
#if GFILE_NEED_FILELISTS
0, 0, 0,
#endif
};
static int MEMRead(GFILE *f, void *buf, int size) {
@ -43,3 +45,18 @@ static bool_t MEMSetpos(GFILE *f, long int pos) {
(void) pos;
return TRUE;
}
GFILE * gfileOpenMemory(void *memptr, const char *mode) {
GFILE *f;
// Get an empty file and set the flags
if (!(f = findemptyfile(mode)))
return 0;
// File is open - fill in all the details
f->vmt = &FsMemVMT;
f->obj = memptr;
f->pos = 0;
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
return f;
}

View File

@ -33,6 +33,11 @@ static int NativeWrite(GFILE *f, const void *buf, int size);
static bool_t NativeSetpos(GFILE *f, long int pos);
static long int NativeGetsize(GFILE *f);
static bool_t NativeEof(GFILE *f);
#if GFILE_NEED_FILELISTS
static gfileList *NativeFlOpen(const char *path, bool_t dirs);
static const char *NativeFlRead(gfileList *pfl);
static void NativeFlClose(gfileList *pfl);
#endif
static const GFILEVMT FsNativeVMT = {
GFILE_CHAINHEAD, // next
@ -46,8 +51,10 @@ static const GFILEVMT FsNativeVMT = {
NativeDel, NativeExists, NativeFilesize, NativeRen,
NativeOpen, NativeClose, NativeRead, NativeWrite,
NativeSetpos, NativeGetsize, NativeEof,
0, 0,
0
0, 0, 0,
#if GFILE_NEED_FILELISTS
NativeFlOpen, NativeFlRead, NativeFlClose
#endif
};
#undef GFILE_CHAINHEAD
#define GFILE_CHAINHEAD &FsNativeVMT
@ -102,3 +109,108 @@ static long int NativeGetsize(GFILE *f) {
if (fstat(fileno((FILE *)f->obj), &st)) return -1;
return st.st_size;
}
#if GFILE_NEED_FILELISTS
#if defined(WIN32) || GFX_USE_OS_WIN32
typedef struct NativeFileList {
gfileList fl;
HANDLE d;
WIN32_FIND_DATA f;
bool_t first;
} NativeFileList;
static gfileList *NativeFlOpen(const char *path, bool_t dirs) {
NativeFileList *p;
(void) dirs;
if (!(p = gfxAlloc(sizeof(NativeFileList))))
return 0;
if ((p->d = FindFirstFile(path, &p->f)) == INVALID_HANDLE_VALUE) {
gfxFree(p);
return 0;
}
p->first = TRUE;
return &p->fl;
}
static const char *NativeFlRead(gfileList *pfl) {
#define nfl ((NativeFileList *)pfl)
while(1) {
if (!nfl->first && !FindNextFile(nfl->d, &nfl->f))
return 0;
nfl->first = FALSE;
if (nfl->f.cFileName[0] == '.')
continue;
if (nfl->fl.dirs) {
if ((nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
break;
} else {
if (!(nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
break;
}
}
return nfl->f.cFileName;
#undef nfl
}
static void NativeFlClose(gfileList *pfl) {
CloseHandle(((NativeFileList *)pfl)->d);
gfxFree(pfl);
}
#else
#include <dirent.h>
typedef struct NativeFileList {
gfileList fl;
DIR * d;
struct dirent * f;
} NativeFileList;
static gfileList *NativeFlOpen(const char *path, bool_t dirs) {
NativeFileList *p;
(void) dirs;
if (!(p = gfxAlloc(sizeof(NativeFileList))))
return 0;
if (!(p->d = opendir(path))) {
gfxFree(p);
return 0;
}
return &p->fl;
}
static const char *NativeFlRead(gfileList *pfl) {
#define nfl ((NativeFileList *)pfl)
while(1) {
if (!(nfl->f = readdir(nfl->d)))
return 0;
if (nfl->f->d_name[0] == '.')
continue;
#ifdef _DIRENT_HAVE_D_TYPE
if (nfl->fl.dirs) {
if (nfl->f->d_type == DT_DIR)
break;
} else {
if (nfl->f->d_type == DT_REG)
break;
}
#else
// Oops - no type field. We could use stat() here but that would mean
// concatting the supplied path to the found filename.
// That all just seems too hard. Instead we just don't
// distinguish between files and directories.
break;
#endif
}
return nfl->f->d_name;
#undef nfl
}
static void NativeFlClose(gfileList *pfl) {
closedir(((NativeFileList *)pfl)->d);
gfxFree(pfl);
}
#endif
#endif

View File

@ -0,0 +1,261 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* This file is included by src/gfile/gfile.c
*/
/********************************************************
* Printg Routines
********************************************************/
#include <stdarg.h>
#define MAX_FILLER 11
#define FLOAT_PRECISION 100000
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...) {
int res;
va_list ap;
va_start(ap, fmt);
res = vfnprintg(f, maxlen, fmt, ap);
va_end(ap);
return res;
}
static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) {
int i;
char * q;
if (!divisor) divisor = num;
q = p + MAX_FILLER;
do {
i = (int)(num % radix);
i += '0';
if (i > '9')
i += 'A' - '0' - 10;
*--q = i;
num /= radix;
} while ((divisor /= radix) != 0);
i = (int)(p + MAX_FILLER - q);
do {
*p++ = *q++;
} while (--i);
return p;
}
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg) {
int ret;
char *p, *s, c, filler;
int i, precision, width;
bool_t is_long, left_align;
long l;
#if GFILE_ALLOW_FLOATS
float f;
char tmpbuf[2*MAX_FILLER + 1];
#else
char tmpbuf[MAX_FILLER + 1];
#endif
ret = 0;
if (maxlen < 0)
return 0;
if (!maxlen)
maxlen = -1;
while (*fmt) {
if (*fmt != '%') {
gfileWrite(f, fmt, 1);
ret++; if (!--maxlen) return ret;
fmt++;
continue;
}
fmt++;
p = s = tmpbuf;
left_align = FALSE;
filler = ' ';
width = 0;
precision = 0;
if (*fmt == '-') {
fmt++;
left_align = TRUE;
}
if (*fmt == '.') {
fmt++;
filler = '0';
}
while (1) {
c = *fmt++;
if (c >= '0' && c <= '9') {
c -= '0';
width = width * 10 + c;
} else if (c == '*')
width = va_arg(arg, int);
else
break;
}
if (c == '.') {
while (1) {
c = *fmt++;
if (c >= '0' && c <= '9') {
c -= '0';
precision = precision * 10 + c;
} else if (c == '*')
precision = va_arg(arg, int);
else
break;
}
}
/* Long modifier.*/
if (c == 'l' || c == 'L') {
is_long = TRUE;
if (*fmt)
c = *fmt++;
}
else
is_long = (c >= 'A') && (c <= 'Z');
/* Command decoding.*/
switch (c) {
case 0:
return ret;
case 'c':
filler = ' ';
*p++ = va_arg(arg, int);
break;
case 's':
filler = ' ';
if ((s = va_arg(arg, char *)) == 0)
s = "(null)";
if (precision == 0)
precision = 32767;
for (p = s; *p && (--precision >= 0); p++);
break;
case 'D':
case 'd':
if (is_long)
l = va_arg(arg, long);
else
l = va_arg(arg, int);
if (l < 0) {
*p++ = '-';
l = -l;
}
p = ltoa_wd(p, l, 10, 0);
break;
#if GFILE_ALLOW_FLOATS
case 'f':
f = (float) va_arg(arg, double);
if (f < 0) {
*p++ = '-';
f = -f;
}
l = f;
p = ltoa_wd(p, l, 10, 0);
*p++ = '.';
l = (f - l) * FLOAT_PRECISION;
p = ltoa_wd(p, l, 10, FLOAT_PRECISION / 10);
break;
#endif
case 'X':
case 'x':
c = 16;
goto unsigned_common;
case 'U':
case 'u':
c = 10;
goto unsigned_common;
case 'O':
case 'o':
c = 8;
unsigned_common:
if (is_long)
l = va_arg(arg, long);
else
l = va_arg(arg, int);
p = ltoa_wd(p, l, c, 0);
break;
default:
*p++ = c;
break;
}
i = (int)(p - s);
if ((width -= i) < 0)
width = 0;
if (left_align == FALSE)
width = -width;
if (width < 0) {
if (*s == '-' && filler == '0') {
gfileWrite(f, s++, 1);
ret++; if (!--maxlen) return ret;
i--;
}
do {
gfileWrite(f, &filler, 1);
ret++; if (!--maxlen) return ret;
} while (++width != 0);
}
while (--i >= 0) {
gfileWrite(f, s++, 1);
ret++; if (!--maxlen) return ret;
}
while (width) {
gfileWrite(f, &filler, 1);
ret++; if (!--maxlen) return ret;
width--;
}
}
return ret;
}
#if GFILE_NEED_STRINGS
int snprintg(char *buf, int maxlen, const char *fmt, ...) {
int res;
GFILE f;
va_list ap;
if (maxlen <= 1) {
if (maxlen == 1) {
*buf = 0;
return 0;
}
maxlen += 1;
}
f.flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
gfileOpenStringFromStaticGFILE(&f, buf);
va_start(ap, fmt);
res = vfnprintg(&f, maxlen-1, fmt, ap);
va_end(ap);
return res;
}
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg) {
GFILE f;
if (maxlen <= 1) {
if (maxlen == 1) {
*buf = 0;
return 0;
}
maxlen += 1;
}
f.flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
gfileOpenStringFromStaticGFILE(&f, buf);
return vfnprintg(&f, maxlen-1, fmt, arg);
}
#endif

View File

@ -31,11 +31,15 @@ typedef struct ROMFS_DIRENTRY {
} ROMFS_DIRENTRY;
#define ROMFS_DIRENTRY_HEAD 0
#include "romfs_files.h"
static const ROMFS_DIRENTRY const *FsROMHead = ROMFS_DIRENTRY_HEAD;
typedef struct ROMFileList {
gfileList fl;
const ROMFS_DIRENTRY *pdir;
} ROMFileList;
static bool_t ROMExists(const char *fname);
static long int ROMFilesize(const char *fname);
static bool_t ROMOpen(GFILE *f, const char *fname);
@ -44,6 +48,11 @@ static int ROMRead(GFILE *f, void *buf, int size);
static bool_t ROMSetpos(GFILE *f, long int pos);
static long int ROMGetsize(GFILE *f);
static bool_t ROMEof(GFILE *f);
#if GFILE_NEED_FILELISTS
static gfileList *ROMFlOpen(const char *path, bool_t dirs);
static const char *ROMFlRead(gfileList *pfl);
static void ROMFlClose(gfileList *pfl);
#endif
static const GFILEVMT FsROMVMT = {
GFILE_CHAINHEAD, // next
@ -52,8 +61,10 @@ static const GFILEVMT FsROMVMT = {
0, ROMExists, ROMFilesize, 0,
ROMOpen, ROMClose, ROMRead, 0,
ROMSetpos, ROMGetsize, ROMEof,
0, 0,
0
0, 0, 0,
#if GFILE_NEED_FILELISTS
ROMFlOpen, ROMFlRead, ROMFlClose
#endif
};
#undef GFILE_CHAINHEAD
#define GFILE_CHAINHEAD &FsROMVMT
@ -122,3 +133,45 @@ static bool_t ROMEof(GFILE *f)
{
return f->pos >= ((const ROMFS_DIRENTRY *)f->obj)->size;
}
#if GFILE_NEED_FILELISTS
static gfileList *ROMFlOpen(const char *path, bool_t dirs) {
ROMFileList * p;
(void) path;
// We don't support directories or path searching
if (dirs)
return 0;
// Allocate the list buffer
if (!(p = gfxAlloc(sizeof(ROMFileList))))
return 0;
// Initialize it and return it.
p->pdir = 0;
return &p->fl;
}
static const char *ROMFlRead(gfileList *pfl) {
#define rfl ((ROMFileList *)pfl)
// Is it the first entry
if (!rfl->pdir) {
rfl->pdir = FsROMHead;
return FsROMHead->name;
}
// Is it not the last entry
if (rfl->pdir->next) {
rfl->pdir = rfl->pdir->next;
return rfl->pdir->name;
}
return 0;
#undef rfl
}
static void ROMFlClose(gfileList *pfl) {
gfxFree(pfl);
}
#endif

View File

@ -0,0 +1,257 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* This file is included by src/gfile/gfile.c
*/
/********************************************************
* Scang Routines
********************************************************/
int fscang(GFILE *f, const char *fmt, ...) {
int res;
va_list ap;
va_start(ap, fmt);
res = vfscang(f, fmt, ap);
va_end(ap);
return res;
}
int vfscang(GFILE *f, const char *fmt, va_list arg) {
int res, width, size, base;
unsigned long num;
char c;
bool_t assign, negate;
char *p;
for(res = 0; *fmt; fmt++) {
switch(*fmt) {
case ' ': case '\t': case '\r': case '\n': case '\v': case '\f':
break;
case '%':
fmt++;
assign = TRUE;
negate = FALSE;
width = 0;
size = 1;
num = 0;
if (*fmt == '*') {
fmt++;
assign = FALSE;
}
while(*fmt >= '0' && *fmt <= '9')
width = width * 10 + (*fmt++ - '0');
if (*fmt == 'h') {
fmt++;
size = 0;
} else if (*fmt == 'l') {
fmt++;
size = 2;
} else if (*fmt == 'L') {
fmt++;
size = 3;
}
switch(*fmt) {
case 0:
return res;
case '%':
goto matchchar;
case 'c':
if (!width) {
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
width = 1;
} else {
if (!gfileRead(f, &c, 1)) return res;
}
if (assign) {
p = va_arg(arg, char *);
res++;
*p++ = c;
}
while(--width) {
if (!gfileRead(f, &c, 1)) return res;
if (assign) *p++ = c;
}
break;
case 's':
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (assign) {
p = va_arg(arg, char *);
res++;
*p++ = c;
}
if (width) {
while(--width) {
if (!gfileRead(f, &c, 1)) {
if (assign) *((char *)p) = 0;
return res;
}
if (assign) *p++ = c;
}
} else {
while(1) {
if (!gfileRead(f, &c, 1)) {
if (assign) *((char *)p) = 0;
return res;
}
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': break;
default:
if (assign) *p++ = c;
continue;
}
break;
}
//ungetch(c);
}
if (assign) *p = 0;
break;
case 'd': base = 10; goto getnum;
case 'i': base = -1; goto getnum;
case 'o': base = 8; goto getnum;
case 'u': base = 10; goto getnum;
case 'x': base = 16; goto getnum;
case 'b': base = 2;
getnum:
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (c == '-' && *fmt != 'u') {
negate = TRUE;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
}
if (base == -1) {
if (c == '0') {
if ((width && !--width) || !gfileRead(f, &c, 1)) goto assignnum;
switch(c) {
case 'x': case 'X':
base = 16;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
break;
case 'b': case 'B':
base = 2;
if ((width && !--width) || !gfileRead(f, &c, 1)) return res;
break;
default:
base = 8;
break;
}
} else
base = 10;
}
while(1) {
if (c >= '0' && c <= '9' && c - '0' < base)
num = num * base + (c - '0');
else if (c >= 'A' && c <= 'F' && base == 16)
num = num * base + (c - ('A'-10));
else if (c >= 'a' && c <= 'f' && base == 16)
num = num * base + (c - ('a'-10));
else {
// ungetch(c)
break;
}
if ((width && !--width) || !gfileRead(f, &c, 1))
break;
}
assignnum:
if (negate)
num = -num;
if (assign) {
switch(size) {
case 0: // short
p = (char *)va_arg(arg, short *);
res++;
*((short *)p) = (short)num;
case 1: // int
p = (char *)va_arg(arg, int *);
res++;
*((int *)p) = (int)num;
case 2: case 3: // long
p = (char *)va_arg(arg, long *);
res++;
*((long *)p) = (long)num;
}
}
break;
#if GFILE_ALLOW_FLOATS
case 'e': case 'f': case 'g':
// TODO
#endif
default:
return res;
}
break;
default:
matchchar:
while(1) {
if (!gfileRead(f, &c, 1)) return res;
switch(c) {
case ' ': case '\t': case '\r':
case '\n': case '\v': case '\f': continue;
}
break;
}
if (c != *fmt) return res;
break;
}
}
return res;
}
#if GFILE_NEED_STRINGS
int sscang(const char *buf, const char *fmt, ...) {
int res;
GFILE f;
va_list ap;
f.flags = GFILEFLG_READ;
gfileOpenStringFromStaticGFILE(&f, (char *)buf);
va_start(ap, fmt);
res = vfscang(&f, fmt, ap);
va_end(ap);
return res;
}
int vsscang(const char *buf, const char *fmt, va_list arg) {
GFILE f;
f.flags = GFILEFLG_READ;
gfileOpenStringFromStaticGFILE(&f, (char *)buf);
return vfscang(&f, fmt, arg);
}
#endif

View File

@ -0,0 +1,45 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* This file is included by src/gfile/gfile.c
*/
/********************************************************
* Stdio Emulation Routines
********************************************************/
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f) {
return gfileRead(f, ptr, size*count)/size;
}
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f) {
return gfileWrite(f, ptr, size*count)/size;
}
int gstdioSeek(FILE *f, size_t offset, int origin) {
switch(origin) {
case SEEK_SET:
break;
case SEEK_CUR:
offset += f->pos;
break;
case SEEK_END:
offset += gfileGetSize(f);
break;
default:
return -1;
}
return gfileSetPos(f, offset) ? 0 : -1;
}
int gstdioGetpos(FILE *f, long int *pos) {
if (!(f->flags & GFILEFLG_OPEN))
return -1;
*pos = f->pos;
return 0;
}

View File

@ -0,0 +1,69 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* This file is included by src/gfile/gfile.c
*/
/********************************************************
* The virtual string file VMT
********************************************************/
#include <string.h>
// Special String VMT
static int StringRead(GFILE *f, void *buf, int size) {
int res;
char *p;
p = ((char *)f->obj) + f->pos;
for(res = 0; res < size && *p; res++, p++, buf = ((char *)buf)+1)
((char *)buf)[0] = *p;
return res;
}
static int StringWrite(GFILE *f, const void *buf, int size) {
if ((f->flags & GFILEFLG_APPEND)) {
while(((char *)f->obj)[f->pos])
f->pos++;
}
memcpy(((char *)f->obj)+f->pos, buf, size);
((char *)f->obj)[f->pos+size] = 0;
return size;
}
static const GFILEVMT StringVMT = {
0, // next
0, // flags
'_', // prefix
0, 0, 0, 0,
0, 0, StringRead, StringWrite,
0, 0, 0,
0, 0, 0,
#if GFILE_NEED_FILELISTS
0, 0, 0,
#endif
};
static void gfileOpenStringFromStaticGFILE(GFILE *f, char *str) {
if ((f->flags & GFILEFLG_TRUNC))
str[0] = 0;
f->vmt = &StringVMT;
f->obj = str;
f->pos = 0;
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
}
GFILE *gfileOpenString(char *str, const char *mode) {
GFILE *f;
// Get an empty file and set the flags
if (!(f = findemptyfile(mode)))
return 0;
// File is open - fill in all the details
gfileOpenStringFromStaticGFILE(f, str);
return f;
}

View File

@ -33,8 +33,10 @@
#ifndef GFILE_IMPLEMENTATION
typedef void GFILE;
typedef void gfileList;
#else
typedef struct GFILE GFILE;
typedef struct gfileList gfileList;
#endif
extern GFILE *gfileStdIn;
@ -98,14 +100,33 @@ extern "C" {
/**
* @brief Open file
* @details A file must be opened before it can be accessed
* @details ToDo (document possible modes)
* @details The resulting GFILE will be used for all functions that access the file.
*
* @param[in] fname The file name
* @param[in] mode The mode
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes follow the c library fopen() standard.
* The valid modes are:<br/>
* <ul><li>r - Open for read, the file must exist</li>
* <li>w - Open for write, the file is truncated if it exists</li>
* <li>wx - Open for write, the file must not exist</li>
* <li>a - Open for append, the file is truncated if it exists</li>
* <li>ax - Open for append, the file must not exists</li>
* </ul><br/>
* THe following flags can also be added to the above modes:<br/>
* <ul><li>+ - Open for both read and write</li>
* <li>b - Open as a binary file rather than a text file</li>
* <ul>
* @note Not all file-systems support all modes. For example, write
* is not available with the ROM file-system. Similarly few platforms
* distinguish between binary and text files.
* @note Even though binary vs text is relevant only for a small number of platforms
* the "b" flag should always be specified for binary files such as images.
* This ensures portability to other platforms. The extra flag will be ignored
* on platforms where it is not relevant.
*
* @api
*/
GFILE * gfileOpen(const char *fname, const char *mode);
@ -239,15 +260,118 @@ extern "C" {
*/
bool_t gfileSync(GFILE *f);
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
#if GFILE_NEED_FILELISTS || defined(__DOXYGEN__)
/**
* @brief Open a file list
*
* @param[in] fs The file system (F for FatFS)
* @param[in] path Path information to pass to the file system
* @param[in] dirs Pass TRUE to get directories only, FALSE to get files only
*
* @return A pointer to a file list on success, NULL otherwise
*
* @note The path parameter is handled in a file-system specific way. It could be
* treated as a directory name, it may be treated as a file pattern, or it
* may be ignored. Passing NULL will always return the full list of files
* in at least the top level directory.
* @note For file systems that do not support directories, passing TRUE for dirs
* will return an error.
* @note You must call @p gfileCloseFileList() when you have finished with the
* file list in order to free resources.
*
* @api
*/
gfileList *gfileOpenFileList(char fs, const char *path, bool_t dirs);
/**
* @brief Get the next file in a file list.
*
* @param[in] pfl Pointer to a file list returned by @p gfileOpenFileList()
*
* @return A pointer to a file (or directory) name. Returns NULL if there are no more.
*
* @note The file name may contain the full directory path or may not depending
* on how the file system treats directories.
* @note The returned buffer may be destroyed by the next call to any of
* @p gfileOpenFileList(), @p gfileReadFileList() or @p gfileCloseFileList().
* Do not use this pointer after one of those calls.
*
* @api
*/
const char *gfileReadFileList(gfileList *pfl);
/**
* @brief Close a file list.
*
* @param[in] pfl Pointer to a file list returned by @p gfileOpenFileList()
*
* @api
*/
void gfileCloseFileList(gfileList *pfl);
#endif
#if (GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS) || defined(__DOXYGEN__)
/**
* @brief Open file from a ChibiOS BaseFileStream
*
* @param[in] BaseFileStreamPtr The BaseFileStream to open as a GFILE
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). The
* open mode is NOT compared against the BaseFileStream capabilities.
* @note Supported operations are: read, write, getpos, setpos, eof and getsize
*
* @api
*/
GFILE * gfileOpenBaseFileStream(void *BaseFileStreamPtr, const char *mode);
#endif
#if GFILE_NEED_MEMFS
#if GFILE_NEED_MEMFS || defined(__DOXYGEN__)
/**
* @brief Open file from a memory pointer
*
* @param[in] memptr The pointer to the memory
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). Note there is
* no concept of file-size. Be careful not to overwrite other memory or
* to read from inaccessible sections of memory.
* @note Supported operations are: read, write, getpos, setpos
*
* @api
*/
GFILE * gfileOpenMemory(void *memptr, const char *mode);
#endif
#if GFILE_NEED_PRINTG
#if GFILE_NEED_STRINGS || defined(__DOXYGEN__)
/**
* @brief Open file from a null terminated C string
*
* @param[in] memptr The pointer to the string or string buffer
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). Note there is
* no concept of file-size. Be careful not to overwrite other memory or
* to read from inaccessible sections of memory.
* @note Reading will return EOF when the NULL character is reached.
* @note Writing will always place a NULL in the next character effectively terminating the
* string at the character just written.
* @note Supported operations are: read, write, append, getpos, setpos
* @note Be careful with setpos and getpos. They do not check for the end of the string.
* @note Reading and Writing will read/write a maximum of one character at a time.
*
* @api
*/
GFILE * gfileOpenString(char *str, const char *mode);
#endif
#if GFILE_NEED_PRINTG || defined(__DOXYGEN__)
#include <stdarg.h>
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg);
@ -265,7 +389,7 @@ extern "C" {
#endif
#endif
#if GFILE_NEED_SCANG
#if GFILE_NEED_SCANG || defined(__DOXYGEN__)
#include <stdarg.h>
int vfscang(GFILE *f, const char *fmt, va_list arg);

View File

@ -46,6 +46,7 @@
/**
* @brief Include printg, fprintg etc functions
* @details Defaults to FALSE
* @pre To get the string sprintg functions you also need to define @p GFILE_NEED_STRINGS
*/
#ifndef GFILE_NEED_PRINTG
#define GFILE_NEED_PRINTG FALSE
@ -53,15 +54,14 @@
/**
* @brief Include scang, fscang etc functions
* @details Defaults to FALSE
* @pre To get the string sscang functions you also need to define @p GFILE_NEED_STRINGS
*/
#ifndef GFILE_NEED_SCANG
#define GFILE_NEED_SCANG FALSE
#endif
/**
* @brief Include the string sprintg/sscang functions
* @brief Include the string based file functions
* @details Defaults to FALSE
* @pre To get sprintg functions you also need to define @p GFILE_NEED_PRINTG
* @pre To get sscang functions you also need to define @p GFILE_NEED_SCANG
*/
#ifndef GFILE_NEED_STRINGS
#define GFILE_NEED_STRINGS FALSE
@ -146,6 +146,14 @@
#ifndef GFILE_NEED_MEMFS
#define GFILE_NEED_MEMFS FALSE
#endif
/**
* @brief Include support for file list functions
* @details Defaults to FALSE
* @note Adds support for @p gfileOpenFileList(), @p gfileReadFileList() and @p gfileCloseFileList().
*/
#ifndef GFILE_NEED_FILELISTS
#define GFILE_NEED_FILELISTS FALSE
#endif
/**
* @}
*

View File

@ -33,18 +33,21 @@
void _gosInit(void)
{
/* Don't initialise if the user already has */
#if CH_KERNEL_MAJOR == 2
if (!chThdSelf()) {
halInit();
chSysInit();
}
#elif CH_KERNEL_MAJOR == 3
if (!chThdGetSelfX()) {
halInit();
chSysInit();
}
#if !GFX_NO_OS_INIT
/* Don't Initialize if the user already has */
#if CH_KERNEL_MAJOR == 2
if (!chThdSelf()) {
halInit();
chSysInit();
}
#elif CH_KERNEL_MAJOR == 3
if (!chThdGetSelfX()) {
halInit();
chSysInit();
}
#endif
#else
#warning "GOS: Operating System initialization has been turned off. Make sure you call halInit() and chSysInit() before gfxInit() in your application!"
#endif
}

View File

@ -11,8 +11,11 @@
void _gosInit(void)
{
/* Don't initialise if the user already has */
//cyg_scheduler_start();
#if !GFX_NO_OS_INIT
#error "GOS: Operating System initialization for eCos is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h"
#else
#warning "GOS: Operating System initialization has been turned off. Make sure you call cyg_scheduler_start() before gfxInit() in your application!"
#endif
}
void _gosDeinit(void)

View File

@ -18,13 +18,17 @@
#error "GOS: configUSE_MUTEXES must be defined in FreeRTOSConfig.h"
#endif
#if configUSE_COUNTING_SEMAPHORES != 1
#if configUSE_COUNTING_SEMAPHORES != 1
#error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h"
#endif
void _gosInit(void)
{
// The user must call vTaskStartScheduler() himself before he calls gfxInit().
#if !GFX_NO_OS_INIT
#error "GOS: Operating System initialization for FreeRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h"
#else
#warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler() before gfxInit() in your application!"
#endif
}
void _gosDeinit(void)

View File

@ -24,6 +24,18 @@
/* Type definitions */
/*===========================================================================*/
/* Additional types are required when FreeRTOS 7.x is used */
#if !defined(tskKERNEL_VERSION_MAJOR) && !tskKERNEL_VERSION_MAJOR == 8
typedef signed char int8_t
typedef unsigned char uint8_t
typedef signed int int16_t
typedef unsigned int uint16_t
typedef signed long int int32_t
typedef unsigned long int uint32_t
typedef signed long long int int64_t
typedef unsigned long long int uint64_t
#endif
/**
* bool_t,
* int8_t, uint8_t,

View File

@ -18,6 +18,7 @@ static gfxMutex SystemMutex;
void _gosInit(void)
{
/* No initialization of the operating system itself is needed */
gfxMutexInit(&SystemMutex);
}

View File

@ -35,6 +35,7 @@ void get_ticks(mach_timespec_t *mts){
void _gosInit(void)
{
/* No initialization of the operating system itself is needed */
gfxMutexInit(&SystemMutex);
}

View File

@ -24,6 +24,12 @@ static void _gosThreadsInit(void);
void _gosInit(void)
{
/* No initialization of the operating system itself is needed as there isn't one.
* On the other hand the C runtime should still already be initialized before
* getting here!
*/
#warning "GOS: Raw32 - Make sure you initialize your hardware and the C runtime before calling gfxInit() in your application!"
// Set up the heap allocator
_gosHeapInit();

View File

@ -42,14 +42,20 @@
/*===========================================================================*/
typedef unsigned char bool_t;
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef uint32_t size_t;
#ifndef _STDINT_H
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
#endif
#if !defined (__need_size_t) && !defined (_STDDEF_H_)
typedef uint32_t size_t;
#endif
typedef uint32_t delaytime_t;
typedef uint32_t systemticks_t;
typedef short semcount_t;

View File

@ -0,0 +1,83 @@
#include "gfx.h"
#if GFX_USE_OS_RAWRTOS
#include <string.h>
#include "raw_api.h"
#include "raw_config.h"
#if CONFIG_RAW_MUTEX != 1
#error "GOS: CONFIG_RAW_MUTEX must be defined in raw_config.h"
#endif
#if CONFIG_RAW_SEMAPHORE != 1
#error "GOS: CONFIG_RAW_SEMAPHORE must be defined in raw_config.h"
#endif
void _gosInit(void)
{
#if !GFX_NO_OS_INIT
#error "GOS: Operating System initialization for RawRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h"
#else
#warning "GOS: Operating System initialization has been turned off. Make sure you call raw_os_start() before gfxInit() in your application!"
#endif
}
void _gosDeinit(void)
{
}
void gfxSleepMilliseconds(delaytime_t ms)
{
systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000;
if(!ticks)ticks = 1;
raw_sleep(ticks);
}
void gfxSleepMicroseconds(delaytime_t us)
{
systemticks_t ticks = (us/1000)*RAW_TICKS_PER_SECOND/1000;
if(!ticks)ticks = 1;
raw_sleep(ticks);
}
bool_t gfxSemWait(gfxSem* psem, delaytime_t ms)
{
systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000;
if(!ticks)ticks=1;
if(raw_semaphore_get((psem), ticks)==RAW_SUCCESS)
return TRUE;
return FALSE;
}
bool_t gfxSemWaitI(gfxSem* psem)
{
if(raw_semaphore_get((psem), TIME_IMMEDIATE)==RAW_SUCCESS)
return TRUE;
return FALSE;
}
gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param)
{
RAW_U16 ret;
gfxThreadHandle taskobj;
taskobj = gfxAlloc(sizeof(RAW_TASK_OBJ));
ret = raw_task_create(taskobj, (RAW_U8 *)"uGFX_TASK", param,
prio, 0, stackarea,
stacksz/sizeof(PORT_STACK) , fn, 1);
if (ret != RAW_SUCCESS) {
for (;;);
}
return (taskobj);
}
#endif

View File

@ -0,0 +1,77 @@
#ifndef _GOS_RAWRTOS_H
#define _GOS_RAWRTOS_H
#if GFX_USE_OS_RAWRTOS
#include "raw_api.h"
#include <stdint.h>
#define TIME_IMMEDIATE (RAW_NO_WAIT)
#define TIME_INFINITE (RAW_WAIT_FOREVER)
typedef int8_t bool_t;
typedef uint32_t delaytime_t;
typedef RAW_TICK_TYPE systemticks_t;
typedef int32_t semcount_t;
typedef uint32_t threadreturn_t;
typedef RAW_U8 threadpriority_t;
typedef uint32_t size_t;
#define MAX_SEMAPHORE_COUNT RAW_SEMAPHORE_COUNT
#define LOW_PRIORITY (CONFIG_RAW_PRIO_MAX-2)
#define NORMAL_PRIORITY (CONFIG_RAW_PRIO_MAX/2)
#define HIGH_PRIORITY 1
typedef RAW_SEMAPHORE gfxSem;
typedef RAW_MUTEX gfxMutex;
typedef RAW_TASK_OBJ* gfxThreadHandle;
#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param)
#define DECLARE_THREAD_STACK(name, sz) PORT_STACK name[sz];
#define gfxHalt(msg) for(;;)
#define gfxExit() for(;;)
#define gfxAlloc(sz) raw_malloc(sz)
#define gfxRealloc(p,osz,nsz) raw_calloc(p, nsz)
#define gfxFree(ptr) raw_free(ptr)
#define gfxYield() raw_sleep(0)
#define gfxSystemTicks() raw_system_time_get()
#define gfxMillisecondsToTicks(ms) (ms*RAW_TICKS_PER_SECOND/1000)
#define gfxSystemLock() {}
#define gfxSystemUnlock() {}
#define gfxMutexInit(pmutex) raw_mutex_create(pmutex, (RAW_U8 *)"", RAW_MUTEX_INHERIT_POLICY, 3)
#define gfxMutexDestroy(pmutex) raw_mutex_delete(pmutex)
#define gfxMutexEnter(pmutex) raw_mutex_get(pmutex, TIME_INFINITE)
#define gfxMutexExit(pmutex) raw_mutex_put(pmutex)
#define gfxSemInit(psem, val, limit) raw_semaphore_create(psem, "", val)
#define gfxSemDestroy(psem) raw_semaphore_delete(psem)
#define gfxSemSignal(psem) raw_semaphore_put((psem))
#define gfxSemSignalI(psem) raw_semaphore_put_all((psem))
#define gfxSemCounterI(psem) ((psem)->count)
#define gfxThreadMe() {(unsigned int)raw_task_identify()}
#define gfxThreadClose(thread) {}
extern RAW_VOID *raw_malloc(RAW_U32 size);
extern RAW_VOID raw_free(void *ptr);
extern RAW_VOID *raw_calloc(RAW_U32 nmemb, RAW_U32 size);
extern RAW_U16 raw_sleep(RAW_TICK_TYPE dly);
extern RAW_TICK_TYPE raw_system_time_get(void);
extern RAW_U16 raw_mutex_create(RAW_MUTEX *mutex_ptr, RAW_U8 *name_ptr, RAW_U8 policy, RAW_U8 ceiling_prio);
extern RAW_U16 raw_mutex_delete(RAW_MUTEX *mutex_ptr);
extern RAW_U16 raw_mutex_get(RAW_MUTEX *mutex_ptr, RAW_TICK_TYPE wait_option);
extern RAW_U16 raw_mutex_put(RAW_MUTEX *mutex_ptr);
extern RAW_U16 raw_semaphore_create(RAW_SEMAPHORE *semaphore_ptr, RAW_U8 *name_ptr, RAW_U32 initial_count);
extern RAW_U16 raw_semaphore_delete(RAW_SEMAPHORE *semaphore_ptr);
extern RAW_U16 raw_semaphore_get(RAW_SEMAPHORE *semaphore_ptr, RAW_TICK_TYPE wait_option);
extern RAW_U16 raw_semaphore_put(RAW_SEMAPHORE *semaphore_ptr);
void gfxSleepMilliseconds(delaytime_t ms);
void gfxSleepMicroseconds(delaytime_t us);
bool_t gfxSemWait(gfxSem* psem, delaytime_t ms);
bool_t gfxSemWaitI(gfxSem* psem);
gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param);
#endif
#endif

View File

@ -19,7 +19,7 @@ static HANDLE SystemMutex;
void _gosInit(void)
{
/* No initialization of the operating system itself is needed */
}
void _gosDeinit(void)

View File

@ -439,20 +439,22 @@
* All the above was just for the doxygen documentation. All the implementation of the above
* (without any of the documentation overheads) is in the files below.
*/
#elif GFX_USE_OS_RAWRTOS
#include "src/gos/gfx_rawrtos.h"
#elif GFX_USE_OS_CHIBIOS
#include "src/gos/chibios.h"
#include "src/gos/gfx_chibios.h"
#elif GFX_USE_OS_FREERTOS
#include "src/gos/freertos.h"
#include "src/gos/gfx_freertos.h"
#elif GFX_USE_OS_WIN32
#include "src/gos/win32.h"
#include "src/gos/gfx_win32.h"
#elif GFX_USE_OS_LINUX
#include "src/gos/linux.h"
#include "src/gos/gfx_linux.h"
#elif GFX_USE_OS_OSX
#include "src/gos/osx.h"
#include "src/gos/gfx_osx.h"
#elif GFX_USE_OS_RAW32
#include "src/gos/raw32.h"
#include "src/gos/gfx_raw32.h"
#elif GFX_USE_OS_ECOS
#include "src/gos/ecos.h"
#include "src/gos/gfx_ecos.h"
#else
#error "Your operating system is not supported yet"
#endif

View File

@ -1,8 +1,9 @@
GFXSRC += $(GFXLIB)/src/gos/chibios.c \
$(GFXLIB)/src/gos/freertos.c \
$(GFXLIB)/src/gos/win32.c \
$(GFXLIB)/src/gos/linux.c \
$(GFXLIB)/src/gos/osx.c \
$(GFXLIB)/src/gos/raw32.c \
$(GFXLIB)/src/gos/ecos.c
GFXSRC += $(GFXLIB)/src/gos/gfx_chibios.c \
$(GFXLIB)/src/gos/gfx_freertos.c \
$(GFXLIB)/src/gos/gfx_win32.c \
$(GFXLIB)/src/gos/gfx_linux.c \
$(GFXLIB)/src/gos/gfx_osx.c \
$(GFXLIB)/src/gos/gfx_raw32.c \
$(GFXLIB)/src/gos/gfx_ecos.c \
$(GFXLIB)/src/gos/gfx_rawrtos.c

View File

@ -75,6 +75,20 @@
* @name GOS Optional Parameters
* @{
*/
/**
* @brief Should uGFX avoid initializing the operating system
* @details Defaults to FALSE
* @note This is not relevant to all operating systems eg Win32 never initializes the
* operating system as uGFX runs as an application outside the boot process.
* @note Operating system initialization is not necessarily implemented for all
* operating systems yet even when it is relevant. These operating systems
* will display a compile warning reminding you to initialize the operating
* system in your application code. Note that on these operating systems the
* demo applications will not work without modification.
*/
#ifndef GFX_NO_OS_INIT
#define GFX_NO_OS_INIT FALSE
#endif
/**
* @brief Should uGFX stuff be added to the FreeRTOS+Tracer
* @details Defaults to FALSE

View File

@ -16,7 +16,7 @@
#ifndef _GOS_RULES_H
#define _GOS_RULES_H
#if !GFX_USE_OS_CHIBIOS && !GFX_USE_OS_WIN32 && !GFX_USE_OS_LINUX && !GFX_USE_OS_OSX && !GFX_USE_OS_RAW32 && !GFX_USE_OS_FREERTOS && !GFX_USE_OS_ECOS
#if !GFX_USE_OS_CHIBIOS && !GFX_USE_OS_WIN32 && !GFX_USE_OS_LINUX && !GFX_USE_OS_OSX && !GFX_USE_OS_RAW32 && !GFX_USE_OS_FREERTOS && !GFX_USE_OS_ECOS && !GFX_USE_OS_RAWRTOS
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GOS: No Operating System has been defined. ChibiOS (GFX_USE_OS_CHIBIOS) has been turned on for you."
#endif
@ -24,7 +24,7 @@
#define GFX_USE_OS_CHIBIOS TRUE
#endif
#if GFX_USE_OS_CHIBIOS + GFX_USE_OS_WIN32 + GFX_USE_OS_LINUX + GFX_USE_OS_OSX + GFX_USE_OS_RAW32 + GFX_USE_OS_FREERTOS + GFX_USE_OS_ECOS != 1 * TRUE
#if GFX_USE_OS_CHIBIOS + GFX_USE_OS_WIN32 + GFX_USE_OS_LINUX + GFX_USE_OS_OSX + GFX_USE_OS_RAW32 + GFX_USE_OS_FREERTOS + GFX_USE_OS_ECOS + GFX_USE_OS_RAWRTOS != 1 * TRUE
#error "GOS: More than one operation system has been defined as TRUE."
#endif

View File

@ -39,6 +39,9 @@ static void SendButtonEvent(GWidgetObject *gw) {
continue;
pbe->type = GEVENT_GWIN_BUTTON;
pbe->button = (GHandle)gw;
#if GWIN_WIDGET_TAGS
pbe->tag = gw->tag;
#endif
geventSendEvent(psl);
}

View File

@ -38,6 +38,9 @@
typedef struct GEventGWinButton {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle button; // The button that has been depressed (actually triggered on release)
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The button tag
#endif
} GEventGWinButton;
/**

View File

@ -33,6 +33,9 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
pce->type = GEVENT_GWIN_CHECKBOX;
pce->checkbox = &gw->g;
pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
#if GWIN_WIDGET_TAGS
pce->tag = gw->tag;
#endif
geventSendEvent(psl);
}

View File

@ -38,6 +38,9 @@ typedef struct GEventGWinCheckbox {
GEventType type; // The type of this event (GEVENT_GWIN_CHECKBOX)
GHandle checkbox; // The checkbox that has been depressed (actually triggered on release)
bool_t isChecked; // Is the checkbox currently checked or unchecked?
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The checkbox tag
#endif
} GEventGWinCheckbox;
/* A Checkbox window */

View File

@ -23,6 +23,10 @@
#if GFX_USE_GWIN || defined(__DOXYGEN__)
#if defined(__KEIL__) || defined(__C51__)
#pragma anon_unions
#endif
/**
* @brief The predefined flags for a Window
* @{

View File

@ -38,8 +38,10 @@ static coord_t BorderSizeT(GHandle gh) { return (gh->flags & GWIN_FRAME_BORDER)
static void _frameDestroy(GHandle gh) {
/* Deregister the button callback */
geventRegisterCallback(&gh2obj->gl, NULL, NULL);
geventDetachSource(&gh2obj->gl, NULL);
if ((gh->flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN))) {
geventRegisterCallback(&gh2obj->gl, NULL, NULL);
geventDetachSource(&gh2obj->gl, NULL);
}
/* call the gcontainer standard destroy routine */
_gcontainerDestroy(gh);

View File

@ -93,11 +93,14 @@ coord_t gwinGetInnerHeight(GHandle gh) {
static coord_t BorderSize(GHandle gh) { return (gh->flags & GWIN_CONTAINER_BORDER) ? 2 : 0; }
static void DrawSimpleContainer(GWidgetObject *gw, void *param) {
(void) param;
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
if ((gw->g.flags & GWIN_CONTAINER_BORDER))
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
}
(void)param;
if (!(gw->g.flags & GWIN_CONTAINER_TRANSPARENT))
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
if ((gw->g.flags & GWIN_CONTAINER_BORDER))
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
}
// The container VMT table
static const gcontainerVMT containerVMT = {

View File

@ -105,6 +105,7 @@ extern "C" {
* @{
*/
#define GWIN_CONTAINER_BORDER 0x00000001
#define GWIN_CONTAINER_TRANSPARENT 0x00000002
/** @} */
/**

View File

@ -86,6 +86,7 @@ static void gwidgetEvent(void *param, GEvent *pe) {
#define pte ((GEventToggle *)pe)
#define pde ((GEventDial *)pe)
GHandle h;
GHandle gh;
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
uint16_t role;
@ -99,32 +100,38 @@ static void gwidgetEvent(void *param, GEvent *pe) {
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Cycle through all windows
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
for(gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
// check if the widget matches this display
if (gh->display != pme->display)
// The window must be on this display and visible to be relevant
if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
continue;
// check if it is a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
continue;
// Are we captured?
if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
// Is the mouse currently captured by this widget?
if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) {
gh = h;
if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
gh->flags &= ~GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseUp)
wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y);
} else if (wvmt->MouseMove)
wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
wvmt->MouseMove(gw, pme->x - gh->x, pme->y - gh->y);
// We are not captured - look for mouse downs over the widget
} else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
&& pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
// There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
gh = 0;
break;
}
// Save the highest z-order window that the mouse is over
if (pme->x >= h->x && pme->x < h->x + h->width && pme->y >= h->y && pme->y < h->y + h->height)
gh = h;
}
// Process any mouse down over the highest order window if it is an enabled widget
if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
gh->flags |= GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
}
}
break;
@ -242,6 +249,9 @@ GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit
pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
pgw->fnParam = pInit->customParam;
pgw->pstyle = pInit->customStyle ? pInit->customStyle : defaultStyle;
#if GWIN_WIDGET_TAGS
pgw->tag = pInit->tag;
#endif
return &pgw->g;
}
@ -473,5 +483,16 @@ bool_t gwinAttachListener(GListener *pl) {
}
#endif
#if GWIN_WIDGET_TAGS
void gwinSetTag(GHandle gh, WidgetTag tag) {
if ((gh->flags & GWIN_FLG_WIDGET))
gw->tag = tag;
}
WidgetTag gwinGetTag(GHandle gh) {
return ((gh->flags & GWIN_FLG_WIDGET)) ? gw->tag : 0;
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
/** @} */

View File

@ -72,6 +72,11 @@ extern const GWidgetStyle WhiteWidgetStyle;
*/
typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param);
/**
* @brief Defines a the type of a tag on a widget
*/
typedef uint16_t WidgetTag;
/**
* @brief The structure to initialise a widget.
*
@ -92,6 +97,9 @@ typedef struct GWidgetInit {
CustomWidgetDrawFunction customDraw; // @< A custom draw function - use NULL for the standard
void * customParam; // @< A parameter for the custom draw function (default = NULL)
const GWidgetStyle * customStyle; // @< A custom style to use - use NULL for the default style
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
WidgetTag tag; // @< The tag to associate with the widget
#endif
} GWidgetInit;
/** @} */
@ -110,6 +118,9 @@ typedef struct GWidgetObject {
CustomWidgetDrawFunction fnDraw; // @< The current draw function
void * fnParam; // @< A parameter for the current draw function
const GWidgetStyle * pstyle; // @< The current widget style colors
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
WidgetTag tag; // @< The widget tag
#endif
} GWidgetObject;
/** @} */
@ -187,6 +198,34 @@ void gwinSetText(GHandle gh, const char *text, bool_t useAlloc);
*/
const char *gwinGetText(GHandle gh);
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
/**
* @brief Set the tag of a widget.
*
* @param[in] gh The widget handle
* @param[in] tag The tag to set.
*
* @note Non-widgets will ignore this call.
*
* @pre Requires GWIN_WIDGET_TAGS to be TRUE
*
* @api
*/
void gwinSetTag(GHandle gh, WidgetTag tag);
/**
* @brief Get the tag of a widget.
* @return The widget tag value (or 0 if it is not a widget)
*
* @param[in] gh The widget handle
*
* @pre Requires GWIN_WIDGET_TAGS to be TRUE
*
* @api
*/
WidgetTag gwinGetTag(GHandle gh);
#endif
/**
* @brief Set the style of a widget.
*
@ -235,7 +274,7 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
*/
bool_t gwinAttachListener(GListener *pl);
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
/**
* @brief Set the mouse to be used to control the widgets
* @return TRUE on success
@ -249,7 +288,7 @@ bool_t gwinAttachListener(GListener *pl);
bool_t gwinAttachMouse(uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__)
/**
* @brief Attach a toggle to a widget
* @return TRUE on success
@ -267,7 +306,7 @@ bool_t gwinAttachListener(GListener *pl);
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
#if (GFX_USE_GINPUT && GINPUT_NEED_DIAL) || defined(__DOXYGEN__)
/**
* @brief Attach a toggle to a widget
* @return TRUE on success

View File

@ -66,6 +66,9 @@ static void sendListEvent(GWidgetObject *gw, int item) {
ple->type = GEVENT_GWIN_LIST;
ple->list = (GHandle)gw;
ple->item = item;
#if GWIN_WIDGET_TAGS
ple->tag = gw->tag;
#endif
geventSendEvent(psl);
}

View File

@ -40,6 +40,9 @@ typedef struct GEventGWinList {
GEventType type; // The type of this event (GEVENT_GWIN_LIST)
GHandle list; // The list
int item; // The item that has been selected (or unselected in a multi-select listbox)
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The list tag
#endif
} GEventGWinList;
// A list window

View File

@ -38,6 +38,9 @@ static void SendRadioEvent(GWidgetObject *gw) {
pbe->type = GEVENT_GWIN_RADIO;
pbe->radio = (GHandle)gw;
pbe->group = ((GRadioObject *)gw)->group;
#if GWIN_WIDGET_TAGS
pbe->tag = gw->tag;
#endif
geventSendEvent(psl);
}

View File

@ -37,6 +37,9 @@ typedef struct GEventGWinRadio {
GEventType type; // The type of this event (GEVENT_GWIN_RADIO)
GHandle radio; // The radio button that has been depressed
uint16_t group; // The group for this radio button
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The radio tag
#endif
} GEventGWinRadio;
/**

View File

@ -38,6 +38,9 @@ static void SendSliderEvent(GWidgetObject *gw) {
pse->type = GEVENT_GWIN_SLIDER;
pse->slider = (GHandle)gw;
pse->position = ((GSliderObject *)gw)->pos;
#if GWIN_WIDGET_TAGS
pse->tag = gw->tag;
#endif
geventSendEvent(psl);
}

View File

@ -30,6 +30,9 @@ typedef struct GEventGWinSlider {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle slider; // The slider that is returning results
int position;
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The slider tag
#endif
} GEventGWinSlider;
// There are currently no GEventGWinSlider listening flags - use 0

View File

@ -127,6 +127,15 @@
* @name GWIN Optional Parameters
* @{
*/
/**
* @brief Add a tag to each widget
* @details Defaults to FALSE
* @note Adds a tag member to each widget. Any events created include this tag.
* The enables switch based application logic to detect the event source.
*/
#ifndef GWIN_WIDGET_TAGS
#define GWIN_WIDGET_TAGS FALSE
#endif
/**
* @brief Use flat styling for controls rather than a 3D look
* @details Defaults to FALSE