aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/modules/gaudin/gfxconf.h105
-rw-r--r--demos/modules/gaudin/gwinosc.c190
-rw-r--r--demos/modules/gaudin/gwinosc.h95
-rw-r--r--demos/modules/gaudin/main.c67
-rw-r--r--demos/modules/gaudin/results_264x264.jpgbin0 -> 19614 bytes
-rw-r--r--drivers/gadc/AT91SAM7/gadc_lld_config.h7
-rw-r--r--drivers/gaudin/gadc/gaudin_lld.c76
-rw-r--r--drivers/gaudin/gadc/gaudin_lld.mk5
-rw-r--r--drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h60
-rw-r--r--drivers/gaudin/gadc/gaudin_lld_config.h79
-rw-r--r--include/gadc/gadc.h34
-rw-r--r--include/gaudin/gaudin.h350
-rw-r--r--include/gaudin/lld/gaudin_lld.h105
-rw-r--r--include/gfx.h340
-rw-r--r--include/gfx_rules.h11
-rw-r--r--include/gmisc/gmisc.h214
-rw-r--r--src/gadc/gadc.c11
-rw-r--r--src/gaudin/gaudin.c196
-rw-r--r--src/gevent/gevent.c394
-rw-r--r--src/gwin/gwin.c1090
20 files changed, 2192 insertions, 1237 deletions
diff --git a/demos/modules/gaudin/gfxconf.h b/demos/modules/gaudin/gfxconf.h
new file mode 100644
index 00000000..4222acb4
--- /dev/null
+++ b/demos/modules/gaudin/gfxconf.h
@@ -0,0 +1,105 @@
+/**
+ * This file has a different license to the rest of the GFX system.
+ * You can copy, modify and distribute this file as you see fit.
+ * You do not need to publish your source modifications to this file.
+ * The only thing you are not permitted to do is to relicense it
+ * under a different license.
+ */
+
+/**
+ * Copy this file into your project directory and rename it as gfxconf.h
+ * Edit your copy to turn on the GFX features you want to use.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_TDISP FALSE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT FALSE
+#define GFX_USE_GADC TRUE
+#define GFX_USE_GAUDIN TRUE
+#define GFX_USE_GAUDOUT FALSE
+#define GFX_USE_GMISC FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT FALSE
+#define GDISP_NEED_CIRCLE FALSE
+#define GDISP_NEED_ELLIPSE FALSE
+#define GDISP_NEED_ARC FALSE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL FALSE
+#define GDISP_NEED_MULTITHREAD TRUE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* GDISP - builtin fonts */
+#define GDISP_OLD_FONT_DEFINITIONS FALSE
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 FALSE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* Features for the TDISP subsystem. */
+#define TDISP_NEED_MULTITHREAD FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_BUTTON FALSE
+#define GWIN_NEED_CONSOLE FALSE
+#define GWIN_NEED_GRAPH FALSE
+
+/* Features for the GEVENT sub-system. */
+#define GEVENT_ASSERT_NO_RESOURCE FALSE
+
+/* Features for the GTIMER sub-system. */
+/* NONE */
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE FALSE
+#define GINPUT_NEED_KEYBOARD FALSE
+#define GINPUT_NEED_TOGGLE FALSE
+#define GINPUT_NEED_DIAL FALSE
+
+/* Features for the GADC sub-system. */
+/* NONE */
+
+/* Features for the GAUDIN sub-system. */
+/* NONE */
+
+/* Features for the GAUDOUT sub-system. */
+/* NONE */
+
+/* Features for the GMISC sub-system. */
+#define GMISC_NEED_ARRAYOPS FALSE
+
+/* Optional Parameters for various sub-systems */
+/*
+ #define GDISP_MAX_FONT_HEIGHT 16
+ #define GEVENT_MAXIMUM_SIZE 32
+ #define GEVENT_MAX_SOURCE_LISTENERS 32
+ #define GTIMER_THREAD_WORKAREA_SIZE 512
+ #define GADC_MAX_LOWSPEED_DEVICES 4
+*/
+
+/* Optional Low Level Driver Definitions */
+/*
+ #define GDISP_USE_CUSTOM_BOARD FALSE
+ #define GDISP_SCREEN_WIDTH 320
+ #define GDISP_SCREEN_HEIGHT 240
+ #define GDISP_USE_FSMC
+ #define GDISP_USE_GPIO
+ #define GDISP_VMT_NAME1(x) x##YourDriver1
+ #define GDISP_VMT_NAME2(x) x##YourDriver2
+ #define TDISP_COLUMNS 16
+ #define TDISP_ROWS 2
+*/
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gaudin/gwinosc.c b/demos/modules/gaudin/gwinosc.c
new file mode 100644
index 00000000..a5de7e38
--- /dev/null
+++ b/demos/modules/gaudin/gwinosc.c
@@ -0,0 +1,190 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * --------------------------- Our Custom GWIN Oscilloscope ---------------
+ *
+ * This GWIN superset implements a simple audio oscilloscope using the GAUDIN module.
+ *
+ * It makes many assumptions, the most fundamental of which is that the audio device
+ * produces unsigned integer samples.
+ *
+ * The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
+ * correctly if we were really building something generic.
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "gwinosc.h"
+
+/* Include internal GWIN routines so we can build our own superset class */
+#include "gwin/internal.h"
+
+/* Our GWIN identifier */
+#define GW_SCOPE (GW_FIRST_USER_WINDOW+0)
+
+/* The size of our dynamically allocated audio buffer */
+#define AUDIOBUFSZ 64*2
+
+/* How many flat-line sample before we trigger */
+#define FLATLINE_SAMPLES 8
+
+GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint16_t channel, uint32_t frequency) {
+ /* Initialise the base class GWIN */
+ if (!(gs = (GScopeObject *)_gwinInit((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
+ return 0;
+
+ /* Initialise the scope object members and allocate memory for buffers */
+ gs->gwin.type = GW_SCOPE;
+ chBSemInit(&gs->bsem, TRUE);
+ gs->nextx = 0;
+ if (!(gs->lastscopetrace = (coord_t *)chHeapAlloc(NULL, gs->gwin.width * sizeof(coord_t))))
+ return 0;
+ if (!(gs->audiobuf = (adcsample_t *)chHeapAlloc(NULL, AUDIOBUFSZ * sizeof(adcsample_t))))
+ return 0;
+#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ gs->lasty = gs->gwin.height/2;
+#elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ gs->lasty = gs->gwin.height/2;
+ gs->scopemin = 0;
+#endif
+
+ /* Start the GADC high speed converter */
+ gaudinInit(channel, frequency, gs->audiobuf, AUDIOBUFSZ, AUDIOBUFSZ/2);
+ gaudinSetBSem(&gs->bsem, &gs->myEvent);
+ gaudinStart();
+
+ return (GHandle)gs;
+}
+
+void gwinWaitForScopeTrace(GHandle gh) {
+ #define gs ((GScopeObject *)(gh))
+ int i;
+ coord_t x, y;
+ coord_t yoffset;
+ audin_sample_t *pa;
+ coord_t *pc;
+#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ bool_t rdytrigger;
+ int flsamples;
+#elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ bool_t rdytrigger;
+ int flsamples;
+ coord_t scopemin;
+#endif
+
+ /* Wait for a set of audio conversions */
+ chBSemWait(&gs->bsem);
+
+ /* Ensure we are drawing in the right area */
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+
+ yoffset = gh->height/2 + (1<<SCOPE_Y_BITS)/2;
+ x = gs->nextx;
+ pc = gs->lastscopetrace+x;
+ pa = gs->myEvent.buffer;
+#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ rdytrigger = FALSE;
+ flsamples = 0;
+#elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ rdytrigger = FALSE;
+ flsamples = 0;
+ scopemin = 0;
+#endif
+
+ for(i = gs->myEvent.count; i; i--) {
+
+ /* Calculate the new scope value - re-scale using simple shifts for efficiency, re-center and y-invert */
+ #if GAUDIN_BITS_PER_SAMPLE > SCOPE_Y_BITS
+ y = yoffset - (*pa++ >> (GAUDIN_BITS_PER_SAMPLE - SCOPE_Y_BITS));
+ #else
+ y = yoffset - (*pa++ << (SCOPE_Y_BITS - GAUDIN_BITS_PER_SAMPLE));
+ #endif
+
+#if TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Calculate the scopemin ready for the next trace */
+ if (y > scopemin)
+ scopemin = y;
+#endif
+
+ /* Have we reached the end of a scope trace? */
+ if (x >= gh->width) {
+
+#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */
+
+ #if TRIGGER_METHOD == TRIGGER_MINVALUE
+ /* Arm when we reach the sample minimum (y value maximum) of the previous trace */
+ if (!rdytrigger && y >= gs->scopemin)
+ rdytrigger = TRUE;
+ #endif
+
+ if (y == gs->lasty) {
+ /* Trigger if we get too many flat-line samples regardless of the armed state */
+ if (++flsamples < FLATLINE_SAMPLES)
+ continue;
+ flsamples = 0;
+ } else if (y > gs->lasty) {
+ gs->lasty = y;
+ flsamples = 0;
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ /* Arm the trigger when samples fall (y increases) ie. negative slope */
+ rdytrigger = TRUE;
+ #endif
+ continue;
+ } else {
+ /* If the trigger is armed, Trigger when samples increases (y decreases) ie. positive slope */
+ gs->lasty = y;
+ flsamples = 0;
+ if (!rdytrigger)
+ continue;
+ }
+
+ /* Ready for a the next trigger cycle */
+ rdytrigger = FALSE;
+#endif
+
+ /* Prepare for a scope trace */
+ x = 0;
+ pc = gs->lastscopetrace;
+ }
+
+ /* Clear the old scope pixel and then draw the new scope value */
+ gdispDrawPixel(gh->x+x, gh->y+pc[0], gh->bgcolor);
+ gdispDrawPixel(gh->x+x, gh->y+y, gh->color);
+
+ /* Save the value */
+ *pc++ = y;
+ x++;
+ #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
+ gs->lasty = y;
+ #endif
+ }
+ gs->nextx = x;
+#if TRIGGER_METHOD == TRIGGER_MINVALUE
+ gs->scopemin = scopemin;
+#endif
+
+ #undef gs
+}
diff --git a/demos/modules/gaudin/gwinosc.h b/demos/modules/gaudin/gwinosc.h
new file mode 100644
index 00000000..08244717
--- /dev/null
+++ b/demos/modules/gaudin/gwinosc.h
@@ -0,0 +1,95 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _GWINOSC_H
+#define _GWINOSC_H
+
+/**
+ * --------------------------- Our Custom GWIN Oscilloscope ---------------
+ *
+ * This GWIN superset implements a simple audio oscilloscope using the GADC high speed device.
+ *
+ * It makes many assumptions, the most fundamental of which is that the audio device
+ * produces unsigned integer samples.
+ *
+ * The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
+ * correctly if we were really building something generic.
+ */
+
+/* The extent of scaling for our audio data - fixed scale at the moment */
+#ifndef SCOPE_Y_BITS
+ #define SCOPE_Y_BITS 8 // 8 bits = 0..255
+#endif
+
+/* Trigger methods */
+#define TRIGGER_NONE 0 /* No triggering */
+#define TRIGGER_POSITIVERAMP 1 /* Trigger on a positive going signal */
+#define TRIGGER_MINVALUE 2 /* Trigger on reaching the minimum value from the last scope */
+
+/**
+ * Which trigger we want to use.
+ * Experiments suggests that TRIGGER_MINVALUE gives the best result
+ */
+#ifndef TRIGGER_METHOD
+ #define TRIGGER_METHOD TRIGGER_MINVALUE
+#endif
+
+/* A scope window object. Treat it as a black box */
+typedef struct GScopeObject_t {
+ GWindowObject gwin; // Base Class
+
+ coord_t *lastscopetrace; // To store last scope trace
+ BinarySemaphore bsem; // We get signalled on this
+ audin_sample_t *audiobuf; // To store audio samples
+ GEventAudioIn myEvent; // Information on received samples
+ coord_t nextx; // Where we are up to
+#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
+ coord_t lasty; // The last y value - used for trigger slope detection
+#elif TRIGGER_METHOD == TRIGGER_MINVALUE
+ coord_t lasty; // The last y value - used for trigger slope detection
+ coord_t scopemin; // The last scopes minimum value
+#endif
+ } GScopeObject;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Create a scope window.
+ */
+ GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint16_t channel, uint32_t frequency);
+
+ /**
+ * Wait for a scope trace to be ready and then draw it.
+ */
+ void gwinWaitForScopeTrace(GHandle gh);
+
+ /**
+ * We should also have a special destroy routine here as we have dynamically
+ * allocated some memory. There is no point implementing this however as, for
+ * this demo, we never destroy the window.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GWINOSC_H */
diff --git a/demos/modules/gaudin/main.c b/demos/modules/gaudin/main.c
new file mode 100644
index 00000000..7ca8d228
--- /dev/null
+++ b/demos/modules/gaudin/main.c
@@ -0,0 +1,67 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * This demo demonstrates the use of the GAUDIN module to read audio channel 0.
+ * The audio channel gets read to display a very simple oscilloscope.
+ *
+ * It also demonstrates how to write your own custom GWIN window type.
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+/* Include our custom gwin audio oscilloscope */
+#include "gwinosc.h"
+
+/* Specify our timing parameters */
+#define MY_AUDIO_FREQUENCY 4000 /* 4khz */
+#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
+
+/* Data */
+static GScopeObject gScopeWindow;
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+ GHandle ghScope;
+ coord_t swidth, sheight;
+
+ halInit();
+ chSysInit();
+ gdispInit();
+ gdispClear(Black);
+
+ /* Get the screen dimensions */
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+
+ /* Set up the scope window to fill the screen */
+ ghScope = gwinCreateScope(&gScopeWindow, 0, 0, swidth, sheight, MY_AUDIO_CHANNEL, MY_AUDIO_FREQUENCY);
+ gwinSetBgColor(ghScope, White);
+ gwinSetColor(ghScope, Red);
+ gwinClear(ghScope);
+
+ /* Just keep displaying the scope traces */
+ while (TRUE) {
+ gwinWaitForScopeTrace(ghScope);
+ }
+}
diff --git a/demos/modules/gaudin/results_264x264.jpg b/demos/modules/gaudin/results_264x264.jpg
new file mode 100644
index 00000000..461d963b
--- /dev/null
+++ b/demos/modules/gaudin/results_264x264.jpg
Binary files differ
diff --git a/drivers/gadc/AT91SAM7/gadc_lld_config.h b/drivers/gadc/AT91SAM7/gadc_lld_config.h
index 882573c8..8ba71f20 100644
--- a/drivers/gadc/AT91SAM7/gadc_lld_config.h
+++ b/drivers/gadc/AT91SAM7/gadc_lld_config.h
@@ -60,6 +60,11 @@
*/
#define GADC_BITS_PER_SAMPLE AT91_ADC1_RESOLUTION
+/**
+ * @brief The sample format
+ */
+#define GADC_SAMPLE_FORMAT ARRAY_DATA_10BITUNSIGNED
+
/* Pull in board specific defines */
#if defined(GADC_USE_CUSTOM_BOARD) && GADC_USE_CUSTOM_BOARD
/* Include the user supplied board definitions */
@@ -73,6 +78,6 @@
#endif /* GFX_USE_GADC */
-#endif /* _GDISP_LLD_CONFIG_H */
+#endif /* GADC_LLD_CONFIG_H */
/** @} */
diff --git a/drivers/gaudin/gadc/gaudin_lld.c b/drivers/gaudin/gadc/gaudin_lld.c
new file mode 100644
index 00000000..12e6aced
--- /dev/null
+++ b/drivers/gaudin/gadc/gaudin_lld.c
@@ -0,0 +1,76 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file drivers/gaudin/gadc/gaudin.c
+ * @brief GAUDIN - Driver file for using the cpu ADC (via GADC).
+ *
+ * @addtogroup GAUDIN
+ *
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+
+/**
+ * We are now implementing the driver - pull in our channel table
+ * from the board definitions.
+ */
+#define GAUDIN_LLD_IMPLEMENTATION
+
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIN
+
+/* Double check the GADC system is turned on */
+#if !GFX_USE_GADC
+ #error "GAUDIN - The GADC driver for GAUDIN requires GFX_USE_GADC to be TRUE"
+#endif
+
+/* Include the driver defines */
+#include "gaudin/lld/gaudin_lld.h"
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+void gaudin_lld_init(const gaudin_params *paud) {
+ /* Setup the high speed GADC */
+ gadcHighSpeedInit(gaudin_lld_physdevs[paud->channel], paud->frequency, paud->buffer, paud->bufcount, paud->samplesPerEvent);
+
+ /* Register ourselves for ISR callbacks */
+ gadcHighSpeedSetISRCallback(GAUDIN_ISR_CompleteI);
+
+ /**
+ * The gadc driver handles any errors for us by restarting the transaction so there is
+ * no need for us to setup anything for GAUDIN_ISR_ErrorI()
+ */
+}
+
+void gadc_lld_start(void) {
+ gadcHighSpeedStart();
+}
+
+void gadc_lld_stop(void) {
+ gadcHighSpeedStop();
+}
+
+#endif /* GFX_USE_GAUDIN */
+/** @} */
diff --git a/drivers/gaudin/gadc/gaudin_lld.mk b/drivers/gaudin/gadc/gaudin_lld.mk
new file mode 100644
index 00000000..c969e80b
--- /dev/null
+++ b/drivers/gaudin/gadc/gaudin_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gaudin/gadc
diff --git a/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h b/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
new file mode 100644
index 00000000..283a2914
--- /dev/null
+++ b/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
@@ -0,0 +1,60 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
+ * @brief GAUDIN Driver board config file for the Olimex SAM7EX256 board
+ *
+ * @addtogroup GAUDIN
+ * @{
+ */
+
+#ifndef _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H
+#define _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H
+
+/*===========================================================================*/
+/* Audio inputs on this board */
+/*===========================================================================*/
+
+/**
+ * @brief The number of audio channels supported by this driver
+ */
+#define GAUDIN_NUM_CHANNELS 1
+
+/**
+ * @brief The list of audio channels and their uses
+ * @{
+ */
+#define GAUDIN_MICROPHONE 0
+/** @} */
+
+/**
+ * @brief The following defines are for the low level driver use only
+ * @{
+ */
+#ifdef GAUDIN_LLD_IMPLEMENTATION
+ static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
+ GADC_PHYSDEV_MICROPHONE,
+ };
+#endif
+/** @} */
+
+#endif /* _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H */
+/** @} */
diff --git a/drivers/gaudin/gadc/gaudin_lld_config.h b/drivers/gaudin/gadc/gaudin_lld_config.h
new file mode 100644
index 00000000..402e4180
--- /dev/null
+++ b/drivers/gaudin/gadc/gaudin_lld_config.h
@@ -0,0 +1,79 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file drivers/gaudin/gadc/gaudin_lld_config.h
+ * @brief GAUDIN Driver config file.
+ *
+ * @addtogroup GAUDIN
+ * @{
+ */
+
+#ifndef GAUDIN_LLD_CONFIG_H
+#define GAUDIN_LLD_CONFIG_H
+
+#if GFX_USE_GAUDIN
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+/**
+ * @brief The audio input sample type
+ * @details For this driver it matches the cpu sample type
+ */
+typedef adcsample_t audin_sample_t;
+
+/**
+ * @brief The maximum sample frequency supported by this audio device
+ * @details For this driver it matches the GADC maximum high speed sample rate
+ */
+#define GAUDIN_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE
+
+/**
+ * @brief The number of bits in a sample
+ * @details For this driver it matches the cpu sample bits
+ */
+#define GAUDIN_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE
+
+/**
+ * @brief The format of an audio sample
+ * @details For this driver it matches the cpu sample format
+ */
+#define GAUDIN_SAMPLE_FORMAT GADC_SAMPLE_FORMAT
+
+/**
+ * For the GAUDIN driver that uses GADC - all the remaining config definitions are specific
+ * to the board.
+ */
+#if defined(GADC_USE_CUSTOM_BOARD) && GADC_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gaudin_lld_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+ #include "gaudin_lld_board_olimexsam7ex256.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "gaudin_lld_board.h"
+#endif
+
+#endif /* GFX_USE_GAUDIN */
+
+#endif /* GAUDIN_LLD_CONFIG_H */
+/** @} */
diff --git a/include/gadc/gadc.h b/include/gadc/gadc.h
index be7af516..bd35b30c 100644
--- a/include/gadc/gadc.h
+++ b/include/gadc/gadc.h
@@ -96,10 +96,15 @@ typedef struct GEventADC_t {
} GEventADC;
/**
- * @brief A callback function (executed in a thread context)
+ * @brief A callback function (executed in a thread context) for a low speed conversion
*/
typedef void (*GADCCallbackFunction)(adcsample_t *buffer, void *param);
+/**
+ * @brief A callback function (executed in an ISR context) for a high speed conversion
+ */
+typedef void (*GADCISRCallbackFunction)(adcsample_t *buffer, size_t size);
+
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@@ -121,9 +126,9 @@ extern "C" {
* @note If the high speed ADC is running it will be stopped. The Event subsystem is
* disconnected from the high speed ADC and any binary semaphore event is forgotten.
* @note bufcount must be greater than countPerEvent (usually 2 or more times) otherwise
- * the buffer will be overwitten with new data while the application is still trying
+ * the buffer will be overwritten with new data while the application is still trying
* to process the old data.
- * @note Due to a bug in Chibi-OS countPerEvent must be even. If bufcount is not
+ * @note Due to a bug/feature in Chibi-OS countPerEvent must be even. If bufcount is not
* evenly divisable by countPerEvent, the remainder must also be even.
* @note The physdev parameter may be used to turn on more than one ADC channel.
* Each channel is then interleaved into the provided buffer. Note 'bufcount'
@@ -143,8 +148,7 @@ extern "C" {
* @note While the high speed ADC is running, low speed conversions can only occur at
* the frequency of the high speed events. Thus if high speed events are
* being created at 50Hz (eg countPerEvent = 100, frequency = 5kHz) then the maximum
- * frequency for low speed conversions is likely to be 50Hz (although it might be
- * 100Hz on some hardware).
+ * frequency for low speed conversions will be 50Hz.
*
* @api
*/
@@ -159,8 +163,8 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer
* called first. This saves processing time if the application does
* not want to use the GEVENT sub-system for the high speed ADC.
* Once turned on it can only be turned off by calling @p gadcHighSpeedInit() again.
- * @note The high speed ADC is capable of signalling via this method and a binary semaphore
- * at the same time.
+ * @note The high speed ADC is capable of signalling via this method, an ISR callback and a
+ * binary semaphore at the same time.
*
* @api
*/
@@ -168,6 +172,20 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer
#endif
/**
+ * @brief Allow retrieving of results from the high speed ADC using an ISR callback.
+ *
+ * @param[in] isrfn The callback function (called in an ISR context).
+ *
+ * @note Passing a NULL for isrfn will turn off signalling via this method as will calling
+ * @p gadcHighSpeedInit().
+ * @note The high speed ADC is capable of signalling via this method, a binary semaphore and the GEVENT
+ * sub-system at the same time.
+ *
+ * @api
+ */
+void gadcHighSpeedSetISRCallback(GADCISRCallbackFunction isrfn);
+
+/**
* @brief Allow retrieving of results from the high speed ADC using a Binary Semaphore and a static event buffer.
*
* @param[in] pbsem The binary semaphore is signaled when data is available.
@@ -175,7 +193,7 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer
*
* @note Passing a NULL for pbsem or pEvent will turn off signalling via this method as will calling
* @p gadcHighSpeedInit().
- * @note The high speed ADC is capable of signalling via this method and the GEVENT
+ * @note The high speed ADC is capable of signalling via this method, an ISR callback and the GEVENT
* sub-system at the same time.
*
* @api
diff --git a/include/gaudin/gaudin.h b/include/gaudin/gaudin.h
index 6f35ba19..8c5d658a 100644
--- a/include/gaudin/gaudin.h
+++ b/include/gaudin/gaudin.h
@@ -1,170 +1,180 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file include/gaudin/gaudin.h
- * @brief GAUDIN - Audio Input subsystem header file.
- *
- * @addtogroup GAUDIN
- *
- * @{
- */
-
-#ifndef _GAUDIN_H
-#define _GAUDIN_H
-
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
-
-/* Include the driver defines */
-#include "gaudin_lld_config.h"
-//audio_in_sample_t
-//GAUDIN_SAMPLE_FORMAT ARRAY_DATA_10BITUNSIGNED
-//GAUDIN_STEREO_DEVICE FALSE
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-// Event types for GAUDIN
-#define GEVENT_AUDIO_IN (GEVENT_GAUDIN_FIRST+0)
-
-/**
- * @brief The Audio Input event structure.
- * @{
- */
-typedef struct GEventAudioIn_t {
- /**
- * @brief The type of this event (GEVENT_AUDIO_IN)
- */
- GEventType type;
- /**
- * @brief The event flags
- */
- uint16_t flags;
- /**
- * @brief The event flag values.
- * @{
- */
- #define GADC_AUDIO_IN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
- /** @} */
- /**
- * @brief The number of audio samples in the buffer
- */
- size_t count;
- /**
- * @brief The buffer containing the audio samples
- */
- audio_in_sample_t *buffer;
- } GEventAudioIn;
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Initialise the Audio Input Subsystem.
- * @details Initialises but does not start the audio in.
- *
- * @param[in] frequency The sample frequency
- * @param[in] buffer The static buffer to put the samples into.
- * @param[in] bufcount The total number of conversions that will fit in the buffer.
- * @param[in] countPerEvent The number of conversions to do before returning an event.
- *
- * @note If the audio input is running it will be stopped.
- * @note Due to a bug in Chibi-OS countPerEvent must be even for the GADC audio driver.
- * If bufcount is not evenly divisable by countPerEvent, the remainder must also be even.
- * This requirement may not apply to other GAUDIN drivers.
- * @note The number of samples for stereo devices will be double the number of conversions.
- * Make sure you allocate your buffers large enough. Each channel is then interleaved
- * into the provided buffer. Note 'bufcount' and 'countPerEvent' parameters describe the
- * number of conversions not the number of samples.
- * @note The buffer is circular. When the end of the buffer is reached it will start
- * putting data into the beginning of the buffer again.
- * @note The event listener must process the event (and the data in it) before the
- * next event occurs. If not, the following event will be lost.
- * @note If bufcount is evenly divisable by countPerEvent, then every event will return
- * countPerEvent conversions. If bufcount is not evenly divisable, it will return
- * a block of samples containing less than countPerEvent samples when it reaches the
- * end of the buffer.
- *
- * @api
- */
-void gaudinInit(uint32_t frequency, adcsample_t *buffer, size_t bufcount, size_t samplesPerEvent);
-
-#if GFX_USE_GEVENT || defined(__DOXYGEN__)
- /**
- * @brief Turn on sending results to the GEVENT sub-system.
- * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_IN events.
- *
- * @note The audio input will not use the GEVENT system unless this is
- * called first. This saves processing time if the application does
- * not want to use the GEVENT sub-system for audio input.
- * Once turned on it cannot be turned off.
- * @note The audio input is capable of signalling via this method and a binary semaphore
- * at the same time.
- *
- * @api
- */
- GSourceHandle gaudinGetSource(void);
-#endif
-
-/**
- * @brief Allow retrieving of results from the audio input using a Binary Semaphore and a static event buffer.
- *
- * @param[in] pbsem The binary semaphore is signaled when data is available.
- * @param[in] pEvent The static event buffer to place the result information.
- *
- * @note Passing a NULL for pbsem or pEvent will turn off signalling via this method.
- * @note The audio input is capable of signalling via this method and the GEVENT
- * sub-system at the same time.
- *
- * @api
- */
-void gaudinSetBSem(BinarySemaphore *pbsem, GEventAudioIn *pEvent);
-
-/**
- * @brief Start the audio input conversions.
- * @pre It must have been initialised first with @p gaudinInit()
- *
- * @api
- */
-GSourceHandle gaudinStart(void);
-
-/**
- * @brief Stop the audio input conversions.
- *
- * @api
- */
-void gaudinStop(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_GAUDIN */
-
-#endif /* _GAUDIN_H */
-/** @} */
-
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file include/gaudin/gaudin.h
+ * @brief GAUDIN - Audio Input subsystem header file.
+ *
+ * @addtogroup GAUDIN
+ *
+ * @{
+ */
+
+#ifndef _GAUDIN_H
+#define _GAUDIN_H
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
+
+/* Include the driver defines */
+#include "gaudin_lld_config.h"
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+// Event types for GAUDIN
+#define GEVENT_AUDIO_IN (GEVENT_GAUDIN_FIRST+0)
+
+/**
+ * @brief The Audio Input event structure.
+ * @{
+ */
+typedef struct GEventAudioIn_t {
+ #if GFX_USE_GEVENT || defined(__DOXYGEN__)
+ /**
+ * @brief The type of this event (GEVENT_AUDIO_IN)
+ */
+ GEventType type;
+ #endif
+ /**
+ * @brief The current channel
+ */
+ uint16_t channel;
+ /**
+ * @brief The event flags
+ */
+ uint16_t flags;
+ /**
+ * @brief The event flag values.
+ * @{
+ */
+ #define GADC_AUDIO_IN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
+ /** @} */
+ /**
+ * @brief The number of audio samples in the buffer
+ */
+ size_t count;
+ /**
+ * @brief The buffer containing the audio samples
+ */
+ audin_sample_t *buffer;
+ } GEventAudioIn;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise (but not start) the Audio Input Subsystem.
+ * @details Returns FALSE for an invalid channel or other invalid parameter.
+ *
+ * @param[in] channel The channel to convert. Can be set from 0 to GAUDIN_NUM_CHANNELS - 1.
+ * @param[in] frequency The sample frequency
+ * @param[in] buffer The static buffer to put the samples into.
+ * @param[in] bufcount The total number of conversions that will fit in the buffer.
+ * @param[in] countPerEvent The number of conversions to do before returning an event.
+ *
+ * @note Only one channel is active at a time. If an audio input is running it will be stopped.
+ * The Event subsystem is disconnected from the audio subsystem and any binary semaphore
+ * event is forgotten.
+ * @note Some channels may be stereo channels which return twice as much sample data with
+ * the left and right channel data interleaved. Other channels may be mono channels.
+ * Where stereo channels exist it would be common for the low level driver to also
+ * offer the left and right channels separately.
+ * @note Due to a bug in Chibi-OS countPerEvent must be even if using the GADC low level audio driver.
+ * If bufcount is not evenly divisable by countPerEvent, the remainder must also be even.
+ * This requirement may not apply to other GAUDIN drivers.
+ * @note The number of samples for stereo devices will be double the number of conversions.
+ * Make sure you allocate your buffers large enough. Each channel is then interleaved
+ * into the provided buffer. Note 'bufcount' and 'countPerEvent' parameters describe the
+ * number of conversions not the number of samples.
+ * @note The buffer is circular. When the end of the buffer is reached it will start
+ * putting data into the beginning of the buffer again.
+ * @note The event listener must process the event (and the data in it) before the
+ * next event occurs. If not, the following event will be lost.
+ * @note If bufcount is evenly divisable by countPerEvent, then every event will return
+ * countPerEvent conversions. If bufcount is not evenly divisable, it will return
+ * a block of samples containing less than countPerEvent samples when it reaches the
+ * end of the buffer.
+ *
+ * @api
+ */
+bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent);
+
+#if GFX_USE_GEVENT || defined(__DOXYGEN__)
+ /**
+ * @brief Turn on sending results to the GEVENT sub-system.
+ * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_IN events.
+ *
+ * @note The audio input will not use the GEVENT system unless this is
+ * called first. This saves processing time if the application does
+ * not want to use the GEVENT sub-system for audio input.
+ * Once turned on it can only be turned off by calling @p gadcHighSpeedInit() again.
+ * @note The audio input is capable of signalling via this method and a binary semaphore
+ * at the same time.
+ *
+ * @api
+ */
+ GSourceHandle gaudinGetSource(void);
+#endif
+
+/**
+ * @brief Allow retrieving of results from the audio input using a Binary Semaphore and a static event buffer.
+ *
+ * @param[in] pbsem The binary semaphore is signaled when data is available.
+ * @param[in] pEvent The static event buffer to place the result information.
+ *
+ * @note Passing a NULL for pbsem or pEvent will turn off signalling via this method.
+ * @note The audio input is capable of signalling via this method and the GEVENT
+ * sub-system at the same time.
+ *
+ * @api
+ */
+void gaudinSetBSem(BinarySemaphore *pbsem, GEventAudioIn *pEvent);
+
+/**
+ * @brief Start the audio input conversions.
+ * @pre It must have been initialised first with @p gaudinInit()
+ *
+ * @api
+ */
+void gaudinStart(void);
+
+/**
+ * @brief Stop the audio input conversions.
+ *
+ * @api
+ */
+void gaudinStop(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GAUDIN */
+
+#endif /* _GAUDIN_H */
+/** @} */
+
diff --git a/include/gaudin/lld/gaudin_lld.h b/include/gaudin/lld/gaudin_lld.h
new file mode 100644
index 00000000..2b2db86e
--- /dev/null
+++ b/include/gaudin/lld/gaudin_lld.h
@@ -0,0 +1,105 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file include/gaudin/lld/gaudin_lld.h
+ * @brief GAUDIN - Audio Input driver header file.
+ *
+ * @defgroup Driver Driver
+ * @ingroup GAUDIN
+ * @{
+ */
+
+#ifndef _GAUDIN_LLD_H
+#define _GAUDIN_LLD_H
+
+#include "gfx.h"
+
+#if GFX_USE_GADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/**
+ * @brief The structure passed to start a audio conversion
+ * @note We use the structure instead of parameters purely to save
+ * interrupt stack space which is very limited in some platforms.
+ * @{
+ */
+typedef struct gaudin_params_t {
+ uint16_t channel;
+ uint32_t frequency;
+ audin_sample_t *buffer;
+ size_t bufcount;
+ size_t samplesPerEvent;
+ } gaudin_params;
+/* @} */
+
+/**
+ * @brief These routines are the callbacks that the driver uses.
+ * @details Defined in the high level GAUDIN code.
+ *
+ * @icode
+ * @notapi
+ * @{
+ */
+extern void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n);
+extern void GAUDIN_ISR_ErrorI(void);
+/**
+ * @}
+ */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise the driver
+ *
+ * @api
+ */
+void gaudin_lld_init(const gaudin_params *paud);
+
+/**
+ * @brief Start the audio input sampling
+ *
+ * @api
+ */
+void gadc_lld_start(void);
+
+/**
+ * @brief Stop the audio input sampling
+ *
+ * @api
+ */
+void gadc_lld_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GADC */
+
+#endif /* _GADC_LLD_H */
+/** @} */
diff --git a/include/gfx.h b/include/gfx.h
index 552e3294..e6b8d03e 100644
--- a/include/gfx.h
+++ b/include/gfx.h
@@ -1,170 +1,170 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file include/gfx.h
- * @brief GFX system header file.
- *
- * @addtogroup GFX
- * @{
- */
-
-#ifndef _GFX_H
-#define _GFX_H
-
-/* gfxconf.h is the user's project configuration for the GFX system. */
-#include "gfxconf.h"
-
-/**
- * @name GFX sub-systems that can be turned on
- * @{
- */
- /**
- * @brief GFX Graphics Display Basic API
- * @details Defaults to FALSE
- * @note Also add the specific hardware driver to your makefile.
- * Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/gdisp_lld.mk
- */
- #ifndef GFX_USE_GDISP
- #define GFX_USE_GDISP FALSE
- #endif
- /**
- * @brief GFX Text Display Basic API
- * @details Defaults to FALSE
- * @note Also add the specific hardware driver to your makefile.
- * Eg. include $(GFXLIB)/drivers/tdisp/HD44780/tdisp_lld.mk
- */
- #ifndef GFX_USE_TDISP
- #define GFX_USE_TDISP FALSE
- #endif
- /**
- * @brief GFX Graphics Windowing API
- * @details Defaults to FALSE
- * @details Extends the GDISP API to add the concept of graphic windows.
- * @note Also supports high-level "window" objects such as console windows,
- * buttons, graphing etc
- */
- #ifndef GFX_USE_GWIN
- #define GFX_USE_GWIN FALSE
- #endif
- /**
- * @brief GFX Event API
- * @details Defaults to FALSE
- * @details Defines the concept of a "Source" that can send "Events" to "Listeners".
- */
- #ifndef GFX_USE_GEVENT
- #define GFX_USE_GEVENT FALSE
- #endif
- /**
- * @brief GFX Timer API
- * @details Defaults to FALSE
- * @details Provides thread context timers - both one-shot and periodic.
- */
- #ifndef GFX_USE_GTIMER
- #define GFX_USE_GTIMER FALSE
- #endif
- /**
- * @brief GFX Input Device API
- * @details Defaults to FALSE
- * @note Also add the specific hardware drivers to your makefile.
- * Eg.
- * include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
- * and...
- * include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
- */
- #ifndef GFX_USE_GINPUT
- #define GFX_USE_GINPUT FALSE
- #endif
- /**
- * @brief GFX Generic Periodic ADC API
- * @details Defaults to FALSE
- */
- #ifndef GFX_USE_GADC
- #define GFX_USE_GADC FALSE
- #endif
- /**
- * @brief GFX Audio Input Device API
- * @details Defaults to FALSE
- * @note Also add the specific hardware drivers to your makefile.
- * Eg.
- * include $(GFXLIB)/drivers/gaudin/GADC/gaudin_lld.mk
- */
- #ifndef GFX_USE_GAUDIN
- #define GFX_USE_GAUDIN FALSE
- #endif
- /**
- * @brief GFX Audio Output Device API
- * @details Defaults to FALSE
- * @note Also add the specific hardware drivers to your makefile.
- * Eg.
- * include $(GFXLIB)/drivers/gaudout/PWM/gaudout_lld.mk
- */
- #ifndef GFX_USE_GAUDOUT
- #define GFX_USE_GAUDOUT FALSE
- #endif
- /**
- * @brief GFX Miscellaneous Routines API
- * @details Defaults to FALSE
- * @note Turning this on without turning on any GMISC_NEED_xxx macros will result
- * in no extra code being compiled in. GMISC is made up from the sum of its
- * parts.
- */
- #ifndef GFX_USE_GMISC
- #define GFX_USE_GMISC FALSE
- #endif
-/** @} */
-
-/**
- * Get all the options for each sub-system.
- *
- */
-#include "gmisc/options.h"
-#include "gevent/options.h"
-#include "gtimer/options.h"
-#include "gdisp/options.h"
-#include "gwin/options.h"
-#include "ginput/options.h"
-#include "tdisp/options.h"
-#include "gadc/options.h"
-#include "gaudin/options.h"
-#include "gaudout/options.h"
-
-/**
- * Inter-dependancy safety checks on the sub-systems.
- *
- */
-#include "gfx_rules.h"
-
-/**
- * Include the sub-system header files
- */
-#include "gevent/gevent.h"
-#include "gtimer/gtimer.h"
-#include "gdisp/gdisp.h"
-#include "gwin/gwin.h"
-#include "ginput/ginput.h"
-#include "tdisp/tdisp.h"
-#include "gadc/gadc.h"
-#include "gaudin/gaudin.h"
-#include "gaudout/gaudout.h"
-#include "gmisc/gmisc.h"
-
-#endif /* _GFX_H */
-/** @} */
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file include/gfx.h
+ * @brief GFX system header file.
+ *
+ * @addtogroup GFX
+ * @{
+ */
+
+#ifndef _GFX_H
+#define _GFX_H
+
+/* gfxconf.h is the user's project configuration for the GFX system. */
+#include "gfxconf.h"
+
+/**
+ * @name GFX sub-systems that can be turned on
+ * @{
+ */
+ /**
+ * @brief GFX Graphics Display Basic API
+ * @details Defaults to FALSE
+ * @note Also add the specific hardware driver to your makefile.
+ * Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/gdisp_lld.mk
+ */
+ #ifndef GFX_USE_GDISP
+ #define GFX_USE_GDISP FALSE
+ #endif
+ /**
+ * @brief GFX Text Display Basic API
+ * @details Defaults to FALSE
+ * @note Also add the specific hardware driver to your makefile.
+ * Eg. include $(GFXLIB)/drivers/tdisp/HD44780/tdisp_lld.mk
+ */
+ #ifndef GFX_USE_TDISP
+ #define GFX_USE_TDISP FALSE
+ #endif
+ /**
+ * @brief GFX Graphics Windowing API
+ * @details Defaults to FALSE
+ * @details Extends the GDISP API to add the concept of graphic windows.
+ * @note Also supports high-level "window" objects such as console windows,
+ * buttons, graphing etc
+ */
+ #ifndef GFX_USE_GWIN
+ #define GFX_USE_GWIN FALSE
+ #endif
+ /**
+ * @brief GFX Event API
+ * @details Defaults to FALSE
+ * @details Defines the concept of a "Source" that can send "Events" to "Listeners".
+ */
+ #ifndef GFX_USE_GEVENT
+ #define GFX_USE_GEVENT FALSE
+ #endif
+ /**
+ * @brief GFX Timer API
+ * @details Defaults to FALSE
+ * @details Provides thread context timers - both one-shot and periodic.
+ */
+ #ifndef GFX_USE_GTIMER
+ #define GFX_USE_GTIMER FALSE
+ #endif
+ /**
+ * @brief GFX Input Device API
+ * @details Defaults to FALSE
+ * @note Also add the specific hardware drivers to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
+ * and...
+ * include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
+ */
+ #ifndef GFX_USE_GINPUT
+ #define GFX_USE_GINPUT FALSE
+ #endif
+ /**
+ * @brief GFX Generic Periodic ADC API
+ * @details Defaults to FALSE
+ */
+ #ifndef GFX_USE_GADC
+ #define GFX_USE_GADC FALSE
+ #endif
+ /**
+ * @brief GFX Audio Input Device API
+ * @details Defaults to FALSE
+ * @note Also add the specific hardware drivers to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/gaudin/GADC/gaudin_lld.mk
+ */
+ #ifndef GFX_USE_GAUDIN
+ #define GFX_USE_GAUDIN FALSE
+ #endif
+ /**
+ * @brief GFX Audio Output Device API
+ * @details Defaults to FALSE
+ * @note Also add the specific hardware drivers to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/gaudout/PWM/gaudout_lld.mk
+ */
+ #ifndef GFX_USE_GAUDOUT
+ #define GFX_USE_GAUDOUT FALSE
+ #endif
+ /**
+ * @brief GFX Miscellaneous Routines API
+ * @details Defaults to FALSE
+ * @note Turning this on without turning on any GMISC_NEED_xxx macros will result
+ * in no extra code being compiled in. GMISC is made up from the sum of its
+ * parts.
+ */
+ #ifndef GFX_USE_GMISC
+ #define GFX_USE_GMISC FALSE
+ #endif
+/** @} */
+
+/**
+ * Get all the options for each sub-system.
+ *
+ */
+#include "gmisc/options.h"
+#include "gevent/options.h"
+#include "gtimer/options.h"
+#include "gdisp/options.h"
+#include "gwin/options.h"
+#include "ginput/options.h"
+#include "tdisp/options.h"
+#include "gadc/options.h"
+#include "gaudin/options.h"
+#include "gaudout/options.h"
+
+/**
+ * Inter-dependancy safety checks on the sub-systems.
+ *
+ */
+#include "gfx_rules.h"
+
+/**
+ * Include the sub-system header files
+ */
+#include "gmisc/gmisc.h"
+#include "gevent/gevent.h"
+#include "gtimer/gtimer.h"
+#include "gdisp/gdisp.h"
+#include "gwin/gwin.h"
+#include "ginput/ginput.h"
+#include "tdisp/tdisp.h"
+#include "gadc/gadc.h"
+#include "gaudin/gaudin.h"
+#include "gaudout/gaudout.h"
+
+#endif /* _GFX_H */
+/** @} */
diff --git a/include/gfx_rules.h b/include/gfx_rules.h
index ce6bea50..27316204 100644
--- a/include/gfx_rules.h
+++ b/include/gfx_rules.h
@@ -99,6 +99,14 @@
#if GFX_USE_TDISP
#endif
+#if GFX_USE_GAUDIN
+ #if GFX_USE_GEVENT && !GFX_USE_GTIMER
+ #warning "GAUDIN: GFX_USE_GTIMER is required if GFX_USE_GAUDIN and GFX_USE_GEVENT are TRUE. It has been turned on for you."
+ #undef GFX_USE_GTIMER
+ #define GFX_USE_GTIMER TRUE
+ #endif
+#endif
+
#if GFX_USE_GADC
#if !CH_USE_MUTEXES || !CH_USE_SEMAPHORES
#error "GADC: CH_USE_MUTEXES and CH_USE_SEMAPHORES must be defined in chconf.h"
@@ -123,9 +131,6 @@
#endif
#endif
-#if GFX_USE_GAUDIN
-#endif
-
#if GFX_USE_GAUDOUT
#endif
diff --git a/include/gmisc/gmisc.h b/include/gmisc/gmisc.h
index c68e5ca2..b11a912b 100644
--- a/include/gmisc/gmisc.h
+++ b/include/gmisc/gmisc.h
@@ -1,106 +1,108 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file include/gmisc/gmisc.h
- * @brief GMISC - Miscellaneous Routines header file.
- *
- * @addtogroup GAUDIN
- *
- * @{
- */
-
-#ifndef _GMISC_H
-#define _GMISC_H
-
-#include "gfx.h"
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-/**
- * @brief Sample data formats
- */
-typedef enum ArrayDataFormat_e {
- ARRAY_DATA_4BITUNSIGNED = 4, ARRAY_DATA_4BITSIGNED = 5,
- ARRAY_DATA_8BITUNSIGNED = 8, ARRAY_DATA_8BITSIGNED = 9,
- ARRAY_DATA_10BITUNSIGNED = 10, ARRAY_DATA_10BITSIGNED = 11,
- ARRAY_DATA_12BITUNSIGNED = 12, ARRAY_DATA_12BITSIGNED = 13,
- ARRAY_DATA_14BITUNSIGNED = 14, ARRAY_DATA_14BITSIGNED = 15,
- ARRAY_DATA_16BITUNSIGNED = 16, ARRAY_DATA_16BITSIGNED = 17,
- } ArrayDataFormat;
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#if GFX_USE_GMISC || defined(__DOXYGEN__)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if GMISC_NEED_ARRAYOPS || defined(__DOXYGEN__)
- /**
- * @brief Convert from one array format to another array format.
- *
- * @param[in] srcfmt The format of the source array
- * @param[in] src The source array
- * @param[in] dstfmt The format of the destination array
- * @param[in] dst The dstination array
- * @param[in] cnt The number of array elements to convert
- *
- * @note Assumes the destination buffer is large enough for the resultant data.
- * @note This routine is optimised to perform as fast as possible.
- * @note No type checking is performed on the source format. It is assumed to
- * have only valid values eg. ARRAY_DATA_4BITSIGNED will have values
- * 0000 -> 0111 for positive numbers and 1111 -> 1000 for negative numbers
- * Bits 5 -> 8 in the storage byte are treated in an undefined manner.
- * @note If srcfmt or dstfmt is an unknown format, this routine does nothing
- * with no warning that something is wrong
- *
- * @api
- */
- void gmiscArrayConvert(ArrayDataFormat srcfmt, void *src, ArrayDataFormat dstfmt, void *dst, size_t cnt);
-
- #if 0
- void gmiscArrayTranslate(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int trans);
-
- void gmiscArrayMultiply(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult);
-
- void gmiscArrayDivide(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mdiv);
-
- void gmiscArrayMultDiv(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult, int div);
-
- void gmiscArrayAdd(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
-
- void gmiscArrayAddNoOverflow(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
- #endif
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_MISC */
-
-#endif /* _GMISC_H */
-/** @} */
-
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file include/gmisc/gmisc.h
+ * @brief GMISC - Miscellaneous Routines header file.
+ *
+ * @addtogroup GAUDIN
+ *
+ * @{
+ */
+
+#ifndef _GMISC_H
+#define _GMISC_H
+
+#include "gfx.h"
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/**
+ * @brief Sample data formats
+ * @note These are defined regardless of whether you use the GMISC module
+ * or not as they are used in lots of places.
+ */
+typedef enum ArrayDataFormat_e {
+ ARRAY_DATA_4BITUNSIGNED = 4, ARRAY_DATA_4BITSIGNED = 5,
+ ARRAY_DATA_8BITUNSIGNED = 8, ARRAY_DATA_8BITSIGNED = 9,
+ ARRAY_DATA_10BITUNSIGNED = 10, ARRAY_DATA_10BITSIGNED = 11,
+ ARRAY_DATA_12BITUNSIGNED = 12, ARRAY_DATA_12BITSIGNED = 13,
+ ARRAY_DATA_14BITUNSIGNED = 14, ARRAY_DATA_14BITSIGNED = 15,
+ ARRAY_DATA_16BITUNSIGNED = 16, ARRAY_DATA_16BITSIGNED = 17,
+ } ArrayDataFormat;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if GFX_USE_GMISC || defined(__DOXYGEN__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if GMISC_NEED_ARRAYOPS || defined(__DOXYGEN__)
+ /**
+ * @brief Convert from one array format to another array format.
+ *
+ * @param[in] srcfmt The format of the source array
+ * @param[in] src The source array
+ * @param[in] dstfmt The format of the destination array
+ * @param[in] dst The dstination array
+ * @param[in] cnt The number of array elements to convert
+ *
+ * @note Assumes the destination buffer is large enough for the resultant data.
+ * @note This routine is optimised to perform as fast as possible.
+ * @note No type checking is performed on the source format. It is assumed to
+ * have only valid values eg. ARRAY_DATA_4BITSIGNED will have values
+ * 0000 -> 0111 for positive numbers and 1111 -> 1000 for negative numbers
+ * Bits 5 -> 8 in the storage byte are treated in an undefined manner.
+ * @note If srcfmt or dstfmt is an unknown format, this routine does nothing
+ * with no warning that something is wrong
+ *
+ * @api
+ */
+ void gmiscArrayConvert(ArrayDataFormat srcfmt, void *src, ArrayDataFormat dstfmt, void *dst, size_t cnt);
+
+ #if 0
+ void gmiscArrayTranslate(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int trans);
+
+ void gmiscArrayMultiply(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult);
+
+ void gmiscArrayDivide(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mdiv);
+
+ void gmiscArrayMultDiv(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult, int div);
+
+ void gmiscArrayAdd(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
+
+ void gmiscArrayAddNoOverflow(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
+ #endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_MISC */
+
+#endif /* _GMISC_H */
+/** @} */
+
diff --git a/src/gadc/gadc.c b/src/gadc/gadc.c
index 509557d3..8a3cfb8d 100644
--- a/src/gadc/gadc.c
+++ b/src/gadc/gadc.c
@@ -83,6 +83,7 @@ static struct hsdev {
size_t remaining;
BinarySemaphore *bsem;
GEventADC *pEvent;
+ GADCISRCallbackFunction isrfn;
} hs;
static struct lsdev {
@@ -181,6 +182,11 @@ void GADC_ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
hs.pEvent->buffer = hs.lastbuffer;
hs.pEvent->flags = hs.lastflags;
}
+
+ /* Our three signalling mechanisms */
+ if (hs.isrfn)
+ hs.isrfn(buffer, n);
+
if (hs.bsem)
chBSemSignalI(hs.bsem);
@@ -344,6 +350,7 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer
hs.remaining = bufcount;
hs.bsem = 0;
hs.pEvent = 0;
+ hs.isrfn = 0;
}
#if GFX_USE_GEVENT
@@ -356,6 +363,10 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer
}
#endif
+void gadcHighSpeedSetISRCallback(GADCISRCallbackFunction isrfn) {
+ hs.isrfn = isrfn;
+}
+
void gadcHighSpeedSetBSem(BinarySemaphore *pbsem, GEventADC *pEvent) {
DoInit();
diff --git a/src/gaudin/gaudin.c b/src/gaudin/gaudin.c
index 120d7d81..4ce04132 100644
--- a/src/gaudin/gaudin.c
+++ b/src/gaudin/gaudin.c
@@ -1,38 +1,158 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file src/gaudin/gaudin.c
- * @brief GAUDIN sub-system code.
- *
- * @addtogroup GAUDIN
- * @{
- */
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
-
- #error "GAUDIN: Not implemented yet"
-
-#endif /* GFX_USE_GAUDIN */
-/** @} */
-
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/gaudin/gaudin.c
+ * @brief GAUDIN sub-system code.
+ *
+ * @addtogroup GAUDIN
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GAUDIN
+
+/* Include the driver defines */
+#include "gaudin/lld/gaudin_lld.h"
+
+static gaudin_params aud;
+static BinarySemaphore *paudSem;
+static GEventAudioIn *paudEvent;
+static audin_sample_t *lastbuffer;
+static size_t lastcount;
+static uint16_t audFlags;
+ #define AUDFLG_RUNNING 0x0001
+ #define AUDFLG_USE_EVENTS 0x0002
+
+#if GFX_USE_GEVENT
+ static GTIMER_DECL(AudGTimer);
+
+ static void AudGTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventADC *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
+ if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GADC_AUDIO_IN_LOSTEVENT;
+ continue;
+ }
+
+ pe->type = GEVENT_AUDIO_IN;
+ pe->channel = aud.channel;
+ pe->count = lastcount;
+ pe->buffer = lastbuffer;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ geventSendEvent(psl);
+ }
+ }
+#endif
+
+void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n) {
+ /* Save the details */
+ lastcount = n;
+ lastbuffer = buffer;
+
+ /* Signal the user with the data */
+ if (paudEvent) {
+ #if GFX_USE_GEVENT
+ paudEvent->type = GEVENT_AUDIO_IN;
+ #endif
+ paudEvent->channel = aud.channel;
+ paudEvent->count = lastcount;
+ paudEvent->buffer = lastbuffer;
+ paudEvent->flags = 0;
+ }
+
+ /* Our two signalling mechanisms */
+ if (paudSem)
+ chBSemSignalI(paudSem);
+
+ #if GFX_USE_GEVENT
+ if (audFlags & AUDFLG_USE_EVENTS)
+ gtimerJabI(&AudGTimer);
+ #endif
+}
+
+void GAUDIN_ISR_ErrorI(void) {
+ /* Ignore any errors for now */
+}
+
+bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent) {
+ /* Check the channel is valid */
+ if (channel >= GAUDIN_NUM_CHANNELS || frequency > GAUDIN_MAX_SAMPLE_FREQUENCY)
+ return FALSE;
+
+ /* Stop any existing transfers */
+ if ((audFlags & AUDFLG_RUNNING))
+ gadc_lld_stop();
+ audFlags = 0;
+
+ /* Initialise everything */
+ aud.channel = channel;
+ aud.frequency = frequency;
+ aud.buffer = buffer;
+ aud.bufcount = bufcount;
+ aud.samplesPerEvent = samplesPerEvent;
+ paudSem = 0;
+ paudEvent = 0;
+
+ /* Set up the low level driver */
+ gaudin_lld_init(&aud);
+ return TRUE;
+}
+
+#if GFX_USE_GEVENT
+ GSourceHandle gaudinGetSource(void) {
+ if (!gtimerIsActive(&AudGTimer))
+ gtimerStart(&AudGTimer, AudGTimerCallback, NULL, TRUE, TIME_INFINITE);
+ audFlags |= AUDFLG_USE_EVENTS;
+ return (GSourceHandle)&aud;
+ }
+#endif
+
+void gaudinSetBSem(BinarySemaphore *pbsem, GEventAudioIn *pEvent) {
+ chSysLock();
+ paudSem = pbsem;
+ paudEvent = pEvent;
+ chSysUnlock();
+}
+
+void gaudinStart(void) {
+ if (!(audFlags & AUDFLG_RUNNING)) {
+ audFlags |= AUDFLG_RUNNING;
+ gadc_lld_start();
+ }
+}
+
+void gaudinStop(void) {
+ if ((audFlags & AUDFLG_RUNNING)) {
+ gadc_lld_stop();
+ audFlags &= ~AUDFLG_RUNNING;
+ }
+}
+
+#endif /* GFX_USE_GAUDIN */
+/** @} */
diff --git a/src/gevent/gevent.c b/src/gevent/gevent.c
index f3d909f0..f6d45f1a 100644
--- a/src/gevent/gevent.c
+++ b/src/gevent/gevent.c
@@ -1,197 +1,197 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file src/gevent/gevent.c
- * @brief GEVENT Driver code.
- *
- * @addtogroup GEVENT
- * @{
- */
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_GEVENT || defined(__DOXYGEN__)
-
-#if GEVENT_ASSERT_NO_RESOURCE
- #define GEVENT_ASSERT(x) assert(x)
-#else
- #define GEVENT_ASSERT(x)
-#endif
-
-/* This mutex protects access to our tables */
-static MUTEX_DECL(geventMutex);
-
-/* Our table of listener/source pairs */
-static GSourceListener Assignments[GEVENT_MAX_SOURCE_LISTENERS];
-
-/* Loop through the assignment table deleting this listener/source pair. */
-/* Null is treated as a wildcard. */
-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 (chSemGetCounterI(&psl->pListener->waitqueue) < 0) {
- chBSemWait(&psl->pListener->eventlock); // Obtain the buffer lock
- psl->pListener->event.type = GEVENT_EXIT; // Set up the EXIT event
- chSemSignal(&psl->pListener->waitqueue); // Wake up the listener
- chBSemSignal(&psl->pListener->eventlock); // Release the buffer lock
- }
- psl->pListener = 0;
- }
- }
-}
-
-void geventListenerInit(GListener *pl) {
- chSemInit(&pl->waitqueue, 0); // Next wait'er will block
- chBSemInit(&pl->eventlock, FALSE); // Only one thread at a time looking at the event buffer
- pl->callback = 0; // No callback active
- pl->event.type = GEVENT_NULL; // Always safety
-}
-
-bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) {
- GSourceListener *psl, *pslfree;
-
- // Safety first
- if (!pl || !gsh) {
- GEVENT_ASSERT(FALSE);
- return FALSE;
- }
-
- chMtxLock(&geventMutex);
-
- // Check if this pair is already in the table (scan for a free slot at the same time)
- pslfree = 0;
- for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
-
- if (pl == psl->pListener && gsh == psl->pSource) {
- // Just update the flags
- chBSemWait(&pl->eventlock); // Safety first - just in case a source is using it
- psl->listenflags = flags;
- chBSemSignal(&pl->eventlock); // Release this lock
- chMtxUnlock();
- return TRUE;
- }
- if (!pslfree && !psl->pListener)
- pslfree = psl;
- }
-
- // A free slot was found - allocate it
- if (pslfree) {
- pslfree->pListener = pl;
- pslfree->pSource = gsh;
- pslfree->listenflags = flags;
- pslfree->srcflags = 0;
- }
- chMtxUnlock();
- GEVENT_ASSERT(pslfree != 0);
- return pslfree != 0;
-}
-
-void geventDetachSource(GListener *pl, GSourceHandle gsh) {
- if (pl && gsh) {
- chMtxLock(&geventMutex);
- deleteAssignments(pl, gsh);
- if (!gsh && chSemGetCounterI(&pl->waitqueue) < 0) {
- chBSemWait(&pl->eventlock); // Obtain the buffer lock
- pl->event.type = GEVENT_EXIT; // Set up the EXIT event
- chSemSignal(&pl->waitqueue); // Wake up the listener
- chBSemSignal(&pl->eventlock); // Release the buffer lock
- }
- chMtxUnlock();
- }
-}
-
-GEvent *geventEventWait(GListener *pl, systime_t timeout) {
- if (pl->callback || chSemGetCounterI(&pl->waitqueue) < 0)
- return 0;
- return chSemWaitTimeout(&pl->waitqueue, timeout) == RDY_OK ? &pl->event : 0;
-}
-
-void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) {
- if (pl) {
- chMtxLock(&geventMutex);
- chBSemWait(&pl->eventlock); // Obtain the buffer lock
- pl->param = param; // Set the param
- pl->callback = fn; // Set the callback function
- if (chSemGetCounterI(&pl->waitqueue) < 0) {
- pl->event.type = GEVENT_EXIT; // Set up the EXIT event
- chSemSignal(&pl->waitqueue); // Wake up the listener
- }
- chBSemSignal(&pl->eventlock); // Release the buffer lock
- chMtxUnlock();
- }
-}
-
-GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr) {
- GSourceListener *psl;
-
- // Safety first
- if (!gsh)
- return 0;
-
- chMtxLock(&geventMutex);
-
- // Unlock the last listener event buffer
- if (lastlr)
- chBSemSignal(&lastlr->pListener->eventlock);
-
- // 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) {
- chBSemWait(&psl->pListener->eventlock); // Obtain a lock on the listener event buffer
- chMtxUnlock();
- return psl;
- }
- }
- chMtxUnlock();
- return 0;
-}
-
-GEvent *geventGetEventBuffer(GSourceListener *psl) {
- // We already know we have the event lock
- return &psl->pListener->callback || chSemGetCounterI(&psl->pListener->waitqueue) < 0 ? &psl->pListener->event : 0;
-}
-
-void geventSendEvent(GSourceListener *psl) {
- chMtxLock(&geventMutex);
- if (psl->pListener->callback) { // This test needs to be taken inside the mutex
- chMtxUnlock();
- // We already know we have the event lock
- psl->pListener->callback(psl->pListener->param, &psl->pListener->event);
-
- } else {
- // Wake up the listener
- if (chSemGetCounterI(&psl->pListener->waitqueue) < 0)
- chSemSignal(&psl->pListener->waitqueue);
- chMtxUnlock();
- }
-}
-
-void geventDetachSourceListeners(GSourceHandle gsh) {
- chMtxLock(&geventMutex);
- deleteAssignments(0, gsh);
- chMtxUnlock();
-}
-
-#endif /* GFX_USE_GEVENT */
-/** @} */
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/gevent/gevent.c
+ * @brief GEVENT Driver code.
+ *
+ * @addtogroup GEVENT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GEVENT || defined(__DOXYGEN__)
+
+#if GEVENT_ASSERT_NO_RESOURCE
+ #define GEVENT_ASSERT(x) assert(x)
+#else
+ #define GEVENT_ASSERT(x)
+#endif
+
+/* This mutex protects access to our tables */
+static MUTEX_DECL(geventMutex);
+
+/* Our table of listener/source pairs */
+static GSourceListener Assignments[GEVENT_MAX_SOURCE_LISTENERS];
+
+/* Loop through the assignment table deleting this listener/source pair. */
+/* Null is treated as a wildcard. */
+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 (chSemGetCounterI(&psl->pListener->waitqueue) < 0) {
+ chBSemWait(&psl->pListener->eventlock); // Obtain the buffer lock
+ psl->pListener->event.type = GEVENT_EXIT; // Set up the EXIT event
+ chSemSignal(&psl->pListener->waitqueue); // Wake up the listener
+ chBSemSignal(&psl->pListener->eventlock); // Release the buffer lock
+ }
+ psl->pListener = 0;
+ }
+ }
+}
+
+void geventListenerInit(GListener *pl) {
+ chSemInit(&pl->waitqueue, 0); // Next wait'er will block
+ chBSemInit(&pl->eventlock, FALSE); // Only one thread at a time looking at the event buffer
+ pl->callback = 0; // No callback active
+ pl->event.type = GEVENT_NULL; // Always safety
+}
+
+bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) {
+ GSourceListener *psl, *pslfree;
+
+ // Safety first
+ if (!pl || !gsh) {
+ GEVENT_ASSERT(FALSE);
+ return FALSE;
+ }
+
+ chMtxLock(&geventMutex);
+
+ // Check if this pair is already in the table (scan for a free slot at the same time)
+ pslfree = 0;
+ for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
+
+ if (pl == psl->pListener && gsh == psl->pSource) {
+ // Just update the flags
+ chBSemWait(&pl->eventlock); // Safety first - just in case a source is using it
+ psl->listenflags = flags;
+ chBSemSignal(&pl->eventlock); // Release this lock
+ chMtxUnlock();
+ return TRUE;
+ }
+ if (!pslfree && !psl->pListener)
+ pslfree = psl;
+ }
+
+ // A free slot was found - allocate it
+ if (pslfree) {
+ pslfree->pListener = pl;
+ pslfree->pSource = gsh;
+ pslfree->listenflags = flags;
+ pslfree->srcflags = 0;
+ }
+ chMtxUnlock();
+ GEVENT_ASSERT(pslfree != 0);
+ return pslfree != 0;
+}
+
+void geventDetachSource(GListener *pl, GSourceHandle gsh) {
+ if (pl) {
+ chMtxLock(&geventMutex);
+ deleteAssignments(pl, gsh);
+ if (!gsh && chSemGetCounterI(&pl->waitqueue) < 0) {
+ chBSemWait(&pl->eventlock); // Obtain the buffer lock
+ pl->event.type = GEVENT_EXIT; // Set up the EXIT event
+ chSemSignal(&pl->waitqueue); // Wake up the listener
+ chBSemSignal(&pl->eventlock); // Release the buffer lock
+ }
+ chMtxUnlock();
+ }
+}
+
+GEvent *geventEventWait(GListener *pl, systime_t timeout) {
+ if (pl->callback || chSemGetCounterI(&pl->waitqueue) < 0)
+ return 0;
+ return chSemWaitTimeout(&pl->waitqueue, timeout) == RDY_OK ? &pl->event : 0;
+}
+
+void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) {
+ if (pl) {
+ chMtxLock(&geventMutex);
+ chBSemWait(&pl->eventlock); // Obtain the buffer lock
+ pl->param = param; // Set the param
+ pl->callback = fn; // Set the callback function
+ if (chSemGetCounterI(&pl->waitqueue) < 0) {
+ pl->event.type = GEVENT_EXIT; // Set up the EXIT event
+ chSemSignal(&pl->waitqueue); // Wake up the listener
+ }
+ chBSemSignal(&pl->eventlock); // Release the buffer lock
+ chMtxUnlock();
+ }
+}
+
+GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr) {
+ GSourceListener *psl;
+
+ // Safety first
+ if (!gsh)
+ return 0;
+
+ chMtxLock(&geventMutex);
+
+ // Unlock the last listener event buffer
+ if (lastlr)
+ chBSemSignal(&lastlr->pListener->eventlock);
+
+ // 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) {
+ chBSemWait(&psl->pListener->eventlock); // Obtain a lock on the listener event buffer
+ chMtxUnlock();
+ return psl;
+ }
+ }
+ chMtxUnlock();
+ return 0;
+}
+
+GEvent *geventGetEventBuffer(GSourceListener *psl) {
+ // We already know we have the event lock
+ return &psl->pListener->callback || chSemGetCounterI(&psl->pListener->waitqueue) < 0 ? &psl->pListener->event : 0;
+}
+
+void geventSendEvent(GSourceListener *psl) {
+ chMtxLock(&geventMutex);
+ if (psl->pListener->callback) { // This test needs to be taken inside the mutex
+ chMtxUnlock();
+ // We already know we have the event lock
+ psl->pListener->callback(psl->pListener->param, &psl->pListener->event);
+
+ } else {
+ // Wake up the listener
+ if (chSemGetCounterI(&psl->pListener->waitqueue) < 0)
+ chSemSignal(&psl->pListener->waitqueue);
+ chMtxUnlock();
+ }
+}
+
+void geventDetachSourceListeners(GSourceHandle gsh) {
+ chMtxLock(&geventMutex);
+ deleteAssignments(0, gsh);
+ chMtxUnlock();
+}
+
+#endif /* GFX_USE_GEVENT */
+/** @} */
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 4eef79ad..e449b830 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -1,544 +1,546 @@
-/*
- ChibiOS/GFX - Copyright (C) 2012
- Joel Bodenmann aka Tectu <joel@unormal.org>
-
- This file is part of ChibiOS/GFX.
-
- ChibiOS/GFX is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/GFX is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file src/gwin/gwin.c
- * @brief GWIN sub-system code.
- *
- * @defgroup Window Window
- * @ingroup GWIN
- *
- * @{
- */
-
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_GWIN || defined(__DOXYGEN__)
-
-#include "gwin/internal.h"
-
-// Internal routine for use by GWIN components only
-// Initialise a window creating it dynamicly if required.
-GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) {
- coord_t w, h;
-
- // Check the window size against the screen size
- w = gdispGetWidth();
- h = gdispGetHeight();
- if (x < 0) { width += x; x = 0; }
- if (y < 0) { height += y; y = 0; }
- if (x >= w || y >= h) return 0;
- if (x+width > w) width = w - x;
- if (y+height > h) height = h - y;
-
- // Allocate the structure if necessary
- if (!gw) {
- if (!(gw = (GWindowObject *)chHeapAlloc(NULL, size)))
- return 0;
- gw->flags = GWIN_FLG_DYNAMIC;
- } else
- gw->flags = 0;
-
- // Initialise all basic fields (except the type)
- gw->x = x;
- gw->y = y;
- gw->width = width;
- gw->height = height;
- gw->color = White;
- gw->bgcolor = Black;
-#if GDISP_NEED_TEXT
- gw->font = 0;
-#endif
- return (GHandle)gw;
-}
-
-/**
- * @brief Create a basic window.
- * @return NULL if there is no resultant drawing area, otherwise a window handle.
- *
- * @param[in] gw The window structure to initialise. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
- * @param[in] width The width of the window
- * @param[in] height The height of the window
- * @note The default drawing color gets set to White and the background drawing color to Black.
- * @note No default font is set so make sure to set one before drawing any text.
- * @note The dimensions and position may be changed to fit on the real screen.
- * @note The window is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
- *
- * @api
- */
-GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject))))
- return 0;
- gw->type = GW_WINDOW;
- return (GHandle)gw;
-}
-
-/**
- * @brief Destroy a window (of any type). Releases any dynamicly allocated memory.
- *
- * @param[in] gh The window handle
- *
- * @api
- */
-void gwinDestroyWindow(GHandle gh) {
- // Clean up any type specific dynamic memory allocations
- switch(gh->type) {
-#if GWIN_NEED_BUTTON
- case GW_BUTTON:
- if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
- gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure
- chHeapFree((void *)((GButtonObject *)gh)->txt);
- }
- break;
-#endif
- default:
- break;
- }
-
- // Clean up the structure
- if (gh->flags & GWIN_FLG_DYNAMIC) {
- gh->flags = 0; // To be sure, to be sure
- chHeapFree((void *)gh);
- }
-}
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Set the current font for this window.
- *
- * @param[in] gh The window handle
- * @param[in] font The font to use for text functions
- *
- * @api
- */
-void gwinSetFont(GHandle gh, font_t font) {
- gh->font = font;
-#if GWIN_NEED_CONSOLE
- if (font && gh->type == GW_CONSOLE) {
- ((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight);
- ((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding);
- }
-#endif
-}
-#endif
-
-/**
- * @brief Clear the window
- * @note Uses the current background color to clear the window
- *
- * @param[in] gh The window handle
- *
- * @api
- */
-void gwinClear(GHandle gh) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
-
- #if GWIN_NEED_CONSOLE
- if (gh->type == GW_CONSOLE) {
- ((GConsoleObject *)gh)->cx = 0;
- ((GConsoleObject *)gh)->cy = 0;
- }
- #endif
-}
-
-/**
- * @brief Set a pixel in the window
- * @note Uses the current foreground color to set the pixel
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The coordinates of the pixel
- *
- * @api
- */
-void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawPixel(gh->x+x, gh->y+y, gh->color);
-}
-
-/**
- * @brief Draw a line in the window
- * @note Uses the current foreground color to draw the line
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x0,y0 The start position
- * @param[in] x1,y1 The end position
- *
- * @api
- */
-void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawLine(gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color);
-}
-
-/**
- * @brief Draw a box in the window
- * @note Uses the current foreground color to draw the box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The start position
- * @param[in] cx,cy The size of the box (outside dimensions)
- *
- * @api
- */
-void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawBox(gh->x+x, gh->y+y, cx, cy, gh->color);
-}
-
-/**
- * @brief Fill an rectangular area in the window
- * @note Uses the current foreground color to fill the box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The start position
- * @param[in] cx,cy The size of the box (outside dimensions)
- *
- * @api
- */
-void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillArea(gh->x+x, gh->y+y, cx, cy, gh->color);
-}
-
-/**
- * @brief Fill an area in the window using the supplied bitmap.
- * @details The bitmap is in the pixel format specified by the low level driver
- * @note If GDISP_NEED_ASYNC is defined then the buffer must be static
- * or at least retained until this call has finished the blit. You can
- * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE.
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x, y The start filled area
- * @param[in] cx, cy The width and height to be filled
- * @param[in] srcx, srcy The bitmap position to start the fill from
- * @param[in] srccx The width of a line in the bitmap.
- * @param[in] buffer The pixels to use to fill the area.
- *
- * @api
- */
-void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispBlitAreaEx(gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer);
-}
-
-#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
-/**
- * @brief Draw a circle in the window.
- * @note Uses the current foreground color to draw the circle
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x, y The center of the circle
- * @param[in] radius The radius of the circle
- *
- * @api
- */
-void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawCircle(gh->x+x, gh->y+y, radius, gh->color);
-}
-#endif
-
-#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
-/**
- * @brief Draw a filled circle in the window.
- * @note Uses the current foreground color to draw the filled circle
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x, y The center of the circle
- * @param[in] radius The radius of the circle
- *
- * @api
- */
-void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillCircle(gh->x+x, gh->y+y, radius, gh->color);
-}
-#endif
-
-#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
-/**
- * @brief Draw an ellipse.
- * @note Uses the current foreground color to draw the ellipse
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The center of the ellipse
- * @param[in] a,b The dimensions of the ellipse
- *
- * @api
- */
-void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawEllipse(gh->x+x, gh->y+y, a, b, gh->color);
-}
-#endif
-
-#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
-/**
- * @brief Draw an filled ellipse.
- * @note Uses the current foreground color to draw the filled ellipse
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The center of the ellipse
- * @param[in] a,b The dimensions of the ellipse
- *
- * @api
- */
-void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillEllipse(gh->x+x, gh->y+y, a, b, gh->color);
-}
-#endif
-
-#if GDISP_NEED_ARC || defined(__DOXYGEN__)
-/*
- * @brief Draw an arc in the window.
- * @note Uses the current foreground color to draw the arc
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The center point
- * @param[in] radius The radius of the arc
- * @param[in] start The start angle (0 to 360)
- * @param[in] end The end angle (0 to 360)
- *
- * @api
- */
-void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
-}
-#endif
-
-#if GDISP_NEED_ARC || defined(__DOXYGEN__)
-/*
- * @brief Draw a filled arc in the window.
- * @note Uses the current foreground color to draw the filled arc
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The center point
- * @param[in] radius The radius of the arc
- * @param[in] start The start angle (0 to 360)
- * @param[in] end The end angle (0 to 360)
- *
- * @api
- */
-void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
-}
-#endif
-
-#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
-/**
- * @brief Get the color of a pixel in the window.
- * @return The color of the pixel.
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position in the window
- *
- * @api
- */
-color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) {
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- return gdispGetPixelColor(gh->x+x, gh->y+y);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text character at the specified position in the window.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] c The character to draw
- *
- * @api
- */
-void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawChar(gh->x+x, gh->y+y, c, gh->font, gh->color);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text character with a filled background at the specified position in the window.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] c The character to draw
- *
- * @api
- */
-void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillChar(gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text string in the window
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] str The string to draw
- *
- * @api
- */
-void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawString(gh->x+x, gh->y+y, str, gh->font, gh->color);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text string with a filled background in the window
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] str The string to draw
- *
- * @api
- */
-void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillString(gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text string verticly centered within the specified box.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character.
- * @note The specified box does not need to align with the window box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
- * @param[in] cx,cy The width and height of the box
- * @param[in] str The string to draw
- * @param[in] justify Justify the text left, center or right within the box
- *
- * @api
- */
-void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispDrawStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify);
-}
-#endif
-
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
-/**
- * @brief Draw a text string verticly centered within the specified filled box.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note The entire box is filled. Note this box does not need to align with the window box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
- * @param[in] cx,cy The width and height of the box
- * @param[in] str The string to draw
- * @param[in] justify Justify the text left, center or right within the box
- *
- * @api
- */
-void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
- if (!gh->font) return;
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispFillStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify);
-}
-#endif
-
-#endif /* GFX_USE_GWIN */
-/** @} */
-
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file src/gwin/gwin.c
+ * @brief GWIN sub-system code.
+ *
+ * @defgroup Window Window
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GWIN || defined(__DOXYGEN__)
+
+#include "gwin/internal.h"
+
+// Internal routine for use by GWIN components only
+// Initialise a window creating it dynamicly if required.
+GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) {
+ coord_t w, h;
+
+ // Check the window size against the screen size
+ w = gdispGetWidth();
+ h = gdispGetHeight();
+ if (x < 0) { width += x; x = 0; }
+ if (y < 0) { height += y; y = 0; }
+ if (x >= w || y >= h) return 0;
+ if (x+width > w) width = w - x;
+ if (y+height > h) height = h - y;
+
+ // Allocate the structure if necessary
+ if (!gw) {
+ if (!(gw = (GWindowObject *)chHeapAlloc(NULL, size)))
+ return 0;
+ gw->flags = GWIN_FLG_DYNAMIC;
+ } else
+ gw->flags = 0;
+
+ // Initialise all basic fields (except the type)
+ gw->x = x;
+ gw->y = y;
+ gw->width = width;
+ gw->height = height;
+ gw->color = White;
+ gw->bgcolor = Black;
+#if GDISP_NEED_TEXT
+ gw->font = 0;
+#endif
+ return (GHandle)gw;
+}
+
+/**
+ * @brief Create a basic window.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] gw The window structure to initialise. If this is NULL the structure is dynamically allocated.
+ * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] width The width of the window
+ * @param[in] height The height of the window
+ * @note The default drawing color gets set to White and the background drawing color to Black.
+ * @note No default font is set so make sure to set one before drawing any text.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ * @note The window is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
+ *
+ * @api
+ */
+GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
+ if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject))))
+ return 0;
+ gw->type = GW_WINDOW;
+ return (GHandle)gw;
+}
+
+/**
+ * @brief Destroy a window (of any type). Releases any dynamicly allocated memory.
+ *
+ * @param[in] gh The window handle
+ *
+ * @api
+ */
+void gwinDestroyWindow(GHandle gh) {
+ // Clean up any type specific dynamic memory allocations
+ switch(gh->type) {
+#if GWIN_NEED_BUTTON
+ case GW_BUTTON:
+ if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure
+ chHeapFree((void *)((GButtonObject *)gh)->txt);
+ }
+ geventDetachSource(&((GButtonObject *)gh)->listener, 0);
+ geventDetachSourceListeners((GSourceHandle *)gh);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ // Clean up the structure
+ if (gh->flags & GWIN_FLG_DYNAMIC) {
+ gh->flags = 0; // To be sure, to be sure
+ chHeapFree((void *)gh);
+ }
+}
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Set the current font for this window.
+ *
+ * @param[in] gh The window handle
+ * @param[in] font The font to use for text functions
+ *
+ * @api
+ */
+void gwinSetFont(GHandle gh, font_t font) {
+ gh->font = font;
+#if GWIN_NEED_CONSOLE
+ if (font && gh->type == GW_CONSOLE) {
+ ((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight);
+ ((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding);
+ }
+#endif
+}
+#endif
+
+/**
+ * @brief Clear the window
+ * @note Uses the current background color to clear the window
+ *
+ * @param[in] gh The window handle
+ *
+ * @api
+ */
+void gwinClear(GHandle gh) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
+
+ #if GWIN_NEED_CONSOLE
+ if (gh->type == GW_CONSOLE) {
+ ((GConsoleObject *)gh)->cx = 0;
+ ((GConsoleObject *)gh)->cy = 0;
+ }
+ #endif
+}
+
+/**
+ * @brief Set a pixel in the window
+ * @note Uses the current foreground color to set the pixel
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The coordinates of the pixel
+ *
+ * @api
+ */
+void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawPixel(gh->x+x, gh->y+y, gh->color);
+}
+
+/**
+ * @brief Draw a line in the window
+ * @note Uses the current foreground color to draw the line
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x0,y0 The start position
+ * @param[in] x1,y1 The end position
+ *
+ * @api
+ */
+void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawLine(gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color);
+}
+
+/**
+ * @brief Draw a box in the window
+ * @note Uses the current foreground color to draw the box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ *
+ * @api
+ */
+void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawBox(gh->x+x, gh->y+y, cx, cy, gh->color);
+}
+
+/**
+ * @brief Fill an rectangular area in the window
+ * @note Uses the current foreground color to fill the box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ *
+ * @api
+ */
+void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillArea(gh->x+x, gh->y+y, cx, cy, gh->color);
+}
+
+/**
+ * @brief Fill an area in the window using the supplied bitmap.
+ * @details The bitmap is in the pixel format specified by the low level driver
+ * @note If GDISP_NEED_ASYNC is defined then the buffer must be static
+ * or at least retained until this call has finished the blit. You can
+ * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE.
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] srcx, srcy The bitmap position to start the fill from
+ * @param[in] srccx The width of a line in the bitmap.
+ * @param[in] buffer The pixels to use to fill the area.
+ *
+ * @api
+ */
+void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispBlitAreaEx(gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer);
+}
+
+#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
+/**
+ * @brief Draw a circle in the window.
+ * @note Uses the current foreground color to draw the circle
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x, y The center of the circle
+ * @param[in] radius The radius of the circle
+ *
+ * @api
+ */
+void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawCircle(gh->x+x, gh->y+y, radius, gh->color);
+}
+#endif
+
+#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
+/**
+ * @brief Draw a filled circle in the window.
+ * @note Uses the current foreground color to draw the filled circle
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x, y The center of the circle
+ * @param[in] radius The radius of the circle
+ *
+ * @api
+ */
+void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillCircle(gh->x+x, gh->y+y, radius, gh->color);
+}
+#endif
+
+#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
+/**
+ * @brief Draw an ellipse.
+ * @note Uses the current foreground color to draw the ellipse
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ *
+ * @api
+ */
+void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawEllipse(gh->x+x, gh->y+y, a, b, gh->color);
+}
+#endif
+
+#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
+/**
+ * @brief Draw an filled ellipse.
+ * @note Uses the current foreground color to draw the filled ellipse
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ *
+ * @api
+ */
+void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillEllipse(gh->x+x, gh->y+y, a, b, gh->color);
+}
+#endif
+
+#if GDISP_NEED_ARC || defined(__DOXYGEN__)
+/*
+ * @brief Draw an arc in the window.
+ * @note Uses the current foreground color to draw the arc
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center point
+ * @param[in] radius The radius of the arc
+ * @param[in] start The start angle (0 to 360)
+ * @param[in] end The end angle (0 to 360)
+ *
+ * @api
+ */
+void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
+}
+#endif
+
+#if GDISP_NEED_ARC || defined(__DOXYGEN__)
+/*
+ * @brief Draw a filled arc in the window.
+ * @note Uses the current foreground color to draw the filled arc
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center point
+ * @param[in] radius The radius of the arc
+ * @param[in] start The start angle (0 to 360)
+ * @param[in] end The end angle (0 to 360)
+ *
+ * @api
+ */
+void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
+}
+#endif
+
+#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
+/**
+ * @brief Get the color of a pixel in the window.
+ * @return The color of the pixel.
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position in the window
+ *
+ * @api
+ */
+color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ return gdispGetPixelColor(gh->x+x, gh->y+y);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text character at the specified position in the window.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ *
+ * @api
+ */
+void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawChar(gh->x+x, gh->y+y, c, gh->font, gh->color);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text character with a filled background at the specified position in the window.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ *
+ * @api
+ */
+void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillChar(gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text string in the window
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] str The string to draw
+ *
+ * @api
+ */
+void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawString(gh->x+x, gh->y+y, str, gh->font, gh->color);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text string with a filled background in the window
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] str The string to draw
+ *
+ * @api
+ */
+void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillString(gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text string verticly centered within the specified box.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character.
+ * @note The specified box does not need to align with the window box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
+ * @param[in] cx,cy The width and height of the box
+ * @param[in] str The string to draw
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispDrawStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify);
+}
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+/**
+ * @brief Draw a text string verticly centered within the specified filled box.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note The entire box is filled. Note this box does not need to align with the window box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
+ * @param[in] cx,cy The width and height of the box
+ * @param[in] str The string to draw
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
+ if (!gh->font) return;
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gdispFillStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify);
+}
+#endif
+
+#endif /* GFX_USE_GWIN */
+/** @} */
+