diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..a8ae8ed8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+docs/html
diff --git a/Doxygenfile b/Doxygenfile
new file mode 100644
index 00000000..295695d4
--- /dev/null
+++ b/Doxygenfile
@@ -0,0 +1,1824 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = ChibiOS/GFX
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 1.5
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = "C:/Documents and Settings/Administrator/"
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 2
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = "iclass=@par Function Class:\n This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers." \
+ "sclass=@par Function Class:\n This is an S-Class API, this function can be invoked from within a system lock zone by threads only." \
+ "api=@par Function Class:\n Normal API, this function can be invoked by regular system threads but not from within a lock zone." \
+ "notapi=@par Function Class:\n Not an API, this function is for internal use only." \
+ "isr=@par Function Class:\n Interrupt handler, this function should not be directly invoked." \
+ "init=@par Function Class:\n Initializer, this function just initializes an object and can be invoked before the kernel is initialized." \
+ "special=@par Function Class:\n Special function, this function has special requirements see the notes."
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE = docs/rsc/layout.xml
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE = ChibiOS-GFX.chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION = "\"C:/Program Files/HTML Help Workshop/hhc.exe\""
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+#
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+#
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = __DOXYGEN__
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = NO
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 8
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = YES
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 20
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 3
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/codingstyle.txt b/codingstyle.txt
new file mode 100644
index 00000000..ceab047c
--- /dev/null
+++ b/codingstyle.txt
@@ -0,0 +1,289 @@
+ ChibiOS/GFX coding style
+
+To provide an easy-to-read code, we want to have a uniform
+coding style within ChibiOS/GFX.
+Because I personally like the widley used linux kernel coding style,
+I decided to use it for ChibiOS/GFX as well.
+Therefore, the coding style documentation is a 1:1 copy from the
+codingstyle.txt of the linux kernel source code.
+
+Please make sure you match these coding styles before you contribute
+any code. If you find any existing code which dosen't match these rules,
+please feel free to submit a patch.
+
+There are only two rules which are not similar to the following
+documentation:
+
+ - Prefered tabsize is 4, not 8
+ - We don't use 80 character columns
+
+
+Please read through the following carefully:
+
+
+
+ Linux kernel coding style
+
+This is a short document describing the preferred coding style for the
+linux kernel. Coding style is very personal, and I won't _force_ my
+views on anybody, but this is what goes for anything that I have to be
+able to maintain, and I'd prefer it for most other things too. Please
+at least consider the points made here.
+
+First off, I'd suggest printing out a copy of the GNU coding standards,
+and NOT read it. Burn them, it's a great symbolic gesture.
+
+Anyway, here goes:
+
+
+ Chapter 1: Indentation
+
+Tabs are 8 characters, and thus indentations are also 8 characters.
+There are heretic movements that try to make indentations 4 (or even 2!)
+characters deep, and that is akin to trying to define the value of PI to
+be 3.
+
+Rationale: The whole idea behind indentation is to clearly define where
+a block of control starts and ends. Especially when you've been looking
+at your screen for 20 straight hours, you'll find it a lot easier to see
+how the indentation works if you have large indentations.
+
+Now, some people will claim that having 8-character indentations makes
+the code move too far to the right, and makes it hard to read on a
+80-character terminal screen. The answer to that is that if you need
+more than 3 levels of indentation, you're screwed anyway, and should fix
+your program.
+
+In short, 8-char indents make things easier to read, and have the added
+benefit of warning you when you're nesting your functions too deep.
+Heed that warning.
+
+
+ Chapter 2: Placing Braces
+
+The other issue that always comes up in C styling is the placement of
+braces. Unlike the indent size, there are few technical reasons to
+choose one placement strategy over the other, but the preferred way, as
+shown to us by the prophets Kernighan and Ritchie, is to put the opening
+brace last on the line, and put the closing brace first, thusly:
+
+ if (x is true) {
+ we do y
+ }
+
+However, there is one special case, namely functions: they have the
+opening brace at the beginning of the next line, thus:
+
+ int function(int x)
+ {
+ body of function
+ }
+
+Heretic people all over the world have claimed that this inconsistency
+is ... well ... inconsistent, but all right-thinking people know that
+(a) K&R are _right_ and (b) K&R are right. Besides, functions are
+special anyway (you can't nest them in C).
+
+Note that the closing brace is empty on a line of its own, _except_ in
+the cases where it is followed by a continuation of the same statement,
+ie a "while" in a do-statement or an "else" in an if-statement, like
+this:
+
+ do {
+ body of do-loop
+ } while (condition);
+
+and
+
+ if (x == y) {
+ ..
+ } else if (x > y) {
+ ...
+ } else {
+ ....
+ }
+
+Rationale: K&R.
+
+Also, note that this brace-placement also minimizes the number of empty
+(or almost empty) lines, without any loss of readability. Thus, as the
+supply of new-lines on your screen is not a renewable resource (think
+25-line terminal screens here), you have more empty lines to put
+comments on.
+
+
+ Chapter 3: Naming
+
+C is a Spartan language, and so should your naming be. Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter. A C programmer would call that
+variable "tmp", which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must. To call a global function "foo" is a
+shooting offense.
+
+GLOBAL variables (to be used only if you _really_ need them) need to
+have descriptive names, as do global functions. If you have a function
+that counts the number of active users, you should call that
+"count_active_users()" or similar, you should _not_ call it "cntusr()".
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer. No wonder MicroSoft
+makes buggy programs.
+
+LOCAL variable names should be short, and to the point. If you have
+some random integer loop counter, it should probably be called "i".
+Calling it "loop_counter" is non-productive, if there is no chance of it
+being mis-understood. Similarly, "tmp" can be just about any type of
+variable that is used to hold a temporary value.
+
+If you are afraid to mix up your local variable names, you have another
+problem, which is called the function-growth-hormone-imbalance syndrome.
+See next chapter.
+
+
+ Chapter 4: Functions
+
+Functions should be short and sweet, and do just one thing. They should
+fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
+as we all know), and do one thing and do that well.
+
+The maximum length of a function is inversely proportional to the
+complexity and indentation level of that function. So, if you have a
+conceptually simple function that is just one long (but simple)
+case-statement, where you have to do lots of small things for a lot of
+different cases, it's OK to have a longer function.
+
+However, if you have a complex function, and you suspect that a
+less-than-gifted first-year high-school student might not even
+understand what the function is all about, you should adhere to the
+maximum limits all the more closely. Use helper functions with
+descriptive names (you can ask the compiler to in-line them if you think
+it's performance-critical, and it will probably do a better job of it
+that you would have done).
+
+Another measure of the function is the number of local variables. They
+shouldn't exceed 5-10, or you're doing something wrong. Re-think the
+function, and split it into smaller pieces. A human brain can
+generally easily keep track of about 7 different things, anything more
+and it gets confused. You know you're brilliant, but maybe you'd like
+to understand what you did 2 weeks from now.
+
+
+ Chapter 5: Commenting
+
+Comments are good, but there is also a danger of over-commenting. NEVER
+try to explain HOW your code works in a comment: it's much better to
+write the code so that the _working_ is obvious, and it's a waste of
+time to explain badly written code.
+
+Generally, you want your comments to tell WHAT your code does, not HOW.
+Also, try to avoid putting comments inside a function body: if the
+function is so complex that you need to separately comment parts of it,
+you should probably go back to chapter 4 for a while. You can make
+small comments to note or warn about something particularly clever (or
+ugly), but try to avoid excess. Instead, put the comments at the head
+of the function, telling people what it does, and possibly WHY it does
+it.
+
+
+ Chapter 6: You've made a mess of it
+
+That's OK, we all do. You've probably been told by your long-time Unix
+user helper that "GNU emacs" automatically formats the C sources for
+you, and you've noticed that yes, it does do that, but the defaults it
+uses are less than desirable (in fact, they are worse than random
+typing - a infinite number of monkeys typing into GNU emacs would never
+make a good program).
+
+So, you can either get rid of GNU emacs, or change it to use saner
+values. To do the latter, you can stick the following in your .emacs file:
+
+(defun linux-c-mode ()
+ "C mode with adjusted defaults for use with the Linux kernel."
+ (interactive)
+ (c-mode)
+ (c-set-style "K&R")
+ (setq c-basic-offset 8))
+
+This will define the M-x linux-c-mode command. When hacking on a
+module, if you put the string -*- linux-c -*- somewhere on the first
+two lines, this mode will be automatically invoked. Also, you may want
+to add
+
+(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
+ auto-mode-alist))
+
+to your .emacs file if you want to have linux-c-mode switched on
+automagically when you edit source files under /usr/src/linux.
+
+But even if you fail in getting emacs to do sane formatting, not
+everything is lost: use "indent".
+
+Now, again, GNU indent has the same brain dead settings that GNU emacs
+has, which is why you need to give it a few command line options.
+However, that's not too bad, because even the makers of GNU indent
+recognize the authority of K&R (the GNU people aren't evil, they are
+just severely misguided in this matter), so you just give indent the
+options "-kr -i8" (stands for "K&R, 8 character indents").
+
+"indent" has a lot of options, and especially when it comes to comment
+re-formatting you may want to take a look at the manual page. But
+remember: "indent" is not a fix for bad programming.
+
+
+ Chapter 7: Configuration-files
+
+For configuration options (arch/xxx/config.in, and all the Config.in files),
+somewhat different indentation is used.
+
+An indention level of 3 is used in the code, while the text in the config-
+options should have an indention-level of 2 to indicate dependencies. The
+latter only applies to bool/tristate options. For other options, just use
+common sense. An example:
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM
+ if [ "$CONFIG_BOOM" != "n" ]; then
+ bool ' Output nice messages when you explode' CONFIG_CHEER
+ fi
+fi
+
+Generally, CONFIG_EXPERIMENTAL should surround all options not considered
+stable. All options that are known to trash data (experimental write-
+support for file-systems, for instance) should be denoted (DANGEROUS), other
+Experimental options should be denoted (EXPERIMENTAL).
+
+
+ Chapter 8: Data structures
+
+Data structures that have visibility outside the single-threaded
+environment they are created and destroyed in should always have
+reference counts. In the kernel, garbage collection doesn't exist (and
+outside the kernel garbage collection is slow and inefficient), which
+means that you absolutely _have_ to reference count all your uses.
+
+Reference counting means that you can avoid locking, and allows multiple
+users to have access to the data structure in parallel - and not having
+to worry about the structure suddenly going away from under them just
+because they slept or did something else for a while.
+
+Note that locking is _not_ a replacement for reference counting.
+Locking is used to keep data structures coherent, while reference
+counting is a memory management technique. Usually both are needed, and
+they are not to be confused with each other.
+
+Many data structures can indeed have two levels of reference counting,
+when there are users of different "classes". The subclass count counts
+the number of subclass users, and decrements the global count just once
+when the subclass count goes to zero.
+
+Examples of this kind of "multi-reference-counting" can be found in
+memory management ("struct mm_struct": mm_users and mm_count), and in
+filesystem code ("struct super_block": s_count and s_active).
+
+Remember: if another thread can find your data structure, and you don't
+have a reference count on it, you almost certainly have a bug.
diff --git a/demos/applications/mandelbrot/gfxconf.h b/demos/applications/mandelbrot/gfxconf.h
new file mode 100644
index 00000000..7eaacc50
--- /dev/null
+++ b/demos/applications/mandelbrot/gfxconf.h
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP FALSE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/applications/mandelbrot/main.c b/demos/applications/mandelbrot/main.c
new file mode 100644
index 00000000..2fe1141d
--- /dev/null
+++ b/demos/applications/mandelbrot/main.c
@@ -0,0 +1,79 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+void mandelbrot(float x1, float y1, float x2, float y2) {
+ unsigned int i,j, width, height;
+ uint16_t iter;
+ color_t color;
+ float fwidth, fheight;
+
+ float sy = y2 - y1;
+ float sx = x2 - x1;
+ const int MAX = 512;
+
+ width = (unsigned int)gdispGetWidth();
+ height = (unsigned int)gdispGetHeight();
+ fwidth = width;
+ fheight = height;
+
+ for(i = 0; i < width; i++) {
+ for(j = 0; j < height; j++) {
+ float cy = j * sy / fheight + y1;
+ float cx = i * sx / fwidth + x1;
+ float x=0.0f, y=0.0f, xx=0.0f, yy=0.0f;
+ for(iter=0; iter <= MAX && xx+yy<4.0f; iter++) {
+ xx = x*x;
+ yy = y*y;
+ y = 2.0f*x*y + cy;
+ x = xx - yy + cx;
+ }
+ //color = ((iter << 8) | (iter&0xFF));
+ color = RGB2COLOR(iter<<7, iter<<4, iter);
+ gdispDrawPixel(i, j, color);
+ }
+ }
+}
+
+int main(void) {
+ float cx, cy;
+ float zoom = 1.0f;
+
+ halInit();
+ chSysInit();
+
+ gdispInit();
+
+ /* where to zoom in */
+ cx = -0.086f;
+ cy = 0.85f;
+
+ while(TRUE) {
+ mandelbrot(-2.0f*zoom+cx, -1.5f*zoom+cy, 2.0f*zoom+cx, 1.5f*zoom+cy);
+
+ zoom *= 0.7f;
+ if(zoom <= 0.00001f)
+ zoom = 1.0f;
+ }
+}
+
diff --git a/demos/applications/notepad/gfxconf.h b/demos/applications/notepad/gfxconf.h
new file mode 100644
index 00000000..45413580
--- /dev/null
+++ b/demos/applications/notepad/gfxconf.h
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_CIRCLE TRUE
+#define GDISP_NEED_ELLIPSE FALSE
+#define GDISP_NEED_ARC FALSE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/applications/notepad/main.c b/demos/applications/notepad/main.c
new file mode 100644
index 00000000..919aaafc
--- /dev/null
+++ b/demos/applications/notepad/main.c
@@ -0,0 +1,113 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#define COLOR_SIZE 20
+#define PEN_SIZE 20
+#define OFFSET 3
+
+#define COLOR_BOX(a) (ev.x >= a && ev.x <= a + COLOR_SIZE)
+#define PEN_BOX(a) (ev.y >= a && ev.y <= a + COLOR_SIZE)
+#define GET_COLOR(a) (COLOR_BOX(a * COLOR_SIZE + OFFSET))
+#define GET_PEN(a) (PEN_BOX(a * 2 * PEN_SIZE + OFFSET))
+#define DRAW_COLOR(a) (a * COLOR_SIZE + OFFSET)
+#define DRAW_PEN(a) (a * 2 * PEN_SIZE + OFFSET)
+#define DRAW_AREA(x, y) (x >= PEN_SIZE + OFFSET + 3 && x <= gdispGetWidth() && \
+ y >= COLOR_SIZE + OFFSET + 3 && y <= gdispGetHeight())
+
+void drawScreen(void) {
+ char *msg = "ChibiOS/GFX";
+ font_t font1, font2;
+
+ font1 = gdispOpenFont("UI2 Double");
+ font2 = gdispOpenFont("LargeNumbers");
+
+ gdispClear(White);
+ gdispDrawString(gdispGetWidth()-gdispGetStringWidth(msg, font1)-3, 3, msg, font1, Black);
+
+ /* colors */
+ gdispFillArea(0 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Black); /* Black */
+ gdispFillArea(1 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Red); /* Red */
+ gdispFillArea(2 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Yellow); /* Yellow */
+ gdispFillArea(3 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Green); /* Green */
+ gdispFillArea(4 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Blue); /* Blue */
+ gdispDrawBox (5 * COLOR_SIZE + 3, 3, COLOR_SIZE, COLOR_SIZE, Black); /* White */
+
+ /* pens */
+ gdispDrawString(OFFSET * 2, DRAW_PEN(1), "1", font2, Black);
+ gdispDrawString(OFFSET * 2, DRAW_PEN(2), "2", font2, Black);
+ gdispDrawString(OFFSET * 2, DRAW_PEN(3), "3", font2, Black);
+ gdispDrawString(OFFSET * 2, DRAW_PEN(4), "4", font2, Black);
+ gdispDrawString(OFFSET * 2, DRAW_PEN(5), "5", font2, Black);
+
+ gdispCloseFont(font1);
+ gdispCloseFont(font2);
+}
+
+GEventMouse ev;
+
+int main(void) {
+ color_t color = Black;
+ uint16_t pen = 0;
+
+ halInit();
+ chSysInit();
+
+ gdispInit();
+ ginputGetMouse(0);
+ gdispSetOrientation(GDISP_ROTATE_90);
+
+ drawScreen();
+
+ while (TRUE) {
+ ginputGetMouseStatus(0, &ev);
+ if (!(ev.current_buttons & GINPUT_MOUSE_BTN_LEFT))
+ continue;
+
+ /* inside color box ? */
+ if(ev.y >= OFFSET && ev.y <= COLOR_SIZE) {
+ if(GET_COLOR(0)) color = Black;
+ else if(GET_COLOR(1)) color = Red;
+ else if(GET_COLOR(2)) color = Yellow;
+ else if(GET_COLOR(3)) color = Green;
+ else if(GET_COLOR(4)) color = Blue;
+ else if(GET_COLOR(5)) color = White;
+
+ /* inside pen box ? */
+ } else if(ev.x >= OFFSET && ev.x <= PEN_SIZE) {
+ if(GET_PEN(1)) pen = 0;
+ else if(GET_PEN(2)) pen = 1;
+ else if(GET_PEN(3)) pen = 2;
+ else if(GET_PEN(4)) pen = 3;
+ else if(GET_PEN(5)) pen = 4;
+
+ /* inside drawing area ? */
+ } else if(DRAW_AREA(ev.x, ev.y)) {
+ if(pen == 0)
+ gdispDrawPixel(ev.x, ev.y, color);
+ else
+ gdispFillCircle(ev.x, ev.y, pen, color);
+ }
+ }
+}
+
diff --git a/demos/benchmarks/gfxconf.h b/demos/benchmarks/gfxconf.h
new file mode 100644
index 00000000..e96bf5fd
--- /dev/null
+++ b/demos/benchmarks/gfxconf.h
@@ -0,0 +1,41 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION FALSE
+#define GDISP_NEED_CLIP FALSE
+#define GDISP_NEED_TEXT TRUE
+#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 TRUE
+#define GDISP_NEED_MULTITHREAD FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+#endif /* _GFXCONF_H */
+
diff --git a/demos/benchmarks/main.c b/demos/benchmarks/main.c
new file mode 100644
index 00000000..9bd3cef3
--- /dev/null
+++ b/demos/benchmarks/main.c
@@ -0,0 +1,146 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "chprintf.h"
+#include "stdlib.h"
+#include "string.h"
+#include "gfx.h"
+
+#define SCB_DEMCR (*(volatile unsigned *)0xE000EDFC)
+#define CPU_RESET_CYCLECOUNTER do { SCB_DEMCR = SCB_DEMCR | 0x01000000; \
+DWT_CYCCNT = 0; \
+DWT_CTRL = DWT_CTRL | 1 ; } while(0)
+
+static int uitoa(unsigned int value, char * buf, int max) {
+ int n = 0;
+ int i = 0;
+ unsigned int tmp = 0;
+
+ if (NULL == buf)
+ return -3;
+
+ if (2 > max)
+ return -4;
+
+ i=1;
+ tmp = value;
+ if (0 > tmp) {
+ tmp *= -1;
+ i++;
+ }
+ for (;;) {
+ tmp /= 10;
+ if (0 >= tmp)
+ break;
+ i++;
+ }
+ if (i >= max) {
+ buf[0] = '?';
+ buf[1] = 0x0;
+ return 2;
+ }
+
+ n = i;
+ tmp = value;
+ if (0 > tmp) {
+ tmp *= -1;
+ }
+ buf[i--] = 0x0;
+ for (;;) {
+ buf[i--] = (tmp % 10) + '0';
+ tmp /= 10;
+ if (0 >= tmp) {
+ break;
+ }
+ }
+ if (-1 != i) {
+ buf[i--] = '-';
+ }
+
+ return n;
+}
+
+void benchmark(void) {
+ uint32_t i, pixels, ms, pps;
+ char pps_str[25];
+ coord_t height, width, rx, ry, rcx, rcy;
+ color_t random_color;
+ font_t font;
+
+ gdispSetOrientation(GDISP_ROTATE_90);
+ gdispClear(Black);
+
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+ font = gdispOpenFont("UI2 Double");
+
+ gdispDrawStringBox(0, 0, width, 30, "ChibiOS/GFX - Benchmark", font, White, justifyCenter);
+
+ font = gdispOpenFont("UI2");
+ gdispDrawStringBox(0, height/2, width, 30, "5000 random rectangles", font, White, justifyCenter);
+
+ chThdSleepMilliseconds(3000);
+
+ /* seed for the rand() */
+ srand(DWT_CYCCNT);
+ pixels = 0;
+
+ CPU_RESET_CYCLECOUNTER;
+
+ for (i = 0; i < 5000; i++) {
+ random_color = (rand() % 65535);
+ rx = (rand() % (width-10));
+ ry = (rand() % (height-10));
+ rcx = (rand() % ((width-rx)-10))+10;
+ rcy = (rand() % ((height-ry)-10))+10;
+
+ gdispFillArea(rx, ry, rcx, rcy, random_color);
+ pixels += (rcx+1)*(rcy+1);
+ }
+
+ ms = DWT_CYCCNT / 168000;
+ pps = (float)pixels/((float)ms/1000.0f);
+
+ memset (pps_str, 0, sizeof(pps_str));
+ uitoa(pps, pps_str, sizeof(pps_str));
+ strcat(pps_str, " Pixels/s");
+
+ font = gdispOpenFont("UI2 Double");
+ gdispClear(Black);
+ gdispDrawStringBox(0, 0, width, 30, "ChibiOS/GFX - Benchmark", font, White, justifyCenter);
+ gdispDrawStringBox(0, height/2, width, 30, pps_str, font, White, justifyCenter);
+ //gdispDrawString(20, height/2, pps_str, font, White);
+}
+
+int main(void) {
+ halInit();
+ chSysInit();
+ gdispInit();
+
+ benchmark();
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+
+ return 0;
+}
diff --git a/demos/modules/console/gfxconf.h b/demos/modules/console/gfxconf.h
new file mode 100644
index 00000000..254bf181
--- /dev/null
+++ b/demos/modules/console/gfxconf.h
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL TRUE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_CONSOLE TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/console/main.c b/demos/modules/console/main.c
new file mode 100644
index 00000000..4efe9d0a
--- /dev/null
+++ b/demos/modules/console/main.c
@@ -0,0 +1,87 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "chprintf.h"
+#include "gfx.h"
+
+/* The handles for our three consoles */
+GHandle GW1, GW2, GW3;
+
+/* The streams for our three consoles */
+BaseSequentialStream *S1, *S2, *S3;
+
+int main(void) {
+ uint8_t i;
+ font_t font1, font2;
+
+ halInit();
+ chSysInit();
+
+ /* initialize and clear the display */
+ gdispInit();
+ gdispClear(Black);
+ font1 = gdispOpenFont("UI2 Double");
+ font2 = gdispOpenFont("Small");
+
+ /* create the three console windows and set a font for each */
+ GW1 = gwinCreateConsole(NULL, 0, 0, gdispGetWidth(), gdispGetHeight()/2, font1);
+ GW2 = gwinCreateConsole(NULL, 0, gdispGetHeight()/2, gdispGetWidth()/2, gdispGetHeight(), font2);
+ GW3 = gwinCreateConsole(NULL, gdispGetWidth()/2, gdispGetHeight()/2, gdispGetWidth(), gdispGetHeight(), font2);
+
+ /* Set the fore- and background colors for each console */
+ gwinSetColor(GW1, Green);
+ gwinSetBgColor(GW1, Black);
+ gwinSetColor(GW2, White);
+ gwinSetBgColor(GW2, Blue);
+ gwinSetColor(GW3, Black);
+ gwinSetBgColor(GW3, Red);
+
+ /* clear all console windows - to set background */
+ gwinClear(GW1);
+ gwinClear(GW2);
+ gwinClear(GW3);
+
+ /* receive the stream pointers of each console */
+ S1 = gwinGetConsoleStream(GW1);
+ S2 = gwinGetConsoleStream(GW2);
+ S3 = gwinGetConsoleStream(GW3);
+
+ /* Output some data on the first console */
+ for(i = 0; i < 10; i++) {
+ chprintf(S1, "Hello ChibiOS/GFX!\r\n");
+ }
+
+ /* Output some data on the second console */
+ for(i = 0; i < 16; i++) {
+ chprintf(S2, "Message Nr.: %d\r\n", i+1);
+ }
+
+ /* Output some data on the third console */
+ for(i = 0; i < 18; i++) {
+ chprintf(S3, "Message Nr.: %d\r\n", i+1);
+ }
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+}
+
diff --git a/demos/modules/gdisp/gdisp_basics/gfxconf.h b/demos/modules/gdisp/gdisp_basics/gfxconf.h
new file mode 100644
index 00000000..498046b4
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_basics/gfxconf.h
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT 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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gdisp/gdisp_basics/main.c b/demos/modules/gdisp/gdisp_basics/main.c
new file mode 100644
index 00000000..fa0bef45
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_basics/main.c
@@ -0,0 +1,52 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+int main(void) {
+ coord_t width, height;
+ coord_t i, j;
+
+ halInit();
+ chSysInit();
+
+ /* Initialize and clear the display */
+ gdispInit();
+ gdispClear(Black);
+
+ // Get the screen size
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+
+ // Code Here
+ gdispDrawBox(10, 10, width/2, height/2, Yellow);
+ gdispFillArea(width/2, height/2, width/2-10, height/2-10, Blue);
+ gdispDrawLine(5, 30, width-50, height-40, Red);
+
+ for(i = 5, j = 0; i < width && j < height; i += 7, j += i/20)
+ gdispDrawPixel (i, j, White);
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+}
+
diff --git a/demos/modules/gdisp/gdisp_circles/gfxconf.h b/demos/modules/gdisp/gdisp_circles/gfxconf.h
new file mode 100644
index 00000000..00d88e48
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_circles/gfxconf.h
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT 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 TRUE
+#define GDISP_NEED_ELLIPSE TRUE
+#define GDISP_NEED_ARC TRUE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL FALSE
+#define GDISP_NEED_MULTITHREAD FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gdisp/gdisp_circles/main.c b/demos/modules/gdisp/gdisp_circles/main.c
new file mode 100644
index 00000000..45764d4f
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_circles/main.c
@@ -0,0 +1,51 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+int main(void) {
+ coord_t width, height;
+
+ halInit();
+ chSysInit();
+
+ /* Initialize and clear the display */
+ gdispInit();
+ gdispClear(Black);
+
+ // Get the screen size
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+
+ // Code Here
+ gdispDrawCircle(width/2, height/2, 20, Yellow);
+ gdispFillCircle (width/4, height/4, 50, Blue);
+ gdispFillEllipse (width-100, height-100, 30, 60, Red);
+ gdispDrawEllipse (width-100, height-100, 50, 20, Yellow);
+ gdispDrawArc(width-width/8, height/8, 30, 10, 70, Gray);
+ gdispFillArc(width/8, height/8, 30, 10, 70, Gray);
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+}
+
diff --git a/demos/modules/gdisp/gdisp_text/gfxconf.h b/demos/modules/gdisp/gdisp_text/gfxconf.h
new file mode 100644
index 00000000..a928806b
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_text/gfxconf.h
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gdisp/gdisp_text/main.c b/demos/modules/gdisp/gdisp_text/main.c
new file mode 100644
index 00000000..4dc45f71
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_text/main.c
@@ -0,0 +1,72 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+int main(void) {
+ coord_t width, height;
+ font_t font1, font2, font3, font4;
+ const char *msg;
+
+ halInit();
+ chSysInit();
+
+ /* Initialize and clear the display */
+ gdispInit();
+ gdispClear(Black);
+
+ // Get the screen size
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+
+ // Get the fonts we want to use
+ font1 = gdispOpenFont("UI2");
+ font2 = gdispOpenFont("UI2 Double");
+ font3 = gdispOpenFont("UI2 Narrow");
+ font4 = gdispOpenFont("LargeNumbers");
+
+ // Display large numbers on the right (measuring the string)
+ msg = "123456";
+ gdispDrawString(width-gdispGetStringWidth(msg, font4)-3, 3, msg, font4, Green);
+
+ // Display the font name under it.
+ msg = gdispGetFontName(font4);
+ gdispDrawString(width-gdispGetStringWidth(msg, font1)-3, 20, msg, font1, Green);
+
+ // Demonstrate our other fonts
+ gdispDrawString(10, 10, "Writing with Font 'UI2'", font1, Yellow);
+ gdispFillString(10, 35, "Writing with Font 'UI2 Double'", font2, Red, White);
+ gdispDrawStringBox(0, 50, width, 40, "Writing with Font 'UI2 Narrow'", font3, Red, justifyCenter);
+ gdispFillStringBox(0, 90, width, 40, "Filled Centered", font3, Pink, Gray, justifyCenter);
+
+ // Clean up the fonts
+ gdispCloseFont(font1);
+ gdispCloseFont(font2);
+ gdispCloseFont(font3);
+ gdispCloseFont(font4);
+
+ // Wait forever
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+}
+
diff --git a/demos/modules/ginput_touch_driver_test/gfxconf.h b/demos/modules/ginput_touch_driver_test/gfxconf.h
new file mode 100644
index 00000000..05f685dd
--- /dev/null
+++ b/demos/modules/ginput_touch_driver_test/gfxconf.h
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#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
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_BUTTON TRUE
+#define GWIN_NEED_CONSOLE TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/ginput_touch_driver_test/main.c b/demos/modules/ginput_touch_driver_test/main.c
new file mode 100644
index 00000000..a77e0b3f
--- /dev/null
+++ b/demos/modules/ginput_touch_driver_test/main.c
@@ -0,0 +1,349 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "chprintf.h"
+#include "gfx.h"
+
+static GConsoleObject gc;
+static GButtonObject gNext;
+static GButtonObject gPrev;
+static GListener gl;
+
+/*------------------------------------------------------------------------*
+ * GINPUT Touch Driver Calibrator. *
+ *------------------------------------------------------------------------*/
+int main(void) {
+ GSourceHandle gs, gsNext, gsPrev;
+ GEvent *pe;
+ GEventMouse *pem;
+ GEventGWinButton *peb;
+ coord_t swidth, sheight;
+ GHandle ghc, ghNext, ghPrev;
+ BaseSequentialStream *gp;
+ GEventType deviceType;
+ font_t font;
+
+ halInit(); // Initialise the Hardware
+ chSysInit(); // Initialize the OS
+ gdispInit(); // Initialize the display
+
+ // Get the display dimensions
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+ ghNext = ghPrev = 0;
+
+ // Create our title
+ font = gdispOpenFont("UI2");
+ gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", font, Red, White, justifyLeft);
+
+ // Create our main display window
+ ghc = gwinCreateConsole(&gc, 0, 20, swidth, sheight-20, font);
+ gwinClear(ghc);
+ gp = gwinGetConsoleStream(ghc);
+
+ // Initialize the mouse in our special no calibration mode.
+ geventListenerInit(&gl);
+ gs = ginputGetMouse(9999);
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ /*
+ * Test: Device Type
+ */
+
+StepDeviceType:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n1. DEVICE TYPE\n\n");
+
+ pem = (GEventMouse *)&gl.event;
+ ginputGetMouseStatus(0, pem);
+ deviceType = pem->type;
+
+ gwinSetColor(ghc, White);
+ chprintf(gp, "This is detected as a %s device\n\n",
+ deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN"));
+
+ if (ghNext)
+ chprintf(gp, "Press Next or Back to continue.\n");
+ else if (deviceType == GEVENT_MOUSE)
+ chprintf(gp, "Click the mouse button to move on to the next test.\n");
+ else
+ chprintf(gp, "Press and release your finger to move on to the next test.\n");
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepClickJitter;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
+ break;
+ }
+ }
+
+ /*
+ * Test: Mouse raw reading jitter
+ */
+
+StepRawJitter:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n");
+
+ gwinSetColor(ghc, White);
+ if (deviceType == GEVENT_MOUSE)
+ chprintf(gp, "Press and hold the mouse button.\n\n");
+ else
+ chprintf(gp, "Press and hold on the surface.\n\n");
+ chprintf(gp, "Numbers will display in this window.\n"
+ "Ensure that values don't jump around very much when your finger is stationary.\n\n"
+ "Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n");
+
+ if (ghNext)
+ chprintf(gp, "Press Next or Back to continue.\n");
+ else if (deviceType == GEVENT_MOUSE)
+ chprintf(gp, "Release the mouse button to move on to the next test.\n");
+ else
+ chprintf(gp, "Release your finger to move on to the next test.\n");
+
+ // For this test turn on ALL mouse movement events
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepDeviceType;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
+ chprintf(gp, "%u:%u\n", pem->x, pem->y);
+ if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
+ break;
+ }
+ }
+
+ // Reset to just changed movements.
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ /*
+ * Test: Calibration
+ */
+
+StepCalibrate:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n");
+ gwinSetColor(ghc, Gray);
+ chprintf(gp, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n");
+ gwinSetColor(ghc, White);
+ chprintf(gp, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
+ "If the calibration repeatedly fails, increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n\n");
+
+ if (ghNext)
+ chprintf(gp, "Press Next to start the calibration.\n");
+ else if (deviceType == GEVENT_MOUSE)
+ chprintf(gp, "Click the mouse button to start the calibration.\n");
+ else
+ chprintf(gp, "Press and release your finger to start the calibration.\n");
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepRawJitter;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
+ break;
+ }
+ }
+
+ // Calibrate
+ ginputCalibrateMouse(0);
+
+ /* From now on we can use Next and Previous Buttons */
+ if (!ghNext) {
+
+ ghNext = gwinCreateButton(&gNext, swidth-50, 0, 50, 20, font, GBTN_NORMAL);
+ gwinSetButtonText(ghNext, "Next", FALSE);
+ gsNext = gwinGetButtonSource(ghNext);
+ geventAttachSource(&gl, gsNext, 0);
+ gwinAttachButtonMouseSource(ghNext, gs);
+
+ ghPrev = gwinCreateButton(&gPrev, swidth-100, 0, 50, 20, font, GBTN_NORMAL);
+ gwinSetButtonText(ghPrev, "Back", FALSE);
+ gsPrev = gwinGetButtonSource(ghPrev);
+ geventAttachSource(&gl, gsPrev, 0);
+ gwinAttachButtonMouseSource(ghPrev, gs);
+
+#if 0
+ {
+ GSourceHandle gsButton1, gsButton2;
+
+ // Attach a couple of hardware toggle buttons to our Next and Back buttons as well.
+ // We can always use the mouse to trigger the buttons if you don't want to use hardware toggles.
+ // This code depends on your hardware. Turn it on only if you have
+ // defined a board definition for your toggle driver. Then change
+ // the next two lines to be correct for your hardware. The values
+ // below are correct for the Win32 toggle driver.
+ gsButton1 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY1);
+ gsButton2 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY2);
+ gwinAttachButtonToggleSource(ghNext, gsButton2);
+ gwinAttachButtonToggleSource(ghPrev, gsButton1);
+ }
+#endif
+ }
+
+ // Calibration used the whole screen - re-establish our title
+ gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", font, Green, White, justifyLeft);
+ gwinButtonDraw(ghNext);
+ gwinButtonDraw(ghPrev);
+
+ /*
+ * Test: Mouse movement jitter
+ */
+
+StepJitter:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n");
+
+ gwinSetColor(ghc, White);
+ if (deviceType == GEVENT_MOUSE)
+ chprintf(gp, "Press and hold the mouse button and move around as if to draw.\n\n");
+ else
+ chprintf(gp, "Press firmly on the surface and move around as if to draw.\n\n");
+
+ chprintf(gp, "Dots will display in this window. Ensure that when you stop moving your finger that "
+ "new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n"
+ "Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n");
+ chprintf(gp, "Press Next or Back to continue.\n\n");
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepCalibrate;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
+ chprintf(gp, ".");
+ }
+ }
+
+ /*
+ * Test: Polling frequency
+ */
+
+StepPolling:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
+
+ gwinSetColor(ghc, White);
+ chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
+ chprintf(gp, "A green line will follow your finger.\n"
+ "Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without "
+ "gaps that are too big.\nDecreasing the value increases CPU usage.\n"
+ "About 25 (millisecs) normally produces good results."
+ "This test can be ignored for interrupt driven drivers.\n\n");
+ chprintf(gp, "Press Next or Back to continue.\n\n");
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepJitter;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
+ gdispDrawPixel(pem->x, pem->y, Green);
+ }
+ }
+
+ /*
+ * Test: Click Jitter
+ */
+
+StepClickJitter:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
+
+ gwinSetColor(ghc, White);
+ chprintf(gp, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
+ chprintf(gp, "For a mouse click with the left and right buttons.\n\n");
+ chprintf(gp, "Dots will display in this window. A yellow dash is a left (or short) click. "
+ "A red x is a right (or long) click.\n\n"
+ "Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n"
+ "Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n"
+ "TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n"
+ "Note: moving your finger (mouse) during a click cancels it.\n\n");
+ chprintf(gp, "This is the last test but you can press Next or Back to continue.\n\n");
+
+ while(1) {
+ pe = geventEventWait(&gl, TIME_INFINITE);
+ if (pe->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pe;
+ if (peb->button == ghPrev)
+ goto StepPolling;
+ if (peb->button == ghNext)
+ break;
+ }
+ if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
+ pem = (GEventMouse *)pe;
+ if ((pem->meta & GMETA_MOUSE_CLICK)) {
+ gwinSetColor(ghc, Yellow);
+ chprintf(gp, "-");
+ }
+ if ((pem->meta & GMETA_MOUSE_CXTCLICK)) {
+ gwinSetColor(ghc, Red);
+ chprintf(gp, "x");
+ }
+ }
+ }
+
+ // Can't let this really exit
+ goto StepDeviceType;
+}
diff --git a/demos/modules/graph/gfxconf.h b/demos/modules/graph/gfxconf.h
new file mode 100644
index 00000000..4f4258ed
--- /dev/null
+++ b/demos/modules/graph/gfxconf.h
@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT 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 TRUE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_GRAPH TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/graph/main.c b/demos/modules/graph/main.c
new file mode 100644
index 00000000..544d4c2b
--- /dev/null
+++ b/demos/modules/graph/main.c
@@ -0,0 +1,71 @@
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+#include "math.h"
+
+const GGraphPoint data[5] = {
+ { -40, -40 },
+ { 70, 40 },
+ { 140, 60 },
+ { 210, 60 },
+ { 280, 200 }
+};
+
+GGraphObject g;
+
+GGraphStyle GraphStyle1 = {
+ { GGRAPH_POINT_DOT, 0, Blue }, // point
+ { GGRAPH_LINE_NONE, 2, Gray }, // line
+ { GGRAPH_LINE_SOLID, 0, White }, // x axis
+ { GGRAPH_LINE_SOLID, 0, White }, // y axis
+ { GGRAPH_LINE_DASH, 5, Gray, 50 }, // x grid
+ { GGRAPH_LINE_DOT, 7, Yellow, 50 }, // y grid
+ GWIN_GRAPH_STYLE_POSITIVE_AXIS_ARROWS // flags
+};
+
+GGraphStyle GraphStyle2 = {
+ { GGRAPH_POINT_SQUARE, 5, Red }, // point
+ { GGRAPH_LINE_DOT, 2, Pink }, // line
+ { GGRAPH_LINE_SOLID, 0, White }, // x axis
+ { GGRAPH_LINE_SOLID, 0, White }, // y axis
+ { GGRAPH_LINE_DASH, 5, Gray, 50 }, // x grid
+ { GGRAPH_LINE_DOT, 7, Yellow, 50 }, // y grid
+ GWIN_GRAPH_STYLE_POSITIVE_AXIS_ARROWS // flags
+};
+
+int main(void) {
+ GHandle gh;
+ uint16_t i;
+
+ halInit();
+ chSysInit();
+
+ gdispInit();
+ gdispClear(Black);
+
+ gh = gwinCreateGraph(&g, 0, 0, gdispGetWidth(), gdispGetHeight());
+
+ gwinGraphSetOrigin(gh, gwinGetWidth(gh)/2, gwinGetHeight(gh)/2);
+ gwinGraphSetStyle(gh, &GraphStyle1);
+ gwinGraphDrawAxis(gh);
+
+ for(i = 0; i < gwinGetWidth(gh); i++)
+ gwinGraphDrawPoint(gh, i-gwinGetWidth(gh)/2, 80*sin(2*0.2*M_PI*i/180));
+
+ gwinGraphStartSet(gh);
+ GraphStyle1.point.color = Green;
+ gwinGraphSetStyle(gh, &GraphStyle1);
+
+ for(i = 0; i < gwinGetWidth(gh)*5; i++)
+ gwinGraphDrawPoint(gh, i/5-gwinGetWidth(gh)/2, 95*sin(2*0.2*M_PI*i/180));
+
+ gwinGraphStartSet(gh);
+ gwinGraphSetStyle(gh, &GraphStyle2);
+
+ gwinGraphDrawPoints(gh, data, sizeof(data)/sizeof(data[0]));
+
+ while(TRUE) {
+ chThdSleepMilliseconds(100);
+ }
+}
+
diff --git a/demos/modules/graph/result-640x480.gif b/demos/modules/graph/result-640x480.gif
new file mode 100644
index 00000000..6fc8b30c
Binary files /dev/null and b/demos/modules/graph/result-640x480.gif differ
diff --git a/demos/modules/gtimer/gfxconf.h b/demos/modules/gtimer/gfxconf.h
new file mode 100644
index 00000000..e814bd18
--- /dev/null
+++ b/demos/modules/gtimer/gfxconf.h
@@ -0,0 +1,19 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP FALSE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gtimer/main.c b/demos/modules/gtimer/main.c
new file mode 100644
index 00000000..ae7c2c92
--- /dev/null
+++ b/demos/modules/gtimer/main.c
@@ -0,0 +1,59 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+GTimer GT1, GT2;
+
+void callback1(void* arg) {
+ (void)arg;
+
+ palTogglePad(GPIOD, GPIOD_LED3);
+}
+
+void callback2(void* arg) {
+ (void)arg;
+
+ palSetPad(GPIOD, GPIOD_LED4);
+}
+
+int main(void) {
+ halInit();
+ chSysInit();
+
+ /* initialize the timers */
+ gtimerInit(>1);
+ gtimerInit(>2);
+
+ /* continious mode - callback1() called without any argument every 250ms */
+ gtimerStart(>1, callback1, NULL, TRUE, 250);
+
+ /* single shot mode - callback2() called without any argument once after 1s */
+ gtimerStart(>2, callback2, NULL, FALSE, 1000);
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+
+ return 0;
+}
+
diff --git a/demos/modules/tdisp/gfxconf.h b/demos/modules/tdisp/gfxconf.h
new file mode 100644
index 00000000..5077e010
--- /dev/null
+++ b/demos/modules/tdisp/gfxconf.h
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_TDISP TRUE
+#define GFX_USE_GDISP FALSE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP subsystem */
+#define GDISP_NEED_VALIDATION FALSE
+#define GDISP_NEED_CLIP FALSE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Features for the TDISP subsystem */
+#define TDISP_NEED_4BIT_MODE TRUE
+#define TDISP_NEED_8BIT_MODE FALSE
+
+/* Builtin Fonts */
+#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
+
+/* GWIN */
+#define GWIN_NEED_CONSOLE FALSE
+#define GWIN_NEED_GRAPH FALSE
+#define GWIN_NEED_BUTTON FALSE
+#define GWIN_NEED_DIAL FALSE
+
+/* GINPUT */
+#define GINPUT_NEED_MOUSE FALSE
+
+#endif /* _GFXCONF_H */
+
diff --git a/demos/modules/tdisp/main.c b/demos/modules/tdisp/main.c
new file mode 100644
index 00000000..69ab7349
--- /dev/null
+++ b/demos/modules/tdisp/main.c
@@ -0,0 +1,67 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+int main(void) {
+ char charmap[8];
+
+ halInit();
+ chSysInit();
+
+ tdispInit();
+
+ /* reset cursor position and clear the screen */
+ tdispHome();
+ tdispClear();
+
+ /* set cursor position and draw single characters */
+ tdispSetCursor(4, 0);
+ tdispDrawChar('H');
+ tdispDrawChar('D');
+ tdispDrawChar('4');
+ tdispDrawChar('4');
+ tdispDrawChar('7');
+ tdispDrawChar('8');
+ tdispDrawChar('0');
+
+ /* draw a string to a given location */
+ tdispDrawStringLocation(0, 1, "chibios-gfx.com");
+
+ /* create and display a custom made character */
+ charmap[0] = 0b00000;
+ charmap[1] = 0b00100;
+ charmap[2] = 0b00010;
+ charmap[3] = 0b11111;
+ charmap[4] = 0b00010;
+ charmap[5] = 0b00100;
+ charmap[6] = 0b00000;
+ charmap[7] = 0b00000;
+ tdispCreateChar(0, charmap);
+ tdispHome();
+ tdispDrawChar(0);
+
+ while(TRUE) {
+ chThdSleepMilliseconds(250);
+ }
+}
+
diff --git a/demos/modules/window/gfxconf.h b/demos/modules/window/gfxconf.h
new file mode 100644
index 00000000..c8080075
--- /dev/null
+++ b/demos/modules/window/gfxconf.h
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT 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 TRUE
+#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 FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/window/main.c b/demos/modules/window/main.c
new file mode 100644
index 00000000..e9cf21e0
--- /dev/null
+++ b/demos/modules/window/main.c
@@ -0,0 +1,67 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+/* The handles for our two Windows */
+GHandle GW1, GW2;
+
+int main(void) {
+ halInit();
+ chSysInit();
+ coord_t i, j;
+
+ /* Initialize and clear the display */
+ gdispInit();
+ gdispClear(Lime);
+
+ /* Create two windows */
+ GW1 = gwinCreateWindow(NULL, 20, 10, 200, 150);
+ GW2 = gwinCreateWindow(NULL, 50, 190, 150, 100);
+
+ /* Set fore- and background colors for both windows */
+ gwinSetColor(GW1, Black);
+ gwinSetBgColor(GW1, White);
+ gwinSetColor(GW2, White);
+ gwinSetBgColor(GW2, Blue);
+
+ /* Clear both windows - to set background color */
+ gwinClear(GW1);
+ gwinClear(GW2);
+
+ gwinDrawLine (GW1, 5, 30, 150, 110);
+ for(i=5, j=0; i < 200 && j < 150; i+=3, j+=i/20)
+ gwinDrawPixel (GW1, i, j);
+
+ /*
+ * Draw two filled circles at the same coordinate
+ * of each window to demonstrate the relative coordinates
+ * of windows
+ */
+ gwinFillCircle(GW1, 20, 20, 15);
+ gwinFillCircle(GW2, 20, 20, 15);
+
+ while(TRUE) {
+ chThdSleepMilliseconds(500);
+ }
+}
+
diff --git a/demos/readme.txt b/demos/readme.txt
new file mode 100644
index 00000000..fbea2090
--- /dev/null
+++ b/demos/readme.txt
@@ -0,0 +1,4 @@
+This folder contains a few demos which explain how to use the library.
+
+Only the main files are contained. No compile-able projects
+
diff --git a/docs/rsc/layout.xml b/docs/rsc/layout.xml
new file mode 100644
index 00000000..a3cadb4f
--- /dev/null
+++ b/docs/rsc/layout.xml
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/main.dox b/docs/src/main.dox
new file mode 100644
index 00000000..8810abd0
--- /dev/null
+++ b/docs/src/main.dox
@@ -0,0 +1,37 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @mainpage ChibiOS/GFX
+ * @author Joel Bodenmann (joel@unormal.org).
+ *
+ * ChibiOS/GFX
+ * ChibiOS/GFX is an official add-on library for ChibiOS/RT to
+ * interface all different types of LCDs and touchscreens.
+ *
+ * Features
+ * - Modular design to reduce memory footprint
+ * - HAL abstractions allows it to easily write new drivers
+ * - Completely written in C, usable in C++ without any modifications
+ * - Supports hardware accelerated drawing by LCDs
+ * - Very flexible interfaces for calibration storage and more
+ * - We are having our own homepage: http://chibios-gfx.com
+ */
+
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
new file mode 100644
index 00000000..c4468b6d
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -0,0 +1,570 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9320/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_STM32_LCD)
+ #include "gdisp_lld_board_olimex_stm32_lcd.h"
+#else
+ #include "gdisp_lld_board.h"
+#endif
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* This controller is only ever used with a 240 x 320 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_WIDTH
+#endif
+
+#define GDISP_SCREEN_WIDTH 240
+#define GDISP_SCREEN_HEIGHT 320
+
+#define GDISP_INITIAL_CONTRAST 50
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+uint32_t DISPLAY_CODE;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+static __inline void lld_lcdDelay(uint16_t us) {
+ chThdSleepMicroseconds(us);
+}
+
+static __inline void lld_lcdWriteIndex(uint16_t index) {
+ GDISP_LLD(write_index)(index);
+}
+
+static __inline void lld_lcdWriteData(uint16_t data) {
+ GDISP_LLD(write_data)(data);
+}
+
+static __inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
+ GDISP_LLD(write_index)(lcdReg);
+ GDISP_LLD(write_data)(lcdRegValue);
+}
+
+static __inline uint16_t lld_lcdReadData(void) {
+ /* fix this! */
+ //return GDISP_LLD(read_data);
+ return GDISP_RAM;
+}
+
+static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
+ volatile uint16_t dummy;
+
+ GDISP_LLD(write_index)(lcdReg);
+ dummy = lld_lcdReadData();
+ (void)dummy;
+
+ return lld_lcdReadData();
+}
+
+static __inline void lld_lcdWriteStreamStart(void) {
+ lld_lcdWriteIndex(0x0022);
+}
+
+static __inline void lld_lcdWriteStreamStop(void) {
+
+}
+
+static __inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) {
+ uint16_t i;
+
+ for(i = 0; i < size; i++)
+ lld_lcdWriteData(buffer[i]);
+}
+
+static __inline void lld_lcdReadStreamStart(void) {
+ lld_lcdWriteIndex(0x0022);
+}
+
+static __inline void lld_lcdReadStreamStop(void) {
+
+}
+
+static __inline void lld_lcdReadStream(uint16_t *buffer, size_t size) {
+ uint16_t i;
+ volatile uint16_t dummy;
+
+ dummy = lld_lcdReadData();
+ (void)dummy;
+
+ for(i = 0; i < size; i++)
+ buffer[i] = lld_lcdReadData();
+}
+
+bool_t lld_gdisp_init(void) {
+ /* Initialise your display */
+ GDISP_LLD(init_board)();
+
+ /* Hardware reset */
+ GDISP_LLD(setpin_reset)(TRUE);
+ lld_lcdDelay(1000);
+ GDISP_LLD(setpin_reset)(FALSE);
+ lld_lcdDelay(1000);
+
+ DISPLAY_CODE = lld_lcdReadReg(0);
+ lld_lcdWriteReg(0x0000, 0x0001); //start Int. osc
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0001, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
+ lld_lcdWriteReg(0x0002, 0x0700); //select the line inversion
+ lld_lcdWriteReg(0x0003, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
+ lld_lcdWriteReg(0x0004, 0x0000); //Resize control(No resizing)
+ lld_lcdWriteReg(0x0008, 0x0202); //front and back porch 2 lines
+ lld_lcdWriteReg(0x0009, 0x0000); //select normal scan
+ lld_lcdWriteReg(0x000A, 0x0000); //display control 4
+ lld_lcdWriteReg(0x000C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
+ lld_lcdWriteReg(0x000D, 0x0000); //Frame marker position
+ lld_lcdWriteReg(0x000F, 0x0000); //selects clk, enable and sync signal polarity,
+ lld_lcdWriteReg(0x0010, 0x0000); //
+ lld_lcdWriteReg(0x0011, 0x0000); //power control 2 reference voltages = 1:1,
+ lld_lcdWriteReg(0x0012, 0x0000); //power control 3 VRH
+ lld_lcdWriteReg(0x0013, 0x0000); //power control 4 VCOM amplitude
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0010, 0x17B0); //power control 1 BT,AP
+ lld_lcdWriteReg(0x0011, 0x0137); //power control 2 DC,VC
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0012, 0x0139); //power control 3 VRH
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0013, 0x1d00); //power control 4 vcom amplitude
+ lld_lcdWriteReg(0x0029, 0x0011); //power control 7 VCOMH
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0030, 0x0007);
+ lld_lcdWriteReg(0x0031, 0x0403);
+ lld_lcdWriteReg(0x0032, 0x0404);
+ lld_lcdWriteReg(0x0035, 0x0002);
+ lld_lcdWriteReg(0x0036, 0x0707);
+ lld_lcdWriteReg(0x0037, 0x0606);
+ lld_lcdWriteReg(0x0038, 0x0106);
+ lld_lcdWriteReg(0x0039, 0x0007);
+ lld_lcdWriteReg(0x003c, 0x0700);
+ lld_lcdWriteReg(0x003d, 0x0707);
+ lld_lcdWriteReg(0x0020, 0x0000); //starting Horizontal GRAM Address
+ lld_lcdWriteReg(0x0021, 0x0000); //starting Vertical GRAM Address
+ lld_lcdWriteReg(0x0050, 0x0000); //Horizontal GRAM Start Position
+ lld_lcdWriteReg(0x0051, 0x00EF); //Horizontal GRAM end Position
+ lld_lcdWriteReg(0x0052, 0x0000); //Vertical GRAM Start Position
+ lld_lcdWriteReg(0x0053, 0x013F); //Vertical GRAM end Position
+ switch (DISPLAY_CODE) {
+ case 0x9320:
+ lld_lcdWriteReg(0x0060, 0x2700); //starts scanning from G1, and 320 drive lines
+ break;
+ case 0x9325:
+ lld_lcdWriteReg(0x0060, 0xA700); //starts scanning from G1, and 320 drive lines
+ break;
+ }
+
+ lld_lcdWriteReg(0x0061, 0x0001); //fixed base display
+ lld_lcdWriteReg(0x006a, 0x0000); //no scroll
+ lld_lcdWriteReg(0x0090, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
+ lld_lcdWriteReg(0x0092, 0x0000); //set gate output non-overlap period=0
+ lld_lcdWriteReg(0x0093, 0x0003); //set Source Output Position=3
+ lld_lcdWriteReg(0x0095, 0x0110); //RGB interface(Clocks per line period=16 clocks)
+ lld_lcdWriteReg(0x0097, 0x0110); //set Gate Non-overlap Period 0 locksc
+ lld_lcdWriteReg(0x0098, 0x0110); //
+ lld_lcdWriteReg(0x0007, 0x0173); //display On
+
+ // Turn on the backlight
+ GDISP_LLD(set_backlight)(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+
+ return TRUE;
+}
+
+static void lld_lcdSetCursor(uint16_t x, uint16_t y) {
+ uint32_t addr;
+
+ addr = y * 0x100 + x;
+
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0020, addr & 0xff); /* low addr */
+ lld_lcdWriteReg(0x0021, (addr >> 8) & 0x1ff); /* high addr */
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0020, (addr >> 8) & 0x1ff); /* low addr */
+ lld_lcdWriteReg(0x0021, addr & 0xff); /* high addr */
+ break;
+
+ case GDISP_ROTATE_180:
+ break;
+
+ case GDISP_ROTATE_270:
+ break;
+ }
+}
+
+static void lld_lcdSetViewPort(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0050, x);
+ lld_lcdWriteReg(0x0051, x + cx - 1);
+ lld_lcdWriteReg(0x0052, y);
+ lld_lcdWriteReg(0x0053, y + cy - 1);
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0050, y);
+ lld_lcdWriteReg(0x0051, y + cy - 1);
+ lld_lcdWriteReg(0x0052, x);
+ lld_lcdWriteReg(0x0053, x + cx - 1);
+ break;
+
+ case GDISP_ROTATE_180:
+ break;
+
+ case GDISP_ROTATE_270:
+ break;
+
+ }
+
+ lld_lcdSetCursor(x, y);
+}
+
+static __inline void lld_lcdResetViewPort(void) {
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ lld_lcdSetViewPort(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
+ break;
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ lld_lcdSetViewPort(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
+ break;
+ }
+}
+
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+ lld_lcdSetCursor(x, y);
+ lld_lcdWriteReg(0x0022, color);
+}
+
+#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
+ void lld_gdisp_clear(color_t color) {
+ unsigned i;
+
+ lld_lcdSetCursor(0, 0);
+ lld_lcdWriteStreamStart();
+
+ for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
+ lld_lcdWriteData(color);
+
+ lld_lcdWriteStreamStop();
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ unsigned i, area;
+
+ area = cx*cy;
+ lld_lcdSetViewPort(x, y, cx, cy);
+ lld_lcdWriteStreamStart();
+ for(i = 0; i < area; i++)
+ lld_lcdWriteData(color);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy;
+ unsigned lg;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ lld_lcdSetViewPort(x, y, cx, cy);
+ lld_lcdWriteStreamStart();
+
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ buffer += srcx + srcy * srccx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ lld_lcdWriteData(*buffer++);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+
+ lld_lcdSetCursor(x, y);
+ lld_lcdWriteStreamStart();
+
+ color = lld_lcdReadData();
+ color = lld_lcdReadData();
+
+ lld_lcdWriteStreamStop();
+
+ return color;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
+ coord_t row0, row1;
+ unsigned i, gap, abslines;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ abslines = lines < 0 ? -lines : lines;
+
+ if (abslines >= cy) {
+ abslines = cy;
+ gap = 0;
+ } else {
+ gap = cy - abslines;
+ for(i = 0; i < gap; i++) {
+ if(lines > 0) {
+ row0 = y + i + lines;
+ row1 = y + i;
+ } else {
+ row0 = (y - i - 1) + lines;
+ row1 = (y - i - 1);
+ }
+
+ /* read row0 into the buffer and then write at row1*/
+ lld_lcdSetViewPort(x, row0, cx, 1);
+ lld_lcdReadStreamStart();
+ lld_lcdReadStream(buf, cx);
+ lld_lcdReadStreamStop();
+
+ lld_lcdSetViewPort(x, row1, cx, 1);
+ lld_lcdWriteStreamStart();
+ lld_lcdWriteStream(buf, cx);
+ lld_lcdWriteStreamStop();
+ }
+ }
+
+ /* fill the remaining gap */
+ lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines);
+ lld_lcdWriteStreamStart();
+ gap = cx*abslines;
+ for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ void lld_gdisp_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_POWER:
+ if(GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ lld_lcdWriteReg(0x0007, 0x0000);
+ lld_lcdWriteReg(0x0010, 0x0000);
+ lld_lcdWriteReg(0x0011, 0x0000);
+ lld_lcdWriteReg(0x0012, 0x0000);
+ lld_lcdWriteReg(0x0013, 0x0000);
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ case powerOn:
+ //*************Power On sequence ******************//
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+ lld_lcdWriteReg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0012, 0x013C); /* VREG1OUT voltage */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdWriteReg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0007, 0x0173); /* 262K color and display ON */
+ GDISP_LLD(set_backlight)(GDISP.Backlight);
+ if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
+ lld_gdisp_init();
+ break;
+
+ case powerSleep:
+ lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ case powerDeepSleep:
+ lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+
+ case GDISP_CONTROL_ORIENTATION:
+ if(GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0001, 0x0100);
+ lld_lcdWriteReg(0x0003, 0x1038);
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0001, 0x0000);
+ lld_lcdWriteReg(0x0003, 0x1030);
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ case GDISP_ROTATE_180:
+ /* ToDo */
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_270:
+ /* ToDo */
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ default:
+ return;
+ }
+
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+
+ case GDISP_CONTROL_BACKLIGHT:
+ if((unsigned)value > 100) value = (void *)100;
+ GDISP_LLD(set_backlight)((unsigned)value);
+ GDISP.Backlight = (unsigned)value;
+ break;
+
+ default:
+ return;
+ }
+ }
+
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.mk b/drivers/gdisp/ILI9320/gdisp_lld.mk
new file mode 100644
index 00000000..bcdd3230
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/ILI9320
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_example.h b/drivers/gdisp/ILI9320/gdisp_lld_board_example.h
new file mode 100644
index 00000000..a79e557b
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_example.h
@@ -0,0 +1,59 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9320/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+static __inline void GDISP_LLD(init_board)(void) {
+ #error "ILI9320: You must implement the init_board routine for your board"
+}
+
+static __inline void GDISP_LLD(setpin_reset)(bool_t state) {
+ #error "ILI9320: You must implement setpin_reset routine for your board"
+}
+
+static __inline void GDISP_LLD(write_index)(uint16_t data) {
+ #error "ILI9320: You must implement write_index routine for your board"
+}
+
+static __inline void GDISP_LLD(write_data)(uint16_t data) {
+ #error "ILI9320: You must implement write_data routine for your board"
+}
+
+static __inline uint16_t GDISP_LLD(read_data)(void) {
+ #error "ILI9320: You must implement read_data routine for your board"
+}
+
+/* if not available, just ignore the argument and return */
+static __inline uint16_t GDISP_LLD(set_backlight)(uint8_t percentage) {
+ #error "ILI9320: You must implement set_backlight routine for your board"
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
new file mode 100644
index 00000000..a6d9d631
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
@@ -0,0 +1,85 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
+ * @brief GDISP Graphic Driver subsystem board interface for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
+
+static __inline void GDISP_LLD(init_board)(void) {
+ /* FSMC setup for F1 */
+ rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+ /* set pin modes */
+ IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
+ IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
+ palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL);
+
+ const unsigned char FSMC_Bank = 0;
+
+ /* FSMC timing */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
+
+ /* Bank1 NOR/SRAM control register configuration
+ * This is actually not needed as already set by default after reset */
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+}
+
+static __inline void GDISP_LLD(setpin_reset)(bool_t state) {
+ if(state)
+ palClearPad(GPIOE, GPIOE_TFT_RST);
+ else
+ palSetPad(GPIOE, GPIOE_TFT_RST);
+}
+
+static __inline void GDISP_LLD(write_index)(uint16_t reg) {
+ GDISP_REG = reg;
+}
+
+static __inline void GDISP_LLD(write_data)(uint16_t data) {
+ GDISP_RAM = data;
+}
+
+static __inline uint16_t GDISP_LLD(read_data)(void) {
+ return GDISP_RAM;
+}
+
+static __inline void GDISP_LLD(set_backlight)(uint8_t percent) {
+ if(percent == 100)
+ palClearPad(GPIOD, GPIOD_TFT_LIGHT);
+ else
+ palSetPad(GPIOD, GPIOD_TFT_LIGHT);
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
new file mode 100644
index 00000000..d55f2115
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9320/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_CONFIG_H
+#define GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "ILI9320"
+#define GDISP_LLD(x) gdisp_lld_##x##_ILI9320
+
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS FALSE
+#define GDISP_HARDWARE_SCROLL FALSE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9320/readme.txt b/drivers/gdisp/ILI9320/readme.txt
new file mode 100644
index 00000000..dcffe206
--- /dev/null
+++ b/drivers/gdisp/ILI9320/readme.txt
@@ -0,0 +1,15 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+
+ d) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_example.h file as a basis.
+ Currently known boards are:
+ Olimex STM32-LCD
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.mk
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
new file mode 100644
index 00000000..bc2b6dd5
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -0,0 +1,580 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9325/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_HY_STM32_100P)
+ #include "gdisp_lld_board_hy_stm32_100p.h"
+#else
+ #include "gdisp_lld_board.h"
+#endif
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* This controller is only ever used with a 240 x 320 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_WIDTH
+#endif
+
+#define GDISP_SCREEN_WIDTH 240
+#define GDISP_SCREEN_HEIGHT 320
+
+#define GDISP_INITIAL_CONTRAST 50
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+uint32_t DISPLAY_CODE;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+static __inline void lld_lcdDelay(uint16_t us) {
+ chThdSleepMicroseconds(us);
+}
+
+static __inline void lld_lcdWriteIndex(uint16_t index) {
+ GDISP_LLD(write_index)(index);
+}
+
+static __inline void lld_lcdWriteData(uint16_t data) {
+ GDISP_LLD(write_data)(data);
+}
+
+static __inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
+ GDISP_LLD(write_index)(lcdReg);
+ GDISP_LLD(write_data)(lcdRegValue);
+}
+
+static __inline uint16_t lld_lcdReadData(void) {
+ /* fix this! */
+ //return GDISP_LLD(read_data);
+ return GDISP_RAM;
+}
+
+static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
+ volatile uint16_t dummy;
+
+ GDISP_LLD(write_index)(lcdReg);
+ dummy = lld_lcdReadData();
+ (void)dummy;
+
+ return lld_lcdReadData();
+}
+
+static __inline void lld_lcdWriteStreamStart(void) {
+ lld_lcdWriteIndex(0x0022);
+}
+
+static __inline void lld_lcdWriteStreamStop(void) {
+
+}
+
+static __inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) {
+ uint16_t i;
+
+ for(i = 0; i < size; i++)
+ lld_lcdWriteData(buffer[i]);
+}
+
+static __inline void lld_lcdReadStreamStart(void) {
+ lld_lcdWriteIndex(0x0022);
+}
+
+static __inline void lld_lcdReadStreamStop(void) {
+
+}
+
+static __inline void lld_lcdReadStream(uint16_t *buffer, size_t size) {
+ uint16_t i;
+ volatile uint16_t dummy;
+
+ dummy = lld_lcdReadData();
+ (void)dummy;
+
+ for(i = 0; i < size; i++)
+ buffer[i] = lld_lcdReadData();
+}
+
+bool_t lld_gdisp_init(void) {
+ /* Initialise your display */
+ GDISP_LLD(init_board)();
+
+ /* Hardware reset */
+ GDISP_LLD(setpin_reset)(TRUE);
+ lld_lcdDelay(1000);
+ GDISP_LLD(setpin_reset)(FALSE);
+ lld_lcdDelay(1000);
+
+ // chinese code starts here
+ lld_lcdWriteReg(0x0000,0x0001);
+ lld_lcdDelay(10);
+
+ lld_lcdWriteReg(0x0015,0x0030);
+ lld_lcdWriteReg(0x0011,0x0040);
+ lld_lcdWriteReg(0x0010,0x1628);
+ lld_lcdWriteReg(0x0012,0x0000);
+ lld_lcdWriteReg(0x0013,0x104d);
+ lld_lcdDelay(10);
+ lld_lcdWriteReg(0x0012,0x0010);
+ lld_lcdDelay(10);
+ lld_lcdWriteReg(0x0010,0x2620);
+ lld_lcdWriteReg(0x0013,0x344d); //304d
+ lld_lcdDelay(10);
+
+ lld_lcdWriteReg(0x0001,0x0100);
+ lld_lcdWriteReg(0x0002,0x0300);
+ lld_lcdWriteReg(0x0003,0x1038);//0x1030
+ lld_lcdWriteReg(0x0008,0x0604);
+ lld_lcdWriteReg(0x0009,0x0000);
+ lld_lcdWriteReg(0x000A,0x0008);
+
+ lld_lcdWriteReg(0x0041,0x0002);
+ lld_lcdWriteReg(0x0060,0x2700);
+ lld_lcdWriteReg(0x0061,0x0001);
+ lld_lcdWriteReg(0x0090,0x0182);
+ lld_lcdWriteReg(0x0093,0x0001);
+ lld_lcdWriteReg(0x00a3,0x0010);
+ lld_lcdDelay(10);
+
+ //################# void Gamma_Set(void) ####################//
+ lld_lcdWriteReg(0x30,0x0000);
+ lld_lcdWriteReg(0x31,0x0502);
+ lld_lcdWriteReg(0x32,0x0307);
+ lld_lcdWriteReg(0x33,0x0305);
+ lld_lcdWriteReg(0x34,0x0004);
+ lld_lcdWriteReg(0x35,0x0402);
+ lld_lcdWriteReg(0x36,0x0707);
+ lld_lcdWriteReg(0x37,0x0503);
+ lld_lcdWriteReg(0x38,0x1505);
+ lld_lcdWriteReg(0x39,0x1505);
+ lld_lcdDelay(10);
+
+ //################## void Display_ON(void) ####################//
+ lld_lcdWriteReg(0x0007,0x0001);
+ lld_lcdDelay(10);
+ lld_lcdWriteReg(0x0007,0x0021);
+ lld_lcdWriteReg(0x0007,0x0023);
+ lld_lcdDelay(10);
+ lld_lcdWriteReg(0x0007,0x0033);
+ lld_lcdDelay(10);
+ lld_lcdWriteReg(0x0007,0x0133);
+
+ // chinese code ends here
+
+ // Turn on the backlight
+ GDISP_LLD(set_backlight)(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+
+ return TRUE;
+}
+
+static void lld_lcdSetCursor(uint16_t x, uint16_t y) {
+
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0020, x);
+ lld_lcdWriteReg(0x0021, y);
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0020, y);
+ lld_lcdWriteReg(0x0021, x);
+ break;
+
+ case GDISP_ROTATE_180:
+ lld_lcdWriteReg(0x0020, x);
+ lld_lcdWriteReg(0x0021, y);
+ break;
+
+ case GDISP_ROTATE_270:
+ lld_lcdWriteReg(0x0020, y);
+ lld_lcdWriteReg(0x0021, x);
+ break;
+ }
+}
+
+static void lld_lcdSetViewPort(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0050, x);
+ lld_lcdWriteReg(0x0051, x + cx - 1);
+ lld_lcdWriteReg(0x0052, y);
+ lld_lcdWriteReg(0x0053, y + cy - 1);
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0050, y);
+ lld_lcdWriteReg(0x0051, y + cy - 1);
+ lld_lcdWriteReg(0x0052, x);
+ lld_lcdWriteReg(0x0053, x + cx - 1);
+ break;
+
+ case GDISP_ROTATE_180:
+ lld_lcdWriteReg(0x0050, x);
+ lld_lcdWriteReg(0x0051, x + cx - 1);
+ lld_lcdWriteReg(0x0052, y);
+ lld_lcdWriteReg(0x0053, y + cy - 1);
+ break;
+
+ case GDISP_ROTATE_270:
+ lld_lcdWriteReg(0x0050, y);
+ lld_lcdWriteReg(0x0051, y + cy - 1);
+ lld_lcdWriteReg(0x0052, x);
+ lld_lcdWriteReg(0x0053, x + cx - 1);
+ break;
+
+ }
+
+ lld_lcdSetCursor(x, y);
+}
+
+static __inline void lld_lcdResetViewPort(void) {
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ lld_lcdSetViewPort(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
+ break;
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ lld_lcdSetViewPort(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
+ break;
+ }
+}
+
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+ lld_lcdSetCursor(x, y);
+ lld_lcdWriteReg(0x0022, color);
+}
+
+#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
+ void lld_gdisp_clear(color_t color) {
+ unsigned i;
+
+ lld_lcdSetCursor(0, 0);
+ lld_lcdWriteStreamStart();
+
+ for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
+ lld_lcdWriteData(color);
+
+ lld_lcdWriteStreamStop();
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ unsigned i, area;
+
+ area = cx*cy;
+ lld_lcdSetViewPort(x, y, cx, cy);
+ lld_lcdWriteStreamStart();
+ for(i = 0; i < area; i++)
+ lld_lcdWriteData(color);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy;
+ unsigned lg;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ lld_lcdSetViewPort(x, y, cx, cy);
+ lld_lcdWriteStreamStart();
+
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ buffer += srcx + srcy * srccx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ lld_lcdWriteData(*buffer++);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+
+ lld_lcdSetCursor(x, y);
+ lld_lcdWriteStreamStart();
+
+ color = lld_lcdReadData();
+ color = lld_lcdReadData();
+
+ lld_lcdWriteStreamStop();
+
+ return color;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
+ coord_t row0, row1;
+ unsigned i, gap, abslines;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ abslines = lines < 0 ? -lines : lines;
+
+ if (abslines >= cy) {
+ abslines = cy;
+ gap = 0;
+ } else {
+ gap = cy - abslines;
+ for(i = 0; i < gap; i++) {
+ if(lines > 0) {
+ row0 = y + i + lines;
+ row1 = y + i;
+ } else {
+ row0 = (y - i - 1) + lines;
+ row1 = (y - i - 1);
+ }
+
+ /* read row0 into the buffer and then write at row1*/
+ lld_lcdSetViewPort(x, row0, cx, 1);
+ lld_lcdReadStreamStart();
+ lld_lcdReadStream(buf, cx);
+ lld_lcdReadStreamStop();
+
+ lld_lcdSetViewPort(x, row1, cx, 1);
+ lld_lcdWriteStreamStart();
+ lld_lcdWriteStream(buf, cx);
+ lld_lcdWriteStreamStop();
+ }
+ }
+
+ /* fill the remaining gap */
+ lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines);
+ lld_lcdWriteStreamStart();
+ gap = cx*abslines;
+ for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor);
+ lld_lcdWriteStreamStop();
+ lld_lcdResetViewPort();
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ void lld_gdisp_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_POWER:
+ if(GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ lld_lcdWriteReg(0x0007, 0x0000);
+ lld_lcdWriteReg(0x0010, 0x0000);
+ lld_lcdWriteReg(0x0011, 0x0000);
+ lld_lcdWriteReg(0x0012, 0x0000);
+ lld_lcdWriteReg(0x0013, 0x0000);
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ case powerOn:
+ //*************Power On sequence ******************//
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+ lld_lcdWriteReg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0012, 0x013C); /* VREG1OUT voltage */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdWriteReg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+ lld_lcdDelay(500);
+ lld_lcdWriteReg(0x0007, 0x0173); /* 262K color and display ON */
+ GDISP_LLD(set_backlight)(GDISP.Backlight);
+ if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
+ lld_gdisp_init();
+ break;
+
+ case powerSleep:
+ lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ case powerDeepSleep:
+ lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
+ lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+ lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
+ lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+ lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
+ lld_lcdWriteReg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+ GDISP_LLD(set_backlight)(0);
+ break;
+
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+
+ case GDISP_CONTROL_ORIENTATION:
+ if(GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ lld_lcdWriteReg(0x0001, 0x0100);
+ lld_lcdWriteReg(0x0003, 0x1038);
+ lld_lcdWriteReg(0x0060, 0x2700);
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_90:
+ lld_lcdWriteReg(0x0001, 0x0000);
+ lld_lcdWriteReg(0x0003, 0x1030);
+ lld_lcdWriteReg(0x0060, 0x2700);
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ case GDISP_ROTATE_180:
+ lld_lcdWriteReg(0x0001, 0x0000);
+ lld_lcdWriteReg(0x0003, 0x1038);
+ lld_lcdWriteReg(0x0060, 0xa700);
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_270:
+ lld_lcdWriteReg(0x0001, 0x0100);
+ lld_lcdWriteReg(0x0003, 0x1030);
+ lld_lcdWriteReg(0x0060, 0xA700);
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ default:
+ return;
+ }
+
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+
+ case GDISP_CONTROL_BACKLIGHT:
+ if((unsigned)value > 100) value = (void *)100;
+ GDISP_LLD(set_backlight)((unsigned)value);
+ GDISP.Backlight = (unsigned)value;
+ break;
+
+ default:
+ return;
+ }
+ }
+
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.mk b/drivers/gdisp/ILI9325/gdisp_lld.mk
new file mode 100644
index 00000000..b5061324
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/ILI9325
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_example.h b/drivers/gdisp/ILI9325/gdisp_lld_board_example.h
new file mode 100644
index 00000000..7b537dcd
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_example.h
@@ -0,0 +1,59 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9325/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+static __inline void GDISP_LLD(init_board)(void) {
+ #error "ILI9325: You must implement the init_board routine for your board"
+}
+
+static __inline void GDISP_LLD(setpin_reset)(bool_t state) {
+ #error "ILI9325: You must implement setpin_reset routine for your board"
+}
+
+static __inline void GDISP_LLD(write_index)(uint16_t data) {
+ #error "ILI9325: You must implement write_index routine for your board"
+}
+
+static __inline void GDISP_LLD(write_data)(uint16_t data) {
+ #error "ILI9325: You must implement write_data routine for your board"
+}
+
+static __inline uint16_t GDISP_LLD(read_data)(void) {
+ #error "ILI9325: You must implement read_data routine for your board"
+}
+
+/* if not available, just ignore the argument and return */
+static __inline uint16_t GDISP_LLD(set_backlight)(uint8_t percentage) {
+ #error "ILI9325: You must implement set_backlight routine for your board"
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
new file mode 100644
index 00000000..e785ad10
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
@@ -0,0 +1,96 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/*
+ driver quickly hacked together from a chinese sourcecode that came
+ with the board and existing ili9320 code by Chris van Dongen (sjaak)
+ (sjaak2002 at msn.com)
+
+ Also added rotation for 180 and 270 degrees and minor tweaks to
+ setcursor
+
+ Added code comes without warranty and free bugs. Feel free to use
+ or misuse the added code :D
+*/
+
+
+/**
+ * @file drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+ * @brief GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+
+static __inline void GDISP_LLD(init_board)(void) {
+ /* FSMC setup for F1 */
+ rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+ /* set pin modes */
+/* IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
+ IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
+ palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL); */
+
+ const unsigned char FSMC_Bank = 0;
+
+ /* FSMC timing */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
+
+ /* Bank1 NOR/SRAM control register configuration
+ * This is actually not needed as already set by default after reset */
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+
+}
+
+static __inline void GDISP_LLD(setpin_reset)(bool_t state) {
+ if(state)
+ palClearPad(GPIOE, GPIOE_TFT_RST);
+ else
+ palSetPad(GPIOE, GPIOE_TFT_RST);
+}
+
+static __inline void GDISP_LLD(write_index)(uint16_t reg) {
+ GDISP_REG = reg;
+}
+
+static __inline void GDISP_LLD(write_data)(uint16_t data) {
+ GDISP_RAM = data;
+}
+
+static __inline uint16_t GDISP_LLD(read_data)(void) {
+ return GDISP_RAM;
+}
+
+static __inline void GDISP_LLD(set_backlight)(uint8_t percent) {
+ percent=percent; // avoid a warning
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_config.h b/drivers/gdisp/ILI9325/gdisp_lld_config.h
new file mode 100644
index 00000000..44f8323f
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld_config.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/ILI9325/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_CONFIG_H
+#define GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "ILI9325"
+#define GDISP_LLD(x) gdisp_lld_##x##_ILI9325
+
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS FALSE
+#define GDISP_HARDWARE_SCROLL FALSE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/readme.txt b/drivers/gdisp/ILI9325/readme.txt
new file mode 100644
index 00000000..9150610e
--- /dev/null
+++ b/drivers/gdisp/ILI9325/readme.txt
@@ -0,0 +1,15 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+
+ d) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_example.h file as a basis.
+ Currently known boards are:
+ HY_STM32_100p
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld.mk
diff --git a/drivers/gdisp/Nokia6610GE12/GE12.h b/drivers/gdisp/Nokia6610GE12/GE12.h
new file mode 100644
index 00000000..6c980e2e
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/GE12.h
@@ -0,0 +1,81 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#ifndef GE12_H
+#define GE12_H
+
+// *************************************************************************************
+// LCD Include File for Philips PCF8833 STN RGB- 132x132x3 Driver (GE12)
+//
+// Taken from Philips data sheet Feb 14, 2003
+// *************************************************************************************
+
+// Philips PCF8833 LCD controller command codes
+#define NOP 0x00 // nop
+#define SWRESET 0x01 // software reset
+#define BSTROFF 0x02 // booster voltage OFF
+#define BSTRON 0x03 // booster voltage ON
+#define RDDIDIF 0x04 // read display identification
+#define RDDST 0x09 // read display status
+#define SLEEPIN 0x10 // sleep in
+#define SLEEPOUT 0x11 // sleep out
+#define PTLON 0x12 // partial display mode
+#define NORON 0x13 // display normal mode
+#define INVOFF 0x20 // inversion OFF
+#define INVON 0x21 // inversion ON
+#define DALO 0x22 // all pixel OFF
+#define DAL 0x23 // all pixel ON
+#define SETCON 0x25 // write contrast
+#define DISPOFF 0x28 // display OFF
+#define DISPON 0x29 // display ON
+#define CASET 0x2A // column address set
+#define PASET 0x2B // page address set
+#define RAMWR 0x2C // memory write
+#define RGBSET 0x2D // colour set
+#define PTLAR 0x30 // partial area
+#define VSCRDEF 0x33 // vertical scrolling definition
+#define TEOFF 0x34 // test mode
+#define TEON 0x35 // test mode
+#define MADCTL 0x36 // memory access control
+#define SEP 0x37 // vertical scrolling start address
+#define IDMOFF 0x38 // idle mode OFF
+#define IDMON 0x39 // idle mode ON
+#define COLMOD 0x3A // interface pixel format
+#define SETVOP 0xB0 // set Vop
+#define BRS 0xB4 // bottom row swap
+#define TRS 0xB6 // top row swap
+#define DISCTR 0xB9 // display control
+#define DOR 0xBA // data order
+#define TCDFE 0xBD // enable/disable DF temperature compensation
+#define TCVOPE 0xBF // enable/disable Vop temp comp
+#define EC 0xC0 // internal or external oscillator
+#define SETMUL 0xC2 // set multiplication factor
+#define TCVOPAB 0xC3 // set TCVOP slopes A and B
+#define TCVOPCD 0xC4 // set TCVOP slopes c and d
+#define TCDF 0xC5 // set divider frequency
+#define DF8COLOR 0xC6 // set divider frequency 8-color mode
+#define SETBS 0xC7 // set bias system
+#define RDTEMP 0xC8 // temperature read back
+#define NLI 0xC9 // n-line inversion
+#define RDID1 0xDA // read ID1
+#define RDID2 0xDB // read ID2
+#define RDID3 0xDC // read ID3
+
+#endif /* GE12_H */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
new file mode 100644
index 00000000..6ce7b581
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -0,0 +1,528 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* Controller definitions */
+#include "GE12.h"
+
+/* This controller is only ever used with a 132 x 132 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_WIDTH
+#endif
+#define GDISP_SCREEN_HEIGHT 132
+#define GDISP_SCREEN_WIDTH 132
+
+#define GDISP_INITIAL_CONTRAST 38
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+ #include "gdisp_lld_board_olimexsam7ex256.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#endif
+
+// Some macros just to make reading the code easier
+#define delayms(ms) chThdSleepMilliseconds(ms)
+#define write_data2(d1, d2) { write_data(d1); write_data(d2); }
+#define write_data3(d1, d2, d3) { write_data(d1); write_data(d2); write_data(d3); }
+#define write_cmd1(cmd, d1) { write_cmd(cmd); write_data(d1); }
+#define write_cmd2(cmd, d1, d2) { write_cmd(cmd); write_data2(d1, d2); }
+#define write_cmd3(cmd, d1, d2, d3) { write_cmd(cmd); write_data3(d1, d2, d3); }
+
+// A very common thing to do.
+// An inline function has been used here incase the parameters have side effects with the internal calculations.
+static __inline void setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ write_cmd2(CASET, x, x+cx-1); // Column address set
+ write_cmd2(PASET, y, y+cy-1); // Page address set
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialization.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ /* Initialise your display */
+ init_board();
+
+ // Hardware reset
+ setpin_reset(TRUE);
+ delayms(20);
+ setpin_reset(FALSE);
+ delayms(20);
+
+ // Get the bus for the following initialisation commands
+ acquire_bus();
+
+ // UNTESTED
+ #if 1
+ write_cmd(SLEEPOUT); // Sleep out
+ write_cmd(INVON); // Inversion on: seems to be required for this controller
+ write_cmd1(COLMOD, 0x03); // Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
+ write_cmd1(MADCTL, 0xC8); // Memory access controler - 0xC0 = mirror x and y, reverse rgb
+ write_cmd1(SETCON, GDISP_INITIAL_CONTRAST); // Write contrast
+ delayms(20);
+ write_cmd(DISPON); // Display On
+ #else
+ // Alternative
+ write_cmd(SOFTRST); // Software Reset
+ delayms(20);
+ write_cmd(INITESC); // Initial escape
+ delayms(20);
+ write_cmd1(REFSET, 0x00); // Refresh set
+ write_cmd(DISPCTRL); // Set Display control - really 7 bytes of data
+ write_data(128); // Set the lenght of one selection term
+ write_data(128); // Set N inversion -> no N inversion
+ write_data(134); // Set frame frequence and bias rate -> 2 devision of frequency and 1/8 bias, 1/67 duty, 96x67 size
+ write_data(84); // Set duty parameter
+ write_data(69); // Set duty parameter
+ write_data(82); // Set duty parameter
+ write_data(67); // Set duty parameter
+ write_cmd(GRAYSCALE0); // Grey scale 0 position set - really 15 bytes of data
+ write_data(1); // GCP1 - gray lavel to be output when the RAM data is "0001"
+ write_data(2); // GCP2 - gray lavel to be output when the RAM data is "0010"
+ write_data(4); // GCP3 - gray lavel to be output when the RAM data is "0011"
+ write_data(8); // GCP4 - gray lavel to be output when the RAM data is "0100"
+ write_data(16); // GCP5 - gray lavel to be output when the RAM data is "0101"
+ write_data(30); // GCP6 - gray lavel to be output when the RAM data is "0110"
+ write_data(40); // GCP7 - gray lavel to be output when the RAM data is "0111"
+ write_data(50); // GCP8 - gray lavel to be output when the RAM data is "1000"
+ write_data(60); // GCP9 - gray lavel to be output when the RAM data is "1001"
+ write_data(70); // GCP10 - gray lavel to be output when the RAM data is "1010"
+ write_data(80); // GCP11 - gray lavel to be output when the RAM data is "1011"
+ write_data(90); // GCP12 - gray lavel to be output when the RAM data is "1100"
+ write_data(100); // GCP13 - gray lavel to be output when the RAM data is "1101"
+ write_data(110); // GCP14 - gray lavel to be output when the RAM data is "1110"
+ write_data(127); // GCP15 - gray lavel to be output when the RAM data is "1111"
+ write_cmd1(GAMMA, 0x01); // Gamma curve set - select gray scale - GRAYSCALE 0 or GREYSCALE 1 - Select grey scale 0
+ write_cmd1(COMMONDRV, 0x00); // Command driver output - Set COM1-COM41 side come first, normal mod
+ write_cmd(NORMALMODE); // Set Normal mode (my)
+ // write_cmd(INVERSIONOFF); // Inversion off
+ write_cmd2(COLADDRSET, 0, 131); // Column address set
+ write_cmd2(PAGEADDRSET, 0, 131); // Page address set
+ write_cmd1(ACCESSCTRL, 0x40); // Memory access controler - 0x40 horizontal
+ // write_data(0x20); // vertical
+ write_cmd1(PWRCTRL, 0x04); // Power control - Internal resistance, V1OUT -> high power mode, oscilator devision rate
+ write_cmd(SLEEPOUT); // Sleep out
+ write_cmd(VOLTCTRL); // Voltage control - voltage control and write contrast define LCD electronic volume
+ // write_data(0x7f); // full voltage control
+ // write_data(0x03); // must be "1"
+ write_cmd1(CONTRAST, GDISP_INITIAL_CONTRAST); // Write contrast
+ delayms(20);
+ write_cmd(TEMPGRADIENT); // Temperature gradient - really 14 bytes of data
+ for(i=0; i<14; i++)
+ write_data(0);
+ write_cmd(BOOSTVON); // Booster voltage ON
+ write_cmd(DISPLAYON); // Finally - Display On
+ #endif
+
+ // Release the bus
+ release_bus();
+
+ /* Turn on the back-light */
+ set_backlight(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure to match */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+ acquire_bus();
+ setviewport(x, y, 1, 1);
+ write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
+ release_bus();
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ unsigned i, tuples;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ tuples = (cx*cy+1)/2; // With an odd sized area we over-print by one pixel.
+ // This extra pixel is ignored by the controller.
+
+ acquire_bus();
+ setviewport(x, y, cx, cy);
+ write_cmd(RAMWR);
+ for(i=0; i < tuples; i++)
+ write_data3(((color >> 4) & 0xFF), (((color << 4) & 0xF0)|((color >> 8) & 0x0F)), (color & 0xFF));
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy, lg;
+ color_t c1, c2;
+ #if GDISP_PACKED_PIXELS
+ coord_t pos;
+ const uint8_t *p;
+ #endif
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ /* What are our end points */
+ endx = srcx + cx;
+ endy = y + cy;
+
+ acquire_bus();
+ setviewport(x, y, cx, cy);
+ write_cmd(RAMWR);
+
+ #if !GDISP_PACKED_PIXELS
+ // Although this controller uses packed pixels we support unpacked pixel
+ // formats in this blit by packing the data as we feed it to the controller.
+ lg = srccx - cx;
+ buffer += srcy * srccx + srcx;
+ x = srcx;
+ while (1) {
+ /* Get a pixel */
+ c1 = *buffer++;
+ if (++x >= endx) {
+ if (++y >= endy) {
+ /* Odd pixel at end */
+ write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
+ break;
+ }
+ x = srcx;
+ buffer += lg;
+ }
+ /* Get the next pixel */
+ c2 = *buffer++;
+ write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+ if (++x >= endx) {
+ if (++y >= endy)
+ break;
+ x = srcx;
+ buffer += lg;
+ }
+ }
+
+ #else
+
+ // Although this controller uses packed pixels, we may have to feed it into
+ // the controller with different packing to the source bitmap
+ #if !GDISP_PACKED_LINES
+ srccx = (srccx + 1) & ~1;
+ #endif
+ pos = srcy*srccx;
+ lg = (srccx - cx)/2*3;
+ p = ((const uint8_t *)buffer) + ((pos+srcx)/2 * 3);
+
+ x = srcx;
+ while (1) {
+ /* Get a pixel */
+ switch((pos+x)&1) {
+ case 0: c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break;
+ case 1: c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break;
+ }
+ if (++x >= endx) {
+ if (++y >= endy) {
+ /* Odd pixel at end */
+ write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
+ break;
+ }
+ x = srcx;
+ p += lg;
+ pos += srccx;
+ }
+ /* Get the next pixel */
+ switch((pos+x)&1) {
+ case 0: c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break;
+ case 1: c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break;
+ }
+ write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+ if (++x >= endx) {
+ if (++y >= endy)
+ break;
+ x = srcx;
+ p += lg;
+ pos += srccx;
+ }
+ }
+ #endif
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The start of the text
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ /* NOT IMPLEMENTED */
+ /* Some board hardware might support this in the future.
+ * The Olimex board doesn't.
+ */
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ /* NOT IMPLEMENTED */
+ /* The hardware seems capable of doing this.
+ * It is just really complex so we leave it out for now.
+ */
+ }
+#endif
+
+#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ /* The hardware is capable of supporting...
+ * GDISP_CONTROL_POWER - not implemented yet
+ * GDISP_CONTROL_ORIENTATION - not implemented yet
+ * GDISP_CONTROL_BACKLIGHT - supported (the OlimexSAM7EX256 board.h currently only implements off/on although PWM is supported by the hardware)
+ * GDISP_CONTROL_CONTRAST - supported
+ */
+ switch(what) {
+#if 0
+ // NOT IMPLEMENTED YET
+ case GDISP_CONTROL_POWER:
+ if (GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ // Code here
+ break;
+ case powerOn:
+ // Code here
+ /* You may need this ---
+ * if (GDISP.Powermode != powerSleep)
+ * lld_gdisp_init();
+ */
+ break;
+ case powerSleep:
+ /* Code here */
+ break;
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+#endif
+#if 0
+ // NOT IMPLEMENTED YET
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ // WriteSpiData(0x48); // no mirror Y (temporary to satisfy Olimex bmptoarray utility)
+ // WriteSpiData(0xC8); // restore to (mirror x and y, reverse rgb)
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_90:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_180:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_270:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+#endif
+ case GDISP_CONTROL_BACKLIGHT:
+ if ((unsigned)value > 100) value = (void *)100;
+ set_backlight((unsigned)value);
+ GDISP.Backlight = (unsigned)value;
+ return;
+ case GDISP_CONTROL_CONTRAST:
+ if ((unsigned)value > 100) value = (void *)100;
+ acquire_bus();
+ write_cmd1(CONTRAST,(unsigned)value);
+ release_bus();
+ GDISP.Contrast = (unsigned)value;
+ return;
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
new file mode 100644
index 00000000..575d52a3
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_example.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_example.h
new file mode 100644
index 00000000..1885f07c
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_example.h
@@ -0,0 +1,135 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE12/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes Performs the following functions:
+ * 1. initialise the spi port used by your display
+ * 2. initialise the reset pin (initial state not-in-reset)
+ * 3. initialise the chip select pin (initial state not-active)
+ * 4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for setpin_reset for your board"
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ * @note For now 0% turns the backlight off, anything else the backlight is on.
+ * While the hardware supports PWM backlight control, we are not using it
+ * yet.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for set_backlight for your board"
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for acquire_bus for your board"
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Send an 8 bit command to the lcd.
+ *
+ * @param[in] cmd The command to send
+ *
+ * @notapi
+ */
+static __inline void write_cmd(uint16_t cmd) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for write_cmd for your board"
+}
+
+/**
+ * @brief Send an 8 bit data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for write_data for your board"
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ /* Code here */
+ #error "gdispNokia6610GE12: You must supply a definition for read_data for your board"
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
new file mode 100644
index 00000000..c161a9a3
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
@@ -0,0 +1,196 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
+ * @brief GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// ******************************************************
+// Pointers to AT91SAM7X256 peripheral data structures
+// ******************************************************
+volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
+volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
+volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
+volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
+volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes Performs the following functions:
+ * 1. initialise the spi port used by your display
+ * 2. initialise the reset pin (initial state not-in-reset)
+ * 3. initialise the chip select pin (initial state not-active)
+ * 4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ // *********************************************************************************************
+ // InitSpi( )
+ //
+ // Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
+ //
+ // I/O ports used: PA2 = LCD Reset (set to low to reset)
+ // PA12 = LCD chip select (set to low to select the LCD chip)
+ // PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
+ // PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+ // PA18 = SPI0_SPCK Serial Clock (to LCD slave)
+ // PB20 = backlight control (normally PWM control, 1 = full on)
+ //
+ // *********************************************************************************************}
+
+ /* This code should really use the ChibiOS driver for these functions */
+
+ // Pin for backlight
+ pPIOB->PIO_CODR = PIOB_LCD_BL_MASK; // Set PB20 to LOW
+ pPIOB->PIO_OER = PIOB_LCD_BL_MASK; // Configure PB20 as output
+
+ // Reset pin
+ pPIOA->PIO_SODR = PIOA_LCD_RESET_MASK; // Set PA2 to HIGH
+ pPIOA->PIO_OER = PIOA_LCD_RESET_MASK; // Configure PA2 as output
+
+ // CS pin - this seems to be ignored
+ // pPIOA->PIO_SODR = 1<<12; // Set PA2 to HIGH
+ // pPIOA->PIO_OER = 1<<12; // Configure PA2 as output
+
+ // Init SPI0
+ // Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
+ // BIT12 = PA12 -> SPI0_NPCS0 chip select
+ // BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
+ // BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+ // BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
+ pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+ pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+ pPIOA->PIO_BSR = 0;
+
+ //enable the clock of SPI
+ pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
+
+ // Fixed mode
+ pSPI->SPI_CR = 0x81; //SPI Enable, Sowtware reset
+ pSPI->SPI_CR = 0x01; //SPI Enable
+
+ //pSPI->SPI_MR = 0xE0019; //Master mode, fixed select, disable decoder, FDIV=1 (MCK), PCS=1110
+ pSPI->SPI_MR = 0xE0011; //Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110
+
+ //pSPI->SPI_CSR[0] = 0x01010C11; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/32*12 = 125kHz
+ pSPI->SPI_CSR[0] = 0x01010311; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz if using commented MR line above
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ if (state)
+ palClearPad(IOPORT1, PIOA_LCD_RESET);
+ else
+ palSetPad(IOPORT1, PIOA_LCD_RESET);
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ * @note For now 0% turns the backlight off, anything else the backlight is on.
+ * While the hardware supports PWM backlight control, we are not using it
+ * yet.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ if (percent)
+ palSetPad(IOPORT2, PIOB_LCD_BL);
+ else
+ palClearPad(IOPORT2, PIOB_LCD_BL);
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Nothing to do for this board as the LCD is the only device on the SPI port */
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ // Nothing to do for this board as the LCD is the only device on the SPI port
+}
+
+/**
+ * @brief Send an 8 bit command to the lcd.
+ *
+ * @param[in] cmd The command to send
+ *
+ * @notapi
+ */
+static __inline void write_cmd(uint16_t cmd) {
+ // wait for the previous transfer to complete
+ while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+ // send the command
+ pSPI->SPI_TDR = cmd & 0xFF;
+}
+
+/**
+ * @brief Send an 8 bit data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ // wait for the previous transfer to complete
+ while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+ // send the data
+ pSPI->SPI_TDR = data | 0x0100;
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ #error "gdispNokia6610GE12: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
+ return 0;
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
new file mode 100644
index 00000000..ab9d35e7
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
@@ -0,0 +1,58 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "Nokia6610GE12"
+#define GDISP_LLD(x) gdisp_lld_##x##_Nokia6610GE12
+
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE
+#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB444
+/* This driver supports both packed and unpacked pixel formats and line formats.
+ * By default we leave these as FALSE.
+ */
+#define GDISP_PACKED_PIXELS FALSE
+#define GDISP_PACKED_LINES FALSE
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/readme.txt b/drivers/gdisp/Nokia6610GE12/readme.txt
new file mode 100644
index 00000000..54c4570f
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/readme.txt
@@ -0,0 +1,15 @@
+This driver is for the Nokia6610 Philips (GE12) controller
+
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+ c) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_example.h file as a basis.
+ Currently known boards are:
+ Olimex SAM7-EX256
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
diff --git a/drivers/gdisp/Nokia6610GE8/GE8.h b/drivers/gdisp/Nokia6610GE8/GE8.h
new file mode 100644
index 00000000..789308a9
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/GE8.h
@@ -0,0 +1,67 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#ifndef GE8_H
+#define GE8_H
+
+// *****************************************************************************
+// Include file for Epson S1D15G00 LCD Controller (GE8)
+//
+// Author: James P Lynch August 30, 2007
+// Modified for GDISP: Andrew Hannam August 2, 2012
+//
+// *****************************************************************************
+
+#define DISON 0xAF // Display on
+#define DISOFF 0xAE // Display off
+#define DISNOR 0xA6 // Normal display
+#define DISINV 0xA7 // Inverse display
+#define COMSCN 0xBB // Common scan direction
+#define DISCTL 0xCA // Display control
+#define SLPIN 0x95 // Sleep in
+#define SLPOUT 0x94 // Sleep out
+#define PASET 0x75 // Page address set
+#define CASET 0x15 // Column address set
+#define DATCTL 0xBC // Data scan direction, etc.
+#define RGBSET8 0xCE // 256-color position set
+#define RAMWR 0x5C // Writing to memory
+#define RAMRD 0x5D // Reading from memory
+#define PTLIN 0xA8 // Partial display in
+#define PTLOUT 0xA9 // Partial display out
+#define RMWIN 0xE0 // Read and modify write
+#define RMWOUT 0xEE // End
+#define ASCSET 0xAA // Area scroll set
+#define SCSTART 0xAB // Scroll start set
+#define OSCON 0xD1 // Internal oscillation on
+#define OSCOFF 0xD2 // Internal oscillation off
+#define PWRCTR 0x20 // Power control
+#define VOLCTR 0x81 // Electronic volume control
+#define VOLUP 0xD6 // Increment electronic control by 1
+#define VOLDOWN 0xD7 // Decrement electronic control by 1
+#define TMPGRD 0x82 // Temperature gradient set
+#define EPCTIN 0xCD // Control EEPROM
+#define EPCOUT 0xCC // Cancel EEPROM control
+#define EPMWR 0xFC // Write into EEPROM
+#define EPMRD 0xFD // Read from EEPROM
+#define EPSRRD1 0x7C // Read register 1
+#define EPSRRD2 0x7D // Read register 2
+#define NOP 0x25 // NOP instruction
+
+#endif /* GE8_H */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
new file mode 100644
index 00000000..006c964b
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -0,0 +1,483 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE8 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#include "GE8.h"
+
+/* This controller is only ever used with a 132 x 132 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_WIDTH
+#endif
+#define GDISP_SCREEN_HEIGHT 132
+#define GDISP_SCREEN_WIDTH 132
+
+#define GDISP_INITIAL_CONTRAST 38
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+ #include "gdisp_lld_board_olimexsam7ex256.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#endif
+
+// Some macros just to make reading the code easier
+#define delayms(ms) chThdSleepMilliseconds(ms)
+#define write_data2(d1, d2) { write_data(d1); write_data(d2); }
+#define write_data3(d1, d2, d3) { write_data(d1); write_data(d2); write_data(d3); }
+#define write_cmd1(cmd, d1) { write_cmd(cmd); write_data(d1); }
+#define write_cmd2(cmd, d1, d2) { write_cmd(cmd); write_data2(d1, d2); }
+#define write_cmd3(cmd, d1, d2, d3) { write_cmd(cmd); write_data3(d1, d2, d3); }
+
+// A very common thing to do.
+// An inline function has been used here incase the parameters have side effects with the internal calculations.
+static __inline void setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ write_cmd2(CASET, x, x+cx-1); // Column address set
+ write_cmd2(PASET, y, y+cy-1); // Page address set
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialization.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ /* Initialise your display */
+ init_board();
+
+ // Hardware reset
+ setpin_reset(TRUE);
+ delayms(20);
+ setpin_reset(FALSE);
+ delayms(20);
+
+ // Get the bus for the following initialisation commands
+ acquire_bus();
+
+ write_cmd3(DISCTL, 0x00, 0x20, 0x00); // Display control
+ // P1: 0x00 = 2 divisions, switching period=8 (default)
+ // P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
+ // P3: 0x00 = no inversely highlighted lines
+ write_cmd1(COMSCN, 0x01); // COM scan P1: 0x01 = Scan 1->80, 160<-81
+ write_cmd(OSCON); // Internal oscilator ON
+ write_cmd(SLPOUT); // Sleep out
+ write_cmd1(PWRCTR, 0x0F); // Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+ write_cmd3(DATCTL, 0x48, 0x00, 0x02); // Data control
+ // P1: 0x01 = page address inverted, column address normal, address scan in column direction
+ // P2: 0x00 = RGB sequence (default value)
+ // P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A)
+ write_cmd2(VOLCTR, GDISP_INITIAL_CONTRAST, 0x03); // Voltage control (contrast setting)
+ // P1 = Contrast
+ // P2 = 3 resistance ratio (only value that works)
+ delayms(100); // allow power supply to stabilize
+ write_cmd(DISON); // Turn on the display
+
+ // Release the bus
+ release_bus();
+
+ /* Turn on the back-light */
+ set_backlight(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure to match */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+ acquire_bus();
+ setviewport(x, y, 1, 1);
+ write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
+ release_bus();
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ unsigned i, tuples;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ tuples = (cx*cy+1)/2; // With an odd sized area we over-print by one pixel.
+ // This extra pixel is ignored by the controller.
+
+ acquire_bus();
+ setviewport(x, y, cx, cy);
+ write_cmd(RAMWR);
+ for(i=0; i < tuples; i++)
+ write_data3(((color >> 4) & 0xFF), (((color << 4) & 0xF0)|((color >> 8) & 0x0F)), (color & 0xFF));
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy, lg;
+ color_t c1, c2;
+ #if GDISP_PACKED_PIXELS
+ coord_t pos;
+ const uint8_t *p;
+ #endif
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ /* What are our end points */
+ endx = srcx + cx;
+ endy = y + cy;
+
+ acquire_bus();
+ setviewport(x, y, cx, cy);
+ write_cmd(RAMWR);
+
+ #if !GDISP_PACKED_PIXELS
+ // Although this controller uses packed pixels we support unpacked pixel
+ // formats in this blit by packing the data as we feed it to the controller.
+ lg = srccx - cx;
+ buffer += srcy * srccx + srcx;
+ x = srcx;
+ while (1) {
+ /* Get a pixel */
+ c1 = *buffer++;
+ if (++x >= endx) {
+ if (++y >= endy) {
+ /* Odd pixel at end */
+ write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
+ break;
+ }
+ x = srcx;
+ buffer += lg;
+ }
+ /* Get the next pixel */
+ c2 = *buffer++;
+ write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+ if (++x >= endx) {
+ if (++y >= endy)
+ break;
+ x = srcx;
+ buffer += lg;
+ }
+ }
+
+ #else
+
+ // Although this controller uses packed pixels, we may have to feed it into
+ // the controller with different packing to the source bitmap
+ #if !GDISP_PACKED_LINES
+ srccx = (srccx + 1) & ~1;
+ #endif
+ pos = srcy*srccx;
+ lg = (srccx - cx)/2*3;
+ p = ((const uint8_t *)buffer) + ((pos+srcx)/2 * 3);
+
+ x = srcx;
+ while (1) {
+ /* Get a pixel */
+ switch((pos+x)&1) {
+ case 0: c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break;
+ case 1: c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break;
+ }
+ if (++x >= endx) {
+ if (++y >= endy) {
+ /* Odd pixel at end */
+ write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
+ break;
+ }
+ x = srcx;
+ p += lg;
+ pos += srccx;
+ }
+ /* Get the next pixel */
+ switch((pos+x)&1) {
+ case 0: c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break;
+ case 1: c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break;
+ }
+ write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+ if (++x >= endx) {
+ if (++y >= endy)
+ break;
+ x = srcx;
+ p += lg;
+ pos += srccx;
+ }
+ }
+ #endif
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The start of the text
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ /* NOT IMPLEMENTED */
+ /* Some board hardware might support this in the future.
+ * The Olimex board doesn't.
+ */
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ /* NOT IMPLEMENTED */
+ /* The hardware seems capable of doing this.
+ * It is just really complex so we leave it out for now.
+ */
+ }
+#endif
+
+#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ /* The hardware is capable of supporting...
+ * GDISP_CONTROL_POWER - not implemented yet
+ * GDISP_CONTROL_ORIENTATION - not implemented yet
+ * GDISP_CONTROL_BACKLIGHT - supported (the OlimexSAM7EX256 board.h currently only implements off/on although PWM is supported by the hardware)
+ * GDISP_CONTROL_CONTRAST - supported
+ */
+ switch(what) {
+#if 0
+ // NOT IMPLEMENTED YET
+ case GDISP_CONTROL_POWER:
+ if (GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ // Code here
+ break;
+ case powerOn:
+ // Code here
+ /* You may need this ---
+ * if (GDISP.Powermode != powerSleep)
+ * lld_gdisp_init();
+ */
+ break;
+ case powerSleep:
+ /* Code here */
+ break;
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+#endif
+#if 0
+ // NOT IMPLEMENTED YET
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ // WriteSpiData(0x48); // no mirror Y (temporary to satisfy Olimex bmptoarray utility)
+ // WriteSpiData(0xC8); // restore to (mirror x and y, reverse rgb)
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_90:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_180:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_270:
+ // Code here
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+#endif
+ case GDISP_CONTROL_BACKLIGHT:
+ if ((unsigned)value > 100) value = (void *)100;
+ set_backlight((unsigned)value);
+ GDISP.Backlight = (unsigned)value;
+ return;
+ case GDISP_CONTROL_CONTRAST:
+ if ((unsigned)value > 100) value = (void *)100;
+ acquire_bus();
+ write_cmd2(VOLCTR, (unsigned)value, 0x03);
+ release_bus();
+ GDISP.Contrast = (unsigned)value;
+ return;
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
new file mode 100644
index 00000000..3a1adec9
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_example.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_example.h
new file mode 100644
index 00000000..fd330590
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_example.h
@@ -0,0 +1,135 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE8/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the Nokia6610 GE8 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes Performs the following functions:
+ * 1. initialise the spi port used by your display
+ * 2. initialise the reset pin (initial state not-in-reset)
+ * 3. initialise the chip select pin (initial state not-active)
+ * 4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for setpin_reset for your board"
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ * @note For now 0% turns the backlight off, anything else the backlight is on.
+ * While the hardware supports PWM backlight control, we are not using it
+ * yet.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for set_backlight for your board"
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for acquire_bus for your board"
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Send an 8 bit command to the lcd.
+ *
+ * @param[in] cmd The command to send
+ *
+ * @notapi
+ */
+static __inline void write_cmd(uint16_t cmd) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for write_cmd for your board"
+}
+
+/**
+ * @brief Send an 8 bit data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for write_data for your board"
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ /* Code here */
+ #error "gdispNokia6610GE8: You must supply a definition for read_data for your board"
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
new file mode 100644
index 00000000..f3b32b3a
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
@@ -0,0 +1,196 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
+ * @brief GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// ******************************************************
+// Pointers to AT91SAM7X256 peripheral data structures
+// ******************************************************
+volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
+volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
+volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
+volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
+volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes Performs the following functions:
+ * 1. initialise the spi port used by your display
+ * 2. initialise the reset pin (initial state not-in-reset)
+ * 3. initialise the chip select pin (initial state not-active)
+ * 4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ // *********************************************************************************************
+ // InitSpi( )
+ //
+ // Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
+ //
+ // I/O ports used: PA2 = LCD Reset (set to low to reset)
+ // PA12 = LCD chip select (set to low to select the LCD chip)
+ // PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
+ // PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+ // PA18 = SPI0_SPCK Serial Clock (to LCD slave)
+ // PB20 = backlight control (normally PWM control, 1 = full on)
+ //
+ // *********************************************************************************************}
+
+ /* This code should really use the ChibiOS driver for these functions */
+
+ // Pin for backlight
+ pPIOB->PIO_CODR = PIOB_LCD_BL_MASK; // Set PB20 to LOW
+ pPIOB->PIO_OER = PIOB_LCD_BL_MASK; // Configure PB20 as output
+
+ // Reset pin
+ pPIOA->PIO_SODR = PIOA_LCD_RESET_MASK; // Set PA2 to HIGH
+ pPIOA->PIO_OER = PIOA_LCD_RESET_MASK; // Configure PA2 as output
+
+ // CS pin - this seems to be ignored
+ // pPIOA->PIO_SODR = 1<<12; // Set PA2 to HIGH
+ // pPIOA->PIO_OER = 1<<12; // Configure PA2 as output
+
+ // Init SPI0
+ // Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
+ // BIT12 = PA12 -> SPI0_NPCS0 chip select
+ // BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
+ // BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+ // BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
+ pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+ pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+ pPIOA->PIO_BSR = 0;
+
+ //enable the clock of SPI
+ pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
+
+ // Fixed mode
+ pSPI->SPI_CR = 0x81; //SPI Enable, Sowtware reset
+ pSPI->SPI_CR = 0x01; //SPI Enable
+
+ //pSPI->SPI_MR = 0xE0019; //Master mode, fixed select, disable decoder, FDIV=1 (MCK), PCS=1110
+ pSPI->SPI_MR = 0xE0011; //Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110
+
+ //pSPI->SPI_CSR[0] = 0x01010C11; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/32*12 = 125kHz
+ pSPI->SPI_CSR[0] = 0x01010311; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz if using commented MR line above
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ if (state)
+ palClearPad(IOPORT1, PIOA_LCD_RESET);
+ else
+ palSetPad(IOPORT1, PIOA_LCD_RESET);
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ * @note For now 0% turns the backlight off, anything else the backlight is on.
+ * While the hardware supports PWM backlight control, we are not using it
+ * yet.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ if (percent)
+ palSetPad(IOPORT2, PIOB_LCD_BL);
+ else
+ palClearPad(IOPORT2, PIOB_LCD_BL);
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Nothing to do for this board as the LCD is the only device on the SPI port */
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ // Nothing to do for this board as the LCD is the only device on the SPI port
+}
+
+/**
+ * @brief Send an 8 bit command to the lcd.
+ *
+ * @param[in] cmd The command to send
+ *
+ * @notapi
+ */
+static __inline void write_cmd(uint16_t cmd) {
+ // wait for the previous transfer to complete
+ while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+ // send the command
+ pSPI->SPI_TDR = cmd & 0xFF;
+}
+
+/**
+ * @brief Send an 8 bit data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ // wait for the previous transfer to complete
+ while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+ // send the data
+ pSPI->SPI_TDR = data | 0x0100;
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ #error "gdispNokia6610GE8: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
+ return 0;
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
new file mode 100644
index 00000000..87bdb824
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -0,0 +1,58 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the Nokia6610 GE8 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "Nokia6610GE8"
+#define GDISP_LLD(x) gdisp_lld_##x##_Nokia6610GE8
+
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE
+#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB444
+/* This driver supports both packed and unpacked pixel formats and line formats.
+ * By default we leave these as FALSE.
+ */
+#define GDISP_PACKED_PIXELS FALSE
+#define GDISP_PACKED_LINES FALSE
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/readme.txt b/drivers/gdisp/Nokia6610GE8/readme.txt
new file mode 100644
index 00000000..c8ad8faa
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/readme.txt
@@ -0,0 +1,15 @@
+This driver is for the Nokia6610 Epson (GE8) controller
+
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+ c) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_example.h file as a basis.
+ Currently known boards are:
+ Olimex SAM7-EX256
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
new file mode 100644
index 00000000..0d856c79
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld.c
@@ -0,0 +1,571 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/S6D1121/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the S6d1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if defined(GDISP_SCREEN_HEIGHT)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+ #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+ #undef GDISP_SCREEN_WIDTH
+#endif
+
+#define GDISP_SCREEN_HEIGHT 320
+#define GDISP_SCREEN_WIDTH 240
+
+#define GDISP_INITIAL_CONTRAST 50
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_STM32_E407)
+ #include "gdisp_lld_board_olimex_e407.h"
+#else
+ #include "gdisp_lld_board.h"
+#endif
+
+/* Some common routines and macros */
+#define write_reg(reg, data) { write_index(reg); write_data(data); }
+#define stream_start() write_index(0x0022);
+#define stream_stop()
+#define delay(us) chThdSleepMicroseconds(us)
+#define delayms(ms) chThdSleepMilliseconds(ms)
+
+static __inline void set_cursor(coord_t x, coord_t y) {
+ /* R20h - 8 bit
+ * R21h - 9 bit
+ */
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ write_reg(0x0020, x & 0x00FF);
+ write_reg(0x0021, y & 0x01FF);
+ break;
+ case GDISP_ROTATE_90:
+ /* Note X has already been mirrored, so we do it directly */
+ write_reg(0x0020, y & 0x00FF);
+ write_reg(0x0021, x & 0x01FF);
+ break;
+ case GDISP_ROTATE_180:
+ write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - x) & 0x00FF);
+ write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - y) & 0x01FF);
+ break;
+ case GDISP_ROTATE_270:
+ write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - y) & 0x00FF);
+ write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - x) & 0x01FF);
+ break;
+ }
+}
+
+static __inline void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ /* HSA / HEA are 8 bit
+ * VSA / VEA are 9 bit
+ * use masks 0x00FF and 0x01FF to enforce this
+ */
+
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ write_reg(0x46, (((x + cx - 1) << 8) & 0xFF00 ) |
+ (x & 0x00FF));
+
+ write_reg(0x48, y & 0x01FF);
+ write_reg(0x47, (y + cy - 1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_90:
+ write_reg(0x46, (((y + cy - 1) << 8) & 0xFF00) |
+ (y & 0x00FF));
+
+ write_reg(0x48, x & 0x01FF);
+ write_reg(0x47, (x + cx - 1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_180:
+ write_reg(0x46, (((GDISP_SCREEN_WIDTH - x - 1) & 0x00FF) << 8) |
+ ((GDISP_SCREEN_WIDTH - (x + cx)) & 0x00FF));
+ write_reg(0x48, (GDISP_SCREEN_HEIGHT - (y + cy)) & 0x01FF);
+ write_reg(0x47, (GDISP_SCREEN_HEIGHT- y - 1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_270:
+ write_reg(0x46, (((GDISP_SCREEN_WIDTH - y - 1) & 0x00FF) << 8) |
+ ((GDISP_SCREEN_WIDTH - (y + cy)) & 0x00FF));
+ write_reg(0x48, (GDISP_SCREEN_HEIGHT - (x + cx)) & 0x01FF);
+ write_reg(0x47, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
+ break;
+ }
+
+ set_cursor(x, y);
+}
+
+static __inline void reset_viewport(void) {
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ set_viewport(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
+ break;
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ set_viewport(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
+ break;
+ }
+}
+
+bool_t lld_gdisp_init(void) {
+ /* initialize the hardware */
+ init_board();
+
+ /* Hardware reset */
+ setpin_reset(TRUE);
+ delayms(20);
+ setpin_reset(TRUE);
+ delayms(20);
+
+ /* Get the bus for the following initialisation commands */
+ acquire_bus();
+
+ write_reg(0x11,0x2004);
+ write_reg(0x13,0xCC00);
+ write_reg(0x15,0x2600);
+ write_reg(0x14,0x252A);
+ write_reg(0x12,0x0033);
+ write_reg(0x13,0xCC04);
+
+ delayms(1);
+
+ write_reg(0x13,0xCC06);
+
+ delayms(1);
+
+ write_reg(0x13,0xCC4F);
+
+ delayms(1);
+
+ write_reg(0x13,0x674F);
+ write_reg(0x11,0x2003);
+
+ delayms(1);
+
+ // Gamma Setting
+ write_reg(0x30,0x2609);
+ write_reg(0x31,0x242C);
+ write_reg(0x32,0x1F23);
+ write_reg(0x33,0x2425);
+ write_reg(0x34,0x2226);
+ write_reg(0x35,0x2523);
+ write_reg(0x36,0x1C1A);
+ write_reg(0x37,0x131D);
+ write_reg(0x38,0x0B11);
+ write_reg(0x39,0x1210);
+ write_reg(0x3A,0x1315);
+ write_reg(0x3B,0x3619);
+ write_reg(0x3C,0x0D00);
+ write_reg(0x3D,0x000D);
+
+ write_reg(0x16,0x0007);
+ write_reg(0x02,0x0013);
+ write_reg(0x03,0x0003);
+ write_reg(0x01,0x0127);
+
+ delayms(1);
+
+ write_reg(0x08,0x0303);
+ write_reg(0x0A,0x000B);
+ write_reg(0x0B,0x0003);
+ write_reg(0x0C,0x0000);
+ write_reg(0x41,0x0000);
+ write_reg(0x50,0x0000);
+ write_reg(0x60,0x0005);
+ write_reg(0x70,0x000B);
+ write_reg(0x71,0x0000);
+ write_reg(0x78,0x0000);
+ write_reg(0x7A,0x0000);
+ write_reg(0x79,0x0007);
+ write_reg(0x07,0x0051);
+
+ delayms(1);
+
+ write_reg(0x07,0x0053);
+ write_reg(0x79,0x0000);
+
+ reset_viewport();
+ set_backlight(GDISP_INITIAL_BACKLIGHT);
+
+ /* Now initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = 100;
+ GDISP.Contrast = 50;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ acquire_bus();
+ set_cursor(x, y);
+ write_reg(0x0022, color);
+ release_bus();
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
+ /**
+ * @brief Clear the display.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+ void lld_gdisp_clear(color_t color) {
+ unsigned i;
+
+ acquire_bus();
+ set_cursor(0, 0);
+ stream_start();
+
+ for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
+ write_data(color);
+
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ unsigned i, area;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ area = cx*cy;
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+ for(i = 0; i < area; i++)
+ write_data(color);
+ stream_stop();
+ reset_viewport();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy;
+ unsigned lg;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ buffer += srcx + srcy * srccx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ write_data(*buffer++);
+ stream_stop();
+ reset_viewport();
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note Optional.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The start of the text
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ /* This routine is marked "DO NOT USE" in the original
+ * GLCD driver. We just keep our GDISP_HARDWARE_READPIXEL
+ * turned off for now.
+ */
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+
+ aquire_bus();
+ set_cursor(x, y);
+ stream_start();
+
+ color = lld_lcdReadData();
+ color = lld_lcdReadData();
+
+ stream_stop();
+ release_bus();
+
+ return color;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ /* This is marked as "TODO: Test this" in the original GLCD driver.
+ * For now we just leave the GDISP_HARDWARE_SCROLL off.
+ */
+ static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
+ coord_t row0, row1;
+ unsigned i, gap, abslines;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ abslines = lines < 0 ? -lines : lines;
+
+ acquire_bus();
+ if (abslines >= cy) {
+ abslines = cy;
+ gap = 0;
+ } else {
+ gap = cy - abslines;
+ for(i = 0; i < gap; i++) {
+ if(lines > 0) {
+ row0 = y + i + lines;
+ row1 = y + i;
+ } else {
+ row0 = (y - i - 1) + lines;
+ row1 = (y - i - 1);
+ }
+
+ /* read row0 into the buffer and then write at row1*/
+ set_viewport(x, row0, cx, 1);
+ lld_lcdReadStreamStart();
+ lld_lcdReadStream(buf, cx);
+ lld_lcdReadStreamStop();
+
+ set_viewport(x, row1, cx, 1);
+ stream_start();
+ write_data(buf, cx);
+ stream_stop();
+ }
+ }
+
+ /* fill the remaining gap */
+ set_viewport(x, lines > 0 ? (y+gap) : y, cx, abslines);
+ stream_start();
+ gap = cx*abslines;
+ for(i = 0; i < gap; i++) write_data(bgcolor);
+ stream_stop();
+ reset_viewport();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_POWER:
+ if (GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ /* Code here */
+ /* break; */
+ case powerOn:
+ /* Code here */
+ /* You may need this ---
+ if (GDISP.Powermode != powerSleep)
+ GDISP_LLD(init();
+ */
+ /* break; */
+ case powerSleep:
+ /* Code here */
+ /* break; */
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ write_reg(0x0001,0x0127);
+ write_reg(0x03, 0b0011);
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_90:
+ write_reg(0x0001,0x0027);
+ write_reg(0x0003, 0b1011);
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_180:
+ write_reg(0x0001,0x0127);
+ write_reg(0x0003, 0b0000);
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_270:
+ write_reg(0x0001,0x0027);
+ write_reg(0x0003, 0b1000);
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+/*
+ case GDISP_CONTROL_BACKLIGHT:
+ case GDISP_CONTROL_CONTRAST:
+*/
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.mk b/drivers/gdisp/S6D1121/gdisp_lld.mk
new file mode 100644
index 00000000..38c23c43
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/S6D1121
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_board_example.h b/drivers/gdisp/S6D1121/gdisp_lld_board_example.h
new file mode 100644
index 00000000..2396b155
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld_board_example.h
@@ -0,0 +1,125 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/S6D1121/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the S6D1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief Initialise the board for the display.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for setpin_reset for your board"
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for set_backlight for your board"
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+#error "SSD1289: You must supply a definition for acquire_bus for your board"
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+#error "SSD1289: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Send data to the index register.
+ *
+ * @param[in] index The index register to set
+ *
+ * @notapi
+ */
+static __inline void write_index(uint16_t index) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for write_index for your board"
+}
+
+/**
+ * @brief Send data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for write_data for your board"
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for read_data for your board"
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h b/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
new file mode 100644
index 00000000..34224425
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
@@ -0,0 +1,94 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
+ * @brief GDISP Graphic Driver subsystem board interface for the S6D1121 display
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+
+static __inline void init_board(void) {
+ int FSMC_Bank = 0;
+
+ /* STM32F4 FSMC init */
+ rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+ /* set pins to FSMC mode */
+ IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+ (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+ IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+ (1 << 13) | (1 << 14) | (1 << 15), 0};
+
+ palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+ palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+ /* FSMC timing */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
+
+ /* Bank1 NOR/SRAM control register configuration */
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+}
+
+static __inline void setpin_reset(bool_t state) {
+ (void)state;
+
+ /* Nothing to do here */
+}
+
+static __inline void set_backlight(uint8_t percent) {
+ (void)percent;
+
+ /* Nothing to do here */
+}
+
+static __inline void acquire_bus(void) {
+ /* Nothing to do here */
+}
+
+static __inline void release_bus(void) {
+ /* Nothing to do here */
+}
+
+static __inline void write_index(uint16_t index) {
+ GDISP_REG = index;
+}
+
+static __inline void write_data(uint16_t data) {
+ GDISP_RAM = data;
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+static __inline uint16_t read_data(void) {
+ return GDISP_RAM;
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_config.h b/drivers/gdisp/S6D1121/gdisp_lld_config.h
new file mode 100644
index 00000000..c662d0e7
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld_config.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/S6D1121/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the S6D1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "S6D1121"
+#define GDISP_LLD(x) gdisp_lld_##x##_S6D1121
+
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_SCROLL TRUE
+#define GDISP_HARDWARE_PIXELREAD FALSE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/gdisp/S6D1121/readme.txt b/drivers/gdisp/S6D1121/readme.txt
new file mode 100644
index 00000000..b76b565f
--- /dev/null
+++ b/drivers/gdisp/S6D1121/readme.txt
@@ -0,0 +1,9 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld.mk
+
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
new file mode 100644
index 00000000..96fb94e6
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -0,0 +1,583 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1289/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 240
+#endif
+
+#define GDISP_INITIAL_CONTRAST 50
+#define GDISP_INITIAL_BACKLIGHT 100
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_FIREBULL_STM32_F103)
+ #include "gdisp_lld_board_firebullstm32f103.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#endif
+
+// Some common routines and macros
+#define write_reg(reg, data) { write_index(reg); write_data(data); }
+#define stream_start() write_index(0x0022);
+#define stream_stop()
+#define delay(us) chThdSleepMicroseconds(us)
+#define delayms(ms) chThdSleepMilliseconds(ms)
+
+static __inline void set_cursor(coord_t x, coord_t y) {
+ /* Reg 0x004E is an 8 bit value
+ * Reg 0x004F is 9 bit
+ * Use a bit mask to make sure they are not set too high
+ */
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_180:
+ write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-x) & 0x00FF);
+ write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-y) & 0x01FF);
+ break;
+ case GDISP_ROTATE_0:
+ write_reg(0x004e, x & 0x00FF);
+ write_reg(0x004f, y & 0x01FF);
+ break;
+ case GDISP_ROTATE_270:
+ write_reg(0x004e, y & 0x00FF);
+ write_reg(0x004f, x & 0x01FF);
+ break;
+ case GDISP_ROTATE_90:
+ write_reg(0x004e, (GDISP_SCREEN_WIDTH - y - 1) & 0x00FF);
+ write_reg(0x004f, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
+ break;
+ }
+}
+
+static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+
+ set_cursor(x, y);
+
+ /* Reg 0x44 - Horizontal RAM address position
+ * Upper Byte - HEA
+ * Lower Byte - HSA
+ * 0 <= HSA <= HEA <= 0xEF
+ * Reg 0x45,0x46 - Vertical RAM address position
+ * Lower 9 bits gives 0-511 range in each value
+ * 0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
+ */
+
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (x & 0x00FF));
+ write_reg(0x45, y & 0x01FF);
+ write_reg(0x46, (y+cy-1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_270:
+ write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
+ write_reg(0x45, x & 0x01FF);
+ write_reg(0x46, (x+cx-1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_180:
+ write_reg(0x44, (((GDISP_SCREEN_WIDTH-x-1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (x+cx)) & 0x00FF));
+ write_reg(0x45, (GDISP_SCREEN_HEIGHT-(y+cy)) & 0x01FF);
+ write_reg(0x46, (GDISP_SCREEN_HEIGHT-y-1) & 0x01FF);
+ break;
+ case GDISP_ROTATE_90:
+ write_reg(0x44, (((GDISP_SCREEN_WIDTH - y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (y+cy)) & 0x00FF));
+ write_reg(0x45, (GDISP_SCREEN_HEIGHT - (x+cx)) & 0x01FF);
+ write_reg(0x46, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
+ break;
+ }
+
+ set_cursor(x, y);
+}
+
+static __inline void reset_viewport(void) {
+ set_viewport(0, 0, GDISP.Width, GDISP.Height);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialization.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ /* Initialise your display */
+ init_board();
+
+ // Hardware reset
+ setpin_reset(TRUE);
+ delayms(20);
+ setpin_reset(FALSE);
+ delayms(20);
+
+ // Get the bus for the following initialisation commands
+ acquire_bus();
+
+ write_reg(0x0000,0x0001); delay(5);
+ write_reg(0x0003,0xA8A4); delay(5);
+ write_reg(0x000C,0x0000); delay(5);
+ write_reg(0x000D,0x080C); delay(5);
+ write_reg(0x000E,0x2B00); delay(5);
+ write_reg(0x001E,0x00B0); delay(5);
+ write_reg(0x0001,0x2B3F); delay(5);
+ write_reg(0x0002,0x0600); delay(5);
+ write_reg(0x0010,0x0000); delay(5);
+ write_reg(0x0011,0x6070); delay(5);
+ write_reg(0x0005,0x0000); delay(5);
+ write_reg(0x0006,0x0000); delay(5);
+ write_reg(0x0016,0xEF1C); delay(5);
+ write_reg(0x0017,0x0003); delay(5);
+ write_reg(0x0007,0x0133); delay(5);
+ write_reg(0x000B,0x0000); delay(5);
+ write_reg(0x000F,0x0000); delay(5);
+ write_reg(0x0041,0x0000); delay(5);
+ write_reg(0x0042,0x0000); delay(5);
+ write_reg(0x0048,0x0000); delay(5);
+ write_reg(0x0049,0x013F); delay(5);
+ write_reg(0x004A,0x0000); delay(5);
+ write_reg(0x004B,0x0000); delay(5);
+ write_reg(0x0044,0xEF00); delay(5);
+ write_reg(0x0045,0x0000); delay(5);
+ write_reg(0x0046,0x013F); delay(5);
+ write_reg(0x0030,0x0707); delay(5);
+ write_reg(0x0031,0x0204); delay(5);
+ write_reg(0x0032,0x0204); delay(5);
+ write_reg(0x0033,0x0502); delay(5);
+ write_reg(0x0034,0x0507); delay(5);
+ write_reg(0x0035,0x0204); delay(5);
+ write_reg(0x0036,0x0204); delay(5);
+ write_reg(0x0037,0x0502); delay(5);
+ write_reg(0x003A,0x0302); delay(5);
+ write_reg(0x003B,0x0302); delay(5);
+ write_reg(0x0023,0x0000); delay(5);
+ write_reg(0x0024,0x0000); delay(5);
+ write_reg(0x0025,0x8000); delay(5);
+ write_reg(0x004f,0x0000); delay(5);
+ write_reg(0x004e,0x0000); delay(5);
+
+ // Release the bus
+ release_bus();
+
+ /* Turn on the back-light */
+ set_backlight(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ acquire_bus();
+ set_cursor(x, y);
+ write_reg(0x0022, color);
+ release_bus();
+}
+
+/* ---- Optional Routines ---- */
+/*
+ All the below routines are optional.
+ Defining them will increase speed but everything
+ will work if they are not defined.
+ If you are not using a routine - turn it off using
+ the appropriate GDISP_HARDWARE_XXXX macro.
+ Don't bother coding for obvious similar routines if
+ there is no performance penalty as the emulation software
+ makes a good job of using similar routines.
+ eg. If gfillarea() is defined there is little
+ point in defining clear() unless the
+ performance bonus is significant.
+ For good performance it is suggested to implement
+ fillarea() and blitarea().
+*/
+
+#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
+ /**
+ * @brief Clear the display.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+ void lld_gdisp_clear(color_t color) {
+ unsigned i;
+
+ acquire_bus();
+ reset_viewport();
+ set_cursor(0, 0);
+ stream_start();
+ for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
+ write_data(color);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ unsigned i, area;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ area = cx*cy;
+
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+ for(i = 0; i < area; i++)
+ write_data(color);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t endx, endy;
+ unsigned lg;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ buffer += srcx + srcy * srccx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ write_data(*buffer++);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note Optional.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The pixel to be read
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+
+ acquire_bus();
+ set_cursor(x, y);
+ stream_start();
+ color = read_data(); // dummy read
+ color = read_data();
+ stream_stop();
+ release_bus();
+
+ return color;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
+ coord_t row0, row1;
+ unsigned i, gap, abslines, j;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ abslines = lines < 0 ? -lines : lines;
+
+ acquire_bus();
+ if (abslines >= cy) {
+ abslines = cy;
+ gap = 0;
+ } else {
+ gap = cy - abslines;
+ for(i = 0; i < gap; i++) {
+ if(lines > 0) {
+ row0 = y + i + lines;
+ row1 = y + i;
+ } else {
+ row0 = (y - i - 1) + lines;
+ row1 = (y - i - 1);
+ }
+
+ /* read row0 into the buffer and then write at row1*/
+ set_viewport(x, row0, cx, 1);
+ stream_start();
+ j = read_data(); // dummy read
+ for (j = 0; j < cx; j++)
+ buf[j] = read_data();
+ stream_stop();
+
+ set_viewport(x, row1, cx, 1);
+ stream_start();
+ for (j = 0; j < cx; j++)
+ write_data(buf[j]);
+ stream_stop();
+ }
+ }
+
+ /* fill the remaining gap */
+ set_viewport(x, lines > 0 ? (y+gap) : y, cx, abslines);
+ stream_start();
+ gap = cx*abslines;
+ for(i = 0; i < gap; i++) write_data(bgcolor);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_POWER:
+ if (GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ acquire_bus();
+ write_reg(0x0010, 0x0000); // leave sleep mode
+ write_reg(0x0007, 0x0000); // halt operation
+ write_reg(0x0000, 0x0000); // turn off oszillator
+ write_reg(0x0010, 0x0001); // enter sleepmode
+ release_bus();
+ break;
+ case powerOn:
+ acquire_bus();
+ write_reg(0x0010, 0x0000); // leave sleep mode
+ release_bus();
+ if (GDISP.Powermode != powerSleep)
+ lld_gdisp_init();
+ break;
+ case powerSleep:
+ acquire_bus();
+ write_reg(0x0010, 0x0001); // enter sleep mode
+ release_bus();
+ break;
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ acquire_bus();
+ write_reg(0x0001, 0x2B3F);
+ /* ID = 11 AM = 0 */
+ write_reg(0x0011, 0x6070);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_90:
+ acquire_bus();
+ write_reg(0x0001, 0x293F);
+ /* ID = 11 AM = 1 */
+ write_reg(0x0011, 0x6078);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_180:
+ acquire_bus();
+ write_reg(0x0001, 0x2B3F);
+ /* ID = 01 AM = 0 */
+ write_reg(0x0011, 0x6040);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_270:
+ acquire_bus();
+ write_reg(0x0001, 0x293F);
+ /* ID = 01 AM = 1 */
+ write_reg(0x0011, 0x6048);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+/*
+ case GDISP_CONTROL_BACKLIGHT:
+ case GDISP_CONTROL_CONTRAST:
+*/
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.mk b/drivers/gdisp/SSD1289/gdisp_lld.mk
new file mode 100644
index 00000000..e340a7dc
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/SSD1289
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_example.h b/drivers/gdisp/SSD1289/gdisp_lld_board_example.h
new file mode 100644
index 00000000..00c4b869
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_example.h
@@ -0,0 +1,125 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1289/gdisp_lld_board_example.h
+ * @brief GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief Initialise the board for the display.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for setpin_reset for your board"
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for set_backlight for your board"
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+#error "SSD1289: You must supply a definition for acquire_bus for your board"
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+#error "SSD1289: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Send data to the index register.
+ *
+ * @param[in] index The index register to set
+ *
+ * @notapi
+ */
+static __inline void write_index(uint16_t index) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for write_index for your board"
+}
+
+/**
+ * @brief Send data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for write_data for your board"
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ /* Code here */
+#error "SSD1289: You must supply a definition for read_data for your board"
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_example_fsmc.h b/drivers/gdisp/SSD1289/gdisp_lld_board_example_fsmc.h
new file mode 100644
index 00000000..76a5c04c
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_example_fsmc.h
@@ -0,0 +1,164 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1289/gdisp_lld_board_example_fsmc.h
+ * @brief GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define GDISP_REG ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
+#define GDISP_RAM ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes Performs the following functions:
+ * 1. initialise the io port used by your display
+ * 2. initialise the reset pin (initial state not-in-reset)
+ * 3. initialise the chip select pin (initial state not-active)
+ * 4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ const unsigned char FSMC_Bank;
+
+ #if defined(STM32F1XX) || defined(STM32F3XX)
+ /* FSMC setup for F1/F3 */
+ rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+ #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ #error "DMA not implemented for F1/F3 Devices"
+ #endif
+ #elif defined(STM32F4XX) || defined(STM32F2XX)
+ /* STM32F2-F4 FSMC init */
+ rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+ #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) chSysHalt();
+ dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
+ dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+ #endif
+ #else
+ #error "FSMC not implemented for this device"
+ #endif
+
+ /* set pins to FSMC mode */
+ IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+ (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+ IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+ (1 << 13) | (1 << 14) | (1 << 15), 0};
+
+ palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+ palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+ FSMC_Bank = 0;
+
+ /* FSMC timing */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
+ | (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
+ | (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
+
+ /* Bank1 NOR/SRAM control register configuration
+ * This is actually not needed as already set by default after reset */
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ (void) state;
+ /* Nothing to do here */
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ (void) percent;
+ /* Nothing to do here */
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Nothing to do here */
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Nothing to do here */
+}
+
+/**
+ * @brief Send data to the index register.
+ *
+ * @param[in] index The index register to set
+ *
+ * @notapi
+ */
+static __inline void write_index(uint16_t index) { GDISP_REG = index; }
+
+/**
+ * @brief Send data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) { GDISP_RAM = data; }
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) { return GDISP_RAM; }
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h b/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
new file mode 100644
index 00000000..9cff5a19
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
@@ -0,0 +1,157 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
+ * @brief GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define SET_CS palSetPad(GPIOD, 12);
+#define CLR_CS palClearPad(GPIOD, 12);
+#define SET_RS palSetPad(GPIOD, 13);
+#define CLR_RS palClearPad(GPIOD, 13);
+#define SET_WR palSetPad(GPIOD, 14);
+#define CLR_WR palClearPad(GPIOD, 14);
+#define SET_RD palSetPad(GPIOD, 15);
+#define CLR_RD palClearPad(GPIOD, 15);
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
+
+ // Configure the pins to a well know state
+ SET_RS;
+ SET_RD;
+ SET_WR;
+ CLR_CS;
+}
+
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static __inline void setpin_reset(bool_t state) {
+ (void) state;
+ /* Nothing to do here - reset pin tied to Vcc */
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static __inline void set_backlight(uint8_t percent) {
+ (void) percent;
+ /* Nothing to do here - Backlight always on */
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void acquire_bus(void) {
+ /* Nothing to do here since LCD is the only device on that bus */
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Nothing to do here since LCD is the only device on that bus */
+}
+
+/**
+ * @brief Send data to the index register.
+ *
+ * @param[in] index The index register to set
+ *
+ * @notapi
+ */
+static __inline void write_index(uint16_t index) {
+ palWritePort(GPIOE, index);
+ CLR_RS; CLR_WR; SET_WR; SET_RS;
+}
+
+/**
+ * @brief Send data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static __inline void write_data(uint16_t data) {
+ palWritePort(GPIOE, data);
+ CLR_WR; SET_WR;
+}
+
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static __inline uint16_t read_data(void) {
+ uint16_t value;
+
+ // change pin mode to digital input
+ palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+
+ CLR_RD;
+ value = palReadPort(GPIOE);
+ value = palReadPort(GPIOE);
+ SET_RD;
+
+ // change pin mode back to digital output
+ palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+
+ return value;
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
new file mode 100644
index 00000000..dafbc90f
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -0,0 +1,53 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1289/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "SSD1289"
+#define GDISP_LLD(x) gdisp_lld_##x##_SSD1289
+
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_SCROLL TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/readme.txt b/drivers/gdisp/SSD1289/readme.txt
new file mode 100644
index 00000000..b160abbe
--- /dev/null
+++ b/drivers/gdisp/SSD1289/readme.txt
@@ -0,0 +1,19 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+
+ c) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_example.h or gdisp_lld_board_fsmc.h file as a basis.
+ Currently known boards are:
+ BOARD_FIREBULL_STM32_F103 - GPIO interface: requires GDISP_CMD_PORT and GDISP_DATA_PORT to be defined
+
+ d) The following are optional - define them if you are not using the defaults below:
+ #define GDISP_SCREEN_WIDTH 320
+ #define GDISP_SCREEN_HEIGHT 240
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld.mk
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c
new file mode 100644
index 00000000..0b676ebc
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld.c
@@ -0,0 +1,613 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1963/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 240
+#endif
+
+/* All the board specific code should go in these include file so the driver
+ * can be ported to another board just by creating a suitable file.
+ */
+//#if defined(BOARD_YOURBOARDNAME)
+// #include "gdisp_lld_board_yourboardname.h"
+//#else
+// /* Include the user supplied board definitions */
+// #include "gdisp_lld_board.h"
+//#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+#include "ssd1963.h"
+
+
+#if defined(GDISP_USE_FSMC)
+__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
+ GDISP_REG = cmd;
+}
+
+__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
+ GDISP_REG = lcdReg;
+ GDISP_RAM = lcdRegValue;
+}
+
+__inline void GDISP_LLD(writedata)(uint16_t data) {
+ GDISP_RAM = data;
+}
+
+__inline uint16_t GDISP_LLD(readdata)(void) {
+ return (GDISP_RAM);
+}
+
+__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
+ GDISP_REG = lcdReg;
+ return (GDISP_RAM);
+}
+
+__inline void GDISP_LLD(writestreamstart)(void) {
+ GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
+}
+
+__inline void GDISP_LLD(readstreamstart)(void) {
+ GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
+}
+
+__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) {
+ uint16_t i;
+ for(i = 0; i < size; i++)
+ GDISP_RAM = buffer[i];
+}
+
+__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) {
+ uint16_t i;
+
+ for(i = 0; i < size; i++) {
+ buffer[i] = GDISP_RAM;
+ }
+}
+
+#elif defined(GDISP_USE_GPIO)
+
+__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
+ Set_CS; Set_RS; Set_WR; Clr_RD;
+ palWritePort(GDISP_DATA_PORT, cmd);
+ Clr_CS;
+}
+
+__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
+ Set_CS; Set_RS; Set_WR; Clr_RD;
+ palWritePort(GDISP_DATA_PORT, lcdReg);
+ Clr_RS;
+ palWritePort(GDISP_DATA_PORT, lcdRegValue);
+ Clr_CS;
+}
+__inline void GDISP_LLD(writedata)(uint16_t data) {
+ Set_CS; Clr_RS; Set_WR; Clr_RD;
+ palWritePort(GDISP_DATA_PORT, data);
+ Clr_CS;
+}
+
+__inline uint16_t GDISP_LLD(readdata)(void) {
+ Set_CS; Clr_RS; Clr_WR; Set_RD;
+ uint16_t data = palReadPort(GDISP_DATA_PORT);
+ Clr_CS;
+ return data;
+}
+
+__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
+ Set_CS; Set_RS; Clr_WR; Set_RD;
+ palWritePort(GDISP_DATA_PORT, lcdReg);
+ Clr_RS;
+ uint16_t data = palReadPort(GDISP_DATA_PORT);
+ Clr_CS;
+ return data;
+}
+
+__inline void GDISP_LLD(writestreamstart)(void) {
+ GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
+}
+
+__inline void GDISP_LLD(readstreamstart)(void) {
+ GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
+}
+
+__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) {
+ uint16_t i;
+ Set_CS; Clr_RS; Set_WR; Clr_RD;
+ for(i = 0; i < size; i++) {
+ Set_WR;
+ palWritePort(GDISP_DATA_PORT, buffer[i]);
+ Clr_WR;
+ }
+ Clr_CS;
+}
+
+__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) {
+ uint16_t i;
+ Set_CS; Clr_RS; Clr_WR; Set_RD;
+ for(i = 0; i < size; i++) {
+ Set_RD;
+ buffer[i] = palReadPort(GDISP_DATA_PORT);
+ Clr_RD;
+ }
+}
+#endif
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialisation.
+ * @return TRUE if successful, FALSE on error.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ /* Initialise the display */
+
+#if defined(GDISP_USE_FSMC)
+
+ #if defined(STM32F1XX) || defined(STM32F3XX)
+ /* FSMC setup for F1/F3 */
+ rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+ #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ #error "DMA not implemented for F1/F3 Devices"
+ #endif
+ #elif defined(STM32F4XX) || defined(STM32F2XX)
+ /* STM32F2-F4 FSMC init */
+ rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+ #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) chSysHalt();
+ dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
+ dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+ #endif
+ #else
+ #error "FSMC not implemented for this device"
+ #endif
+
+ /* set pins to FSMC mode */
+ IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+ (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+ IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+ (1 << 13) | (1 << 14) | (1 << 15), 0};
+
+ palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+ palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+ const unsigned char FSMC_Bank = 0;
+ /* FSMC timing */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
+ | (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
+ | (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
+
+ /* Bank1 NOR/SRAM control register configuration
+ * This is actually not needed as already set by default after reset */
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+
+#elif defined(GDISP_USE_GPIO)
+ IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0};
+ IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0};
+ palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL);
+
+#else
+ #error "Please define GDISP_USE_FSMC or GDISP_USE_GPIO"
+#endif
+ GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);
+ chThdSleepMicroseconds(100);
+
+ /* Driver PLL config */
+ GDISP_LLD(writeindex)(SSD1963_SET_PLL_MN);
+ GDISP_LLD(writedata)(35); // PLLclk = REFclk (10Mhz) * 36 (360Mhz)
+ GDISP_LLD(writedata)(2); // SYSclk = PLLclk / 3 (120MHz)
+ GDISP_LLD(writedata)(4); // Apply calculation bit, else it is ignored
+
+ GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Enable PLL
+ GDISP_LLD(writedata)(0x01);
+ chThdSleepMicroseconds(200);
+
+ GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Use PLL
+ GDISP_LLD(writedata)(0x03);
+ chThdSleepMicroseconds(200);
+
+ GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);
+ chThdSleepMicroseconds(100);
+
+ /* Screen size */
+ GDISP_LLD(writeindex)(SSD1963_SET_GDISP_MODE);
+// GDISP_LLD(writedata)(0x0000);
+ GDISP_LLD(writedata)(0b00011000); //Enabled dithering
+ GDISP_LLD(writedata)(0x0000);
+ GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_WIDTH+1)));
+ GDISP_LLD(writedata)((GDISP_SCREEN_WIDTH+1));
+ GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_HEIGHT+1)));
+ GDISP_LLD(writedata)((GDISP_SCREEN_HEIGHT+1));
+ GDISP_LLD(writedata)(0x0000);
+
+ GDISP_LLD(writeindex)(SSD1963_SET_PIXEL_DATA_INTERFACE);
+ GDISP_LLD(writedata)(SSD1963_PDI_16BIT565);
+
+ /* LCD Clock specs */
+ GDISP_LLD(writeindex)(SSD1963_SET_LSHIFT_FREQ);
+ GDISP_LLD(writedata)((GDISP_FPR >> 16) & 0xFF);
+ GDISP_LLD(writedata)((GDISP_FPR >> 8) & 0xFF);
+ GDISP_LLD(writedata)(GDISP_FPR & 0xFF);
+
+ GDISP_LLD(writeindex)(SSD1963_SET_HORI_PERIOD);
+ GDISP_LLD(writedata)(mHIGH(SCREEN_HSYNC_PERIOD));
+ GDISP_LLD(writedata)(mLOW(SCREEN_HSYNC_PERIOD));
+ GDISP_LLD(writedata)(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
+ GDISP_LLD(writedata)(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
+ GDISP_LLD(writedata)(SCREEN_HSYNC_PULSE);
+ GDISP_LLD(writedata)(0x00);
+ GDISP_LLD(writedata)(0x00);
+ GDISP_LLD(writedata)(0x00);
+
+ GDISP_LLD(writeindex)(SSD1963_SET_VERT_PERIOD);
+ GDISP_LLD(writedata)(mHIGH(SCREEN_VSYNC_PERIOD));
+ GDISP_LLD(writedata)(mLOW(SCREEN_VSYNC_PERIOD));
+ GDISP_LLD(writedata)(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
+ GDISP_LLD(writedata)(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
+ GDISP_LLD(writedata)(SCREEN_VSYNC_PULSE);
+ GDISP_LLD(writedata)(0x00);
+ GDISP_LLD(writedata)(0x00);
+
+ /* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel */
+ GDISP_LLD(writeindex)(SSD1963_SET_TEAR_ON);
+ GDISP_LLD(writedata)(0x0000);
+
+ /* Turn on */
+ GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
+ #if defined(GDISP_USE_FSMC)
+ /* FSMC delay reduced as the controller now runs at full speed */
+ FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
+ FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+ #endif
+
+ /* Initialise the GDISP structure to match */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = 100;
+ GDISP.Contrast = 50;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+
+ return TRUE;
+}
+
+void GDISP_LLD(setwindow)(coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
+ /* We don't need to validate here as the LLD routines will validate first.
+ *
+ * #if GDISP_NEED_VALIDATION
+ * if (x0 >= GDISP.Width || y0 >= GDISP.Height || x0 < 0 || y0 < 0) return;
+ * else if (x1 >= GDISP.Width || y1 >= GDISP.Height || y1 < 0 || y2 < 0) return;
+ * #endif
+ */
+ GDISP_LLD(writeindex)(SSD1963_SET_PAGE_ADDRESS);
+ GDISP_LLD(writedata)((y0 >> 8) & 0xFF);
+ GDISP_LLD(writedata)((y0 >> 0) & 0xFF);
+ GDISP_LLD(writedata)((y1 >> 8) & 0xFF);
+ GDISP_LLD(writedata)((y1 >> 0) & 0xFF);
+ GDISP_LLD(writeindex)(SSD1963_SET_COLUMN_ADDRESS);
+ GDISP_LLD(writedata)((x0 >> 8) & 0xFF);
+ GDISP_LLD(writedata)((x0 >> 0) & 0xFF);
+ GDISP_LLD(writedata)((x1 >> 8) & 0xFF);
+ GDISP_LLD(writedata)((x1 >> 0) & 0xFF);
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ GDISP_LLD(setwindow)(x, y, x, y);
+ GDISP_LLD(writestreamstart)();
+ GDISP_LLD(writedata)(color);
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ uint32_t area;
+ area = cx*cy;
+
+ GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1);
+ GDISP_LLD(writestreamstart)();
+
+ #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ uint8_t i;
+ dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
+ dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+ for (i = area/65535; i; i--) {
+ dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
+ dmaStreamEnable(GDISP_DMA_STREAM);
+ dmaWaitCompletion(GDISP_DMA_STREAM);
+ }
+ dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
+ dmaStreamEnable(GDISP_DMA_STREAM);
+ dmaWaitCompletion(GDISP_DMA_STREAM);
+ #else
+ uint32_t index;
+ for(index = 0; index < area; index++)
+ GDISP_LLD(writedata)(color);
+ #endif //#ifdef GDISP_USE_DMA
+}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1);
+ GDISP_LLD(writestreamstart)();
+
+ buffer += srcx + srcy * srccx;
+
+ #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+ uint32_t area = cx*cy;
+ uint8_t i;
+ dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+ dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+ for (i = area/65535; i; i--) {
+ dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
+ dmaStreamEnable(GDISP_DMA_STREAM);
+ dmaWaitCompletion(GDISP_DMA_STREAM);
+ }
+ dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
+ dmaStreamEnable(GDISP_DMA_STREAM);
+ dmaWaitCompletion(GDISP_DMA_STREAM);
+ #else
+ coord_t endx, endy;
+ unsigned lg;
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ GDISP_LLD(writedata)(*buffer++);
+ #endif //#ifdef GDISP_USE_DMA
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+ /* NOT IMPLEMENTED YET */
+
+ /*
+ uint16_t size = x1 - x0 ;
+
+ lld_lcdWriteIndex(SSD1963_SET_SCROLL_AREA);
+ lld_lcdWriteData((x0 >> 8) & 0xFF);
+ lld_lcdWriteData((x0 >> 0) & 0xFF);
+ lld_lcdWriteData((size >> 8) & 0xFF);
+ lld_lcdWriteData((size >> 0) & 0xFF);
+ lld_lcdWriteData(((lcd_height-x1) >> 8) & 0xFF);
+ lld_lcdWriteData(((lcd_height-x1) >> 0) & 0xFF);
+
+ lld_lcdWriteIndex(SSD1963_SET_SCROLL_START);
+ lld_lcdWriteData((lines >> 8) & 0xFF);
+ lld_lcdWriteData((lines >> 0) & 0xFF);
+ */
+ }
+
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ /* NOT IMPLEMENTED YET */
+ switch(what) {
+ case GDISP_CONTROL_POWER:
+ if (GDISP.Powermode == (gdisp_powermode_t)value)
+ return;
+ switch((gdisp_powermode_t)value) {
+ case powerOff:
+ GDISP_LLD(writeindex)(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
+ chThdSleepMicroseconds(5000);
+ GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
+ GDISP_LLD(writeindex)(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
+ break;
+ case powerOn:
+ GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); // 2x Dummy reads to wake up from deep sleep
+ GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000);
+ if (GDISP.Powermode != powerSleep)
+ lld_gdisp_init();
+ GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
+
+ break;
+ case powerSleep:
+ GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
+ GDISP_LLD(writeindex)(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
+ chThdSleepMicroseconds(5000);
+ break;
+ default:
+ return;
+ }
+ GDISP.Powermode = (gdisp_powermode_t)value;
+ return;
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ /* Code here */
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_90:
+ /* Code here */
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_180:
+ /* Code here */
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+ case GDISP_ROTATE_270:
+ /* Code here */
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+/*
+ case GDISP_CONTROL_BACKLIGHT:
+ case GDISP_CONTROL_CONTRAST:
+*/
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.mk b/drivers/gdisp/SSD1963/gdisp_lld.mk
new file mode 100644
index 00000000..7b967502
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/SSD1963
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_config.h b/drivers/gdisp/SSD1963/gdisp_lld_config.h
new file mode 100644
index 00000000..34b4f72b
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld_config.h
@@ -0,0 +1,53 @@
+/*
+ ChibiOS/GFX Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/SSD1963/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "SSD1963"
+#define GDISP_LLD(x) gdisp_lld_##x##_SSD1963
+
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+/* Maybe someday soon */
+#define GDISP_HARDWARE_SCROLL FALSE
+#define GDISP_HARDWARE_CONTROL FALSE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_panel.h b/drivers/gdisp/SSD1963/gdisp_lld_panel.h
new file mode 100644
index 00000000..b4ed5c80
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld_panel.h
@@ -0,0 +1,53 @@
+/*
+ ChibiOS/GFX Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file SSD1963/gdisp_lld_panel.h
+ * @brief TFT LCD panel properties.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_PANEL_H
+#define _GDISP_LLD_PANEL_H
+
+/* LCD panel specs */
+#define GDISP_SCREEN_WIDTH 480
+#define GDISP_SCREEN_HEIGHT 272
+
+#define SCREEN_FPS 60ULL
+
+#define SCREEN_HSYNC_BACK_PORCH 2LL
+#define SCREEN_HSYNC_FRONT_PORCH 2ULL
+#define SCREEN_HSYNC_PULSE 41ULL
+
+#define SCREEN_VSYNC_BACK_PORCH 2ULL
+#define SCREEN_VSYNC_FRONT_PORCH 2ULL
+#define SCREEN_VSYNC_PULSE 10ULL
+
+#define SCREEN_HSYNC_PERIOD (SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH + GDISP_SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH)
+#define SCREEN_VSYNC_PERIOD (SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH + GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH)
+
+#define SCREEN_PCLK (SCREEN_HSYNC_PERIOD * SCREEN_VSYNC_PERIOD * SCREEN_FPS)
+#define GDISP_FPR ((SCREEN_PCLK * 1048576)/100000000)
+
+#endif
+/** @} */
diff --git a/drivers/gdisp/SSD1963/readme.txt b/drivers/gdisp/SSD1963/readme.txt
new file mode 100644
index 00000000..567faf58
--- /dev/null
+++ b/drivers/gdisp/SSD1963/readme.txt
@@ -0,0 +1,38 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h) eg: #define GDISP_NEED_MULTITHREAD TRUE
+ c) One (only) of:
+ #define GDISP_USE_GPIO
+ #define GDISP_USE_FSMC
+ d) If you want to use DMA (only works with FSMC):
+ #define GDISP_USE_DMA
+ #define GDISP_DMA_STREAM STM32_DMA2_STREAM6 //You can change the DMA channel according to your needs
+
+2. Edit gdisp_lld_panel.h with your panel properties
+
+3. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.mk
+
+
+Example FSMC config with DMA:
+
+#define GDISP_SCREEN_WIDTH 480
+#define GDISP_SCREEN_HEIGHT 272
+
+#define GDISP_USE_FSMC
+
+#define GDISP_USE_DMA
+#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
+
+#if defined(GDISP_USE_GPIO)
+
+ #define GDISP_CMD_PORT GPIOC
+ #define GDISP_DATA_PORT GPIOD
+
+ #define GDISP_CS 0
+ #define GDISP_RS 1
+ #define GDISP_WR 2
+ #define GDISP_RD 3
+#endif
diff --git a/drivers/gdisp/SSD1963/ssd1963.h b/drivers/gdisp/SSD1963/ssd1963.h
new file mode 100644
index 00000000..1aa28382
--- /dev/null
+++ b/drivers/gdisp/SSD1963/ssd1963.h
@@ -0,0 +1,133 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+#ifndef SSD1963_H
+#define SSD1963_H
+
+#include "gdisp_lld_panel.h"
+
+#if defined(GDISP_USE_GPIO)
+ #define Set_CS palSetPad(GDISP_CMD_PORT, GDISP_CS);
+ #define Clr_CS palClearPad(GDISP_CMD_PORT, GDISP_CS);
+ #define Set_RS palSetPad(GDISP_CMD_PORT, GDISP_RS);
+ #define Clr_RS palClearPad(GDISP_CMD_PORT, GDISP_RS);
+ #define Set_WR palSetPad(GDISP_CMD_PORT, GDISP_WR);
+ #define Clr_WR palClearPad(GDISP_CMD_PORT, GDISP_WR);
+ #define Set_RD palSetPad(GDISP_CMD_PORT, GDISP_RD);
+ #define Clr_RD palClearPad(GDISP_CMD_PORT, GDISP_RD);
+#endif
+
+#if defined(GDISP_USE_FSMC)
+ /* Using FSMC A16 as RS */
+ #define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+ #define GDISP_RAM (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+#endif
+
+#define mHIGH(x) (x >> 8)
+#define mLOW(x) (x & 0xFF)
+
+/* SSD1963 commands */
+
+#define SSD1963_NOP 0x0000
+#define SSD1963_SOFT_RESET 0x0001
+#define SSD1963_GET_POWER_MODE 0x000A
+#define SSD1963_GET_ADDRESS_MODE 0x000B
+#define SSD1963_GET_DISPLAY_MODE 0x000D
+#define SSD1963_GET_TEAR_EFFECT_STATUS 0x000E
+#define SSD1963_ENTER_SLEEP_MODE 0x0010
+#define SSD1963_EXIT_SLEEP_MODE 0x0011
+#define SSD1963_ENTER_PARTIAL_MODE 0x0012
+#define SSD1963_ENTER_NORMAL_MODE 0x0013
+#define SSD1963_EXIT_INVERT_MODE 0x0020
+#define SSD1963_ENTER_INVERT_MODE 0x0021
+#define SSD1963_SET_GAMMA_CURVE 0x0026
+#define SSD1963_SET_DISPLAY_OFF 0x0028
+#define SSD1963_SET_DISPLAY_ON 0x0029
+#define SSD1963_SET_COLUMN_ADDRESS 0x002A
+#define SSD1963_SET_PAGE_ADDRESS 0x002B
+#define SSD1963_WRITE_MEMORY_START 0x002C
+#define SSD1963_READ_MEMORY_START 0x002E
+#define SSD1963_SET_PARTIAL_AREA 0x0030
+#define SSD1963_SET_SCROLL_AREA 0x0033
+#define SSD1963_SET_TEAR_OFF 0x0034
+#define SSD1963_SET_TEAR_ON 0x0035
+#define SSD1963_SET_ADDRESS_MODE 0x0036
+#define SSD1963_SET_SCROLL_START 0x0037
+#define SSD1963_EXIT_IDLE_MODE 0x0038
+#define SSD1963_ENTER_IDLE_MODE 0x0039
+#define SSD1963_SET_PIXEL_FORMAT 0x003A
+#define SSD1963_WRITE_MEMORY_CONTINUE 0x003C
+#define SSD1963_READ_MEMORY_CONTINUE 0x003E
+#define SSD1963_SET_TEAR_SCANLINE 0x0044
+#define SSD1963_GET_SCANLINE 0x0045
+#define SSD1963_READ_DDB 0x00A1
+#define SSD1963_SET_GDISP_MODE 0x00B0
+#define SSD1963_GET_GDISP_MODE 0x00B1
+#define SSD1963_SET_HORI_PERIOD 0x00B4
+#define SSD1963_GET_HORI_PERIOD 0x00B5
+#define SSD1963_SET_VERT_PERIOD 0x00B6
+#define SSD1963_GET_VERT_PERIOD 0x00B7
+#define SSD1963_SET_GPIO_CONF 0x00B8
+#define SSD1963_GET_GPIO_CONF 0x00B9
+#define SSD1963_SET_GPIO_VALUE 0x00BA
+#define SSD1963_GET_GPIO_STATUS 0x00BB
+#define SSD1963_SET_POST_PROC 0x00BC
+#define SSD1963_GET_POST_PROC 0x00BD
+#define SSD1963_SET_PWM_CONF 0x00BE
+#define SSD1963_GET_PWM_CONF 0x00BF
+#define SSD1963_GET_GDISP_GEN0 0x00C0
+#define SSD1963_SET_GDISP_GEN0 0x00C1
+#define SSD1963_GET_GDISP_GEN1 0x00C2
+#define SSD1963_SET_GDISP_GEN1 0x00C3
+#define SSD1963_GET_GDISP_GEN2 0x00C4
+#define SSD1963_SET_GDISP_GEN2 0x00C5
+#define SSD1963_GET_GDISP_GEN3 0x00C6
+#define SSD1963_SET_GDISP_GEN3 0x00C7
+#define SSD1963_SET_GPIO0_ROP 0x00C8
+#define SSD1963_GET_GPIO0_ROP 0x00C9
+#define SSD1963_SET_GPIO1_ROP 0x00CA
+#define SSD1963_GET_GPIO1_ROP 0x00CB
+#define SSD1963_SET_GPIO2_ROP 0x00CC
+#define SSD1963_GET_GPIO2_ROP 0x00CD
+#define SSD1963_SET_GPIO3_ROP 0x00CE
+#define SSD1963_GET_GPIO3_ROP 0x00CF
+#define SSD1963_SET_DBC_CONF 0x00D0
+#define SSD1963_GET_DBC_CONF 0x00D1
+#define SSD1963_SET_DBC_TH 0x00D4
+#define SSD1963_GET_DBC_TH 0x00D5
+#define SSD1963_SET_PLL 0x00E0
+#define SSD1963_SET_PLL_MN 0x00E2
+#define SSD1963_GET_PLL_MN 0x00E3
+#define SSD1963_GET_PLL_STATUS 0x00E4
+#define SSD1963_SET_DEEP_SLEEP 0x00E5
+#define SSD1963_SET_LSHIFT_FREQ 0x00E6
+#define SSD1963_GET_LSHIFT_FREQ 0x00E7
+#define SSD1963_SET_PIXEL_DATA_INTERFACE 0x00F0
+ #define SSD1963_PDI_8BIT 0
+ #define SSD1963_PDI_12BIT 1
+ #define SSD1963_PDI_16BIT 2
+ #define SSD1963_PDI_16BIT565 3
+ #define SSD1963_PDI_18BIT 4
+ #define SSD1963_PDI_24BIT 5
+ #define SSD1963_PDI_9BIT 6
+#define SSD1963_GET_PIXEL_DATA_INTERFACE 0x00F1
+
+#endif
+
diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c
new file mode 100644
index 00000000..be323912
--- /dev/null
+++ b/drivers/gdisp/TestStub/gdisp_lld.c
@@ -0,0 +1,133 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/TestStub/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source (stub).
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 128
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 128
+#endif
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialization.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ /* Initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOff;
+ GDISP.Backlight = 100;
+ GDISP.Contrast = 50;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ (void)x;
+ (void)y;
+ (void)color;
+}
+
+/* ---- Optional Routines ---- */
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note Optional.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The start of the text
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ (void)x;
+ (void)y;
+
+ return 0;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ (void)x;
+ (void)y;
+ (void)cx;
+ (void)cy;
+ (void)lines;
+ (void)bgcolor;
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/TestStub/gdisp_lld.mk b/drivers/gdisp/TestStub/gdisp_lld.mk
new file mode 100644
index 00000000..5f35be9d
--- /dev/null
+++ b/drivers/gdisp/TestStub/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/TestStub
diff --git a/drivers/gdisp/TestStub/gdisp_lld_config.h b/drivers/gdisp/TestStub/gdisp_lld_config.h
new file mode 100644
index 00000000..18c2de59
--- /dev/null
+++ b/drivers/gdisp/TestStub/gdisp_lld_config.h
@@ -0,0 +1,51 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/TestStub/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header (stub).
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "TestStub"
+#define GDISP_LLD(x) gdisp_lld_##x##_TestStub
+
+#define GDISP_HARDWARE_SCROLL GDISP_NEED_SCROLL
+#define GDISP_HARDWARE_PIXELREAD GDISP_NEED_PIXELREAD
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+#define GDISP_PACKED_PIXELS FALSE
+#define GDISP_PACKED_LINES FALSE
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/gdisp/TestStub/readme.txt b/drivers/gdisp/TestStub/readme.txt
new file mode 100644
index 00000000..11145290
--- /dev/null
+++ b/drivers/gdisp/TestStub/readme.txt
@@ -0,0 +1,16 @@
+This low level driver is a test stub that doesn't talk to any
+real hardware. It is included to allow testing of the compilation
+process.
+
+Do not use this driver as a template for new drivers. Use the
+ templates/gdispXXXXX directory for that.
+
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h)
+ you want to compile test eg: GDISP_NEED_MULTITHREAD
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld.mk
diff --git a/drivers/gdisp/VMT/gdisp_lld.c b/drivers/gdisp/VMT/gdisp_lld.c
new file mode 100644
index 00000000..9d9c7382
--- /dev/null
+++ b/drivers/gdisp/VMT/gdisp_lld.c
@@ -0,0 +1,271 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/VMT/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for VMT.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#define GDISP_LLD_NO_STRUCT
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define GDISP_LLD1(x) GDISP_VMT_NAME1(gdisp_lld_##x##_)
+#define GDISP_LLD2(x) GDISP_VMT_NAME2(gdisp_lld_##x##_)
+
+/* Prototypes for lld driver functions */
+bool_t GDISP_LLD1(init)(void);
+void *GDISP_LLD1(query)(unsigned what);
+void GDISP_LLD1(clear)(color_t color);
+void GDISP_LLD1(drawpixel)(coord_t x, coord_t y, color_t color);
+void GDISP_LLD1(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+void GDISP_LLD1(blitareaex)(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);
+void GDISP_LLD1(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color);
+#if GDISP_NEED_CLIP
+ void GDISP_LLD1(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy);
+#endif
+#if GDISP_NEED_CIRCLE
+ void GDISP_LLD1(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+ void GDISP_LLD1(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+#endif
+#if GDISP_NEED_ELLIPSE
+ void GDISP_LLD1(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ void GDISP_LLD1(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+#endif
+#if GDISP_NEED_ARC
+ void GDISP_LLD1(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ void GDISP_LLD1(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+#endif
+#if GDISP_NEED_TEXT
+ void GDISP_LLD1(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color);
+ void GDISP_LLD1(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor);
+#endif
+#if GDISP_NEED_PIXELREAD
+ color_t GDISP_LLD1(getpixelcolor)(coord_t x, coord_t y);
+#endif
+#if GDISP_NEED_SCROLL
+ void GDISP_LLD1(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor);
+#endif
+#if GDISP_NEED_CONTROL
+ void GDISP_LLD1(control)(unsigned what, void *value);
+#endif
+
+bool_t GDISP_LLD2(init)(void);
+void *GDISP_LLD2(query)(unsigned what);
+void GDISP_LLD2(clear)(color_t color);
+void GDISP_LLD2(drawpixel)(coord_t x, coord_t y, color_t color);
+void GDISP_LLD2(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+void GDISP_LLD2(blitareaex)(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);
+void GDISP_LLD2(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color);
+#if GDISP_NEED_CLIP
+ void GDISP_LLD2(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy);
+#endif
+#if GDISP_NEED_CIRCLE
+ void GDISP_LLD2(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+ void GDISP_LLD2(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+#endif
+#if GDISP_NEED_ELLIPSE
+ void GDISP_LLD2(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ void GDISP_LLD2(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+#endif
+#if GDISP_NEED_ARC
+ void GDISP_LLD2(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ void GDISP_LLD2(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+#endif
+#if GDISP_NEED_TEXT
+ void GDISP_LLD2(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color);
+ void GDISP_LLD2(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor);
+#endif
+#if GDISP_NEED_PIXELREAD
+ color_t GDISP_LLD2(getpixelcolor)(coord_t x, coord_t y);
+#endif
+#if GDISP_NEED_SCROLL
+ void GDISP_LLD2(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor);
+#endif
+#if GDISP_NEED_CONTROL
+ void GDISP_LLD2(control)(unsigned what, void *value);
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/* Our VMT table variables */
+void *GDISP_LLD_VMT(query)(unsigned what);
+void GDISP_LLD_VMT(clear)(color_t color);
+void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color);
+void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+void GDISP_LLD_VMT(blitareaex)(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);
+void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color);
+
+#if GDISP_NEED_CIRCLE
+void GDISP_LLD_VMT(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+void GDISP_LLD_VMT(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+#endif
+
+#if GDISP_NEED_ELLIPSE
+void GDISP_LLD_VMT(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+void GDISP_LLD_VMT(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+#endif
+
+/* Text Rendering Functions */
+#if GDISP_NEED_TEXT
+void GDISP_LLD_VMT(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color);
+void GDISP_LLD_VMT(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor);
+#endif
+
+/* Pixel readback */
+#if GDISP_NEED_PIXELREAD
+color_t GDISP_LLD_VMT(getpixelcolor)(coord_t x, coord_t y);
+#endif
+
+/* Scrolling Function - clears the area scrolled out */
+#if GDISP_NEED_SCROLL
+void GDISP_LLD_VMT(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor);
+#endif
+
+/* Set driver specific control */
+#if GDISP_NEED_CONTROL
+void GDISP_LLD_VMT(control)(unsigned what, void *value);
+#endif
+/* Clipping Functions */
+#if GDISP_NEED_CLIP
+void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy);
+#endif
+
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+bool_t gdisp_lld_init_VMT(void) {
+ if (GDISP_VMT_NAME1(gdisp_lld_init_)()) {
+ gdisp_lld_query_VMT = GDISP_VMT_NAME1(gdisp_lld_query_);
+ gdisp_lld_clear_VMT = GDISP_VMT_NAME1(gdisp_lld_clear_);
+ gdisp_lld_drawpixel_VMT = GDISP_VMT_NAME1(gdisp_lld_drawpixel_);
+ gdisp_lld_fillarea_VMT = GDISP_VMT_NAME1(gdisp_lld_fillarea_);
+ gdisp_lld_blitareaex_VMT = GDISP_VMT_NAME1(gdisp_lld_blitareaex_);
+ gdisp_lld_drawline_VMT = GDISP_VMT_NAME1(gdisp_lld_drawline_);
+ #if GDISP_NEED_CIRCLE
+ gdisp_lld_drawcircle_VMT = GDISP_VMT_NAME1(gdisp_lld_drawcircle_);
+ gdisp_lld_fillcircle_VMT = GDISP_VMT_NAME1(gdisp_lld_fillcircle_);
+ #endif
+ #if GDISP_NEED_ELLIPSE
+ gdisp_lld_drawellipse_VMT = GDISP_VMT_NAME1(gdisp_lld_drawellipse_);
+ gdisp_lld_fillellipse_VMT = GDISP_VMT_NAME1(gdisp_lld_fillellipse_);
+ #endif
+ #if GDISP_NEED_ARC
+ gdisp_lld_drawarc_VMT = GDISP_VMT_NAME1(gdisp_lld_drawarc_);
+ gdisp_lld_fillarc_VMT = GDISP_VMT_NAME1(gdisp_lld_fillarc_);
+ #endif
+ #if GDISP_NEED_TEXT
+ gdisp_lld_drawchar_VMT = GDISP_VMT_NAME1(gdisp_lld_drawchar_);
+ gdisp_lld_fillchar_VMT = GDISP_VMT_NAME1(gdisp_lld_fillchar_);
+ #endif
+ #if GDISP_NEED_PIXELREAD
+ gdisp_lld_getpixelcolor_VMT = GDISP_VMT_NAME1(gdisp_lld_pixelread_);
+ #endif
+ #if GDISP_NEED_SCROLL
+ gdisp_lld_verticalscroll_VMT = GDISP_VMT_NAME1(gdisp_lld_scroll_);
+ #endif
+ #if GDISP_NEED_CONTROL
+ gdisp_lld_control_VMT = GDISP_VMT_NAME1(gdisp_lld_control_);
+ #endif
+ #if GDISP_NEED_CLIP
+ gdisp_lld_setclip_VMT = GDISP_VMT_NAME1(gdisp_lld_setclip_);
+ #endif
+
+ return TRUE;
+ }
+
+ if (GDISP_VMT_NAME2(gdisp_lld_init_)()) {
+ gdisp_lld_query_VMT = GDISP_VMT_NAME2(gdisp_lld_query_);
+ gdisp_lld_clear_VMT = GDISP_VMT_NAME2(gdisp_lld_clear_);
+ gdisp_lld_drawpixel_VMT = GDISP_VMT_NAME2(gdisp_lld_drawpixel_);
+ gdisp_lld_fillarea_VMT = GDISP_VMT_NAME2(gdisp_lld_fillarea_);
+ gdisp_lld_blitareaex_VMT = GDISP_VMT_NAME2(gdisp_lld_blitareaex_);
+ gdisp_lld_drawline_VMT = GDISP_VMT_NAME2(gdisp_lld_drawline_);
+ #if GDISP_NEED_CIRCLE
+ gdisp_lld_drawcircle_VMT = GDISP_VMT_NAME2(gdisp_lld_drawcircle_);
+ gdisp_lld_fillcircle_VMT = GDISP_VMT_NAME2(gdisp_lld_fillcircle_);
+ #endif
+ #if GDISP_NEED_ELLIPSE
+ gdisp_lld_drawellipse_VMT = GDISP_VMT_NAME2(gdisp_lld_drawellipse_);
+ gdisp_lld_fillellipse_VMT = GDISP_VMT_NAME2(gdisp_lld_fillellipse_);
+ #endif
+ #if GDISP_NEED_ARC
+ gdisp_lld_drawarc_VMT = GDISP_VMT_NAME2(gdisp_lld_drawarc_);
+ gdisp_lld_fillarc_VMT = GDISP_VMT_NAME2(gdisp_lld_fillarc_);
+ #endif
+ #if GDISP_NEED_TEXT
+ gdisp_lld_drawchar_VMT = GDISP_VMT_NAME2(gdisp_lld_drawchar_);
+ gdisp_lld_fillchar_VMT = GDISP_VMT_NAME2(gdisp_lld_fillchar_);
+ #endif
+ #if GDISP_NEED_PIXELREAD
+ gdisp_lld_getpixelcolor_VMT = GDISP_VMT_NAME2(gdisp_lld_pixelread_);
+ #endif
+ #if GDISP_NEED_SCROLL
+ gdisp_lld_verticalscroll_VMT = GDISP_VMT_NAME2(gdisp_lld_scroll_);
+ #endif
+ #if GDISP_NEED_CONTROL
+ gdisp_lld_control_VMT = GDISP_VMT_NAME2(gdisp_lld_control_);
+ #endif
+ #if GDISP_NEED_CLIP
+ gdisp_lld_setclip_VMT = GDISP_VMT_NAME2(gdisp_lld_setclip_);
+ #endif
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/VMT/gdisp_lld.mk b/drivers/gdisp/VMT/gdisp_lld.mk
new file mode 100644
index 00000000..96918f8a
--- /dev/null
+++ b/drivers/gdisp/VMT/gdisp_lld.mk
@@ -0,0 +1,7 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/VMT/gdisp_lld.c \
+ $(GFXLIB)/drivers/gdisp/VMT/gdisp_lld_driver1.c \
+ $(GFXLIB)//drivers/gdisp/VMT/gdisp_lld_driver2.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/VMT
diff --git a/drivers/gdisp/VMT/gdisp_lld_config.h b/drivers/gdisp/VMT/gdisp_lld_config.h
new file mode 100644
index 00000000..8c7bfc9c
--- /dev/null
+++ b/drivers/gdisp/VMT/gdisp_lld_config.h
@@ -0,0 +1,71 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/VMT/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header template.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "VMT"
+#define GDISP_LLD(x) gdisp_lld_##x##_VMT
+#define GDISP_LLD_VMT(x) (*GDISP_LLD(x))
+
+#define GDISP_HARDWARE_LINES TRUE
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_CIRCLES TRUE
+#define GDISP_HARDWARE_CIRCLEFILLS TRUE
+#define GDISP_HARDWARE_ELLIPSES TRUE
+#define GDISP_HARDWARE_ELLIPSEFILLS TRUE
+#define GDISP_HARDWARE_ARCS TRUE
+#define GDISP_HARDWARE_ARCFILLS TRUE
+#define GDISP_HARDWARE_TEXT TRUE
+#define GDISP_HARDWARE_TEXTFILLS TRUE
+#define GDISP_HARDWARE_SCROLL TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+#define GDISP_HARDWARE_QUERY TRUE
+#define GDISP_HARDWARE_CLIP TRUE
+
+#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE
+#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+#define GDISP_PACKED_PIXELS FALSE
+#define GDISP_PACKED_LINES FALSE
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/gdisp/VMT/gdisp_lld_driver1.c b/drivers/gdisp/VMT/gdisp_lld_driver1.c
new file mode 100644
index 00000000..01fd4cf0
--- /dev/null
+++ b/drivers/gdisp/VMT/gdisp_lld_driver1.c
@@ -0,0 +1,52 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/VMT/gdisp_lld_driver1.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for VMT.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#define CONFIGFILE() <../GDISP_VMT_NAME1()/gdisp_lld_config.h>
+#define DRIVERFILE() <../GDISP_VMT_NAME1()/gdisp_lld.c>
+
+/* We don't need these in our VMT referenced driver */
+#undef GDISP_NEED_MSGAPI
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Include the specific config file we want */
+#include CONFIGFILE()
+
+/* Bring in our API */
+#include "gfx.h"
+
+/* Add the low level driver */
+#include DRIVERFILE()
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/VMT/gdisp_lld_driver2.c b/drivers/gdisp/VMT/gdisp_lld_driver2.c
new file mode 100644
index 00000000..ed0e8555
--- /dev/null
+++ b/drivers/gdisp/VMT/gdisp_lld_driver2.c
@@ -0,0 +1,52 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/gdisp/VMT/gdisp_lld_driver2.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for VMT.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#define CONFIGFILE() <../GDISP_VMT_NAME2()/gdisp_lld_config.h>
+#define DRIVERFILE() <../GDISP_VMT_NAME2()/gdisp_lld.c>
+
+/* We don't need these in our VMT referenced driver */
+#undef GDISP_NEED_MSGAPI
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Include the specific config file we want */
+#include CONFIGFILE()
+
+/* Bring in our API */
+#include "gfx.h"
+
+/* Add the low level driver */
+#include DRIVERFILE()
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/VMT/readme.txt b/drivers/gdisp/VMT/readme.txt
new file mode 100644
index 00000000..d6b71e0e
--- /dev/null
+++ b/drivers/gdisp/VMT/readme.txt
@@ -0,0 +1,23 @@
+This driver enables you to have two underlying drivers handling different hardware.
+A choice is made at run-time of which driver to call based on which driver succeeds
+to initialise first (init returns TRUE).
+
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+ c) Define these:
+ #define GDISP_VMT_NAME1(x) x##YourDriver1
+ #define GDISP_VMT_NAME2(x) x##YourDriver2
+ Note YourDriver1 & 2 are the basenames of the directories containing the driver.
+ Note that both drivers must be the same pixel format which is
+ GDISP_PIXELFORMAT_RGB565 by default. Alter gdispVMT/gdisp_lld_config.h if your
+ pixel format is different on both drivers.
+ d) Any driver specific defines. If both drivers use the same defines then they must
+ accept the same values for the define.
+
+2. To your makefile add the following lines:
+ include $(CHIBIOS)/os/halext/halext.mk
+ include $(CHIBIOS)/os/halext/drivers/gdispVMT/gdisp_lld.mk
+
diff --git a/drivers/ginput/toggle/Pal/ginput_lld.mk b/drivers/ginput/toggle/Pal/ginput_lld.mk
new file mode 100644
index 00000000..d398da9d
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld_toggle.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/ginput/toggle/Pal
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle.c b/drivers/ginput/toggle/Pal/ginput_lld_toggle.c
new file mode 100644
index 00000000..e2ecc116
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle.c
@@ -0,0 +1,63 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/toggle/Pal/ginput_lld_toggle.c
+ * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) /*|| defined(__DOXYGEN__)*/
+
+#include "ginput/lld/toggle.h"
+
+GINPUT_TOGGLE_DECLARE_STRUCTURE();
+
+/**
+ * @brief Initialise the port.
+ *
+ * @param[in] ptc A pointer to one of the entries in GInputToggleConfigTable
+ *
+ * @notapi
+ */
+void ginput_lld_toggle_init(const GToggleConfig *ptc) {
+ palSetGroupMode(((IOBus *)ptc->id)->portid, ptc->mask, 0, ptc->mode);
+}
+
+/**
+ * @brief Get the bits from the port.
+ *
+ * @param[in] ptc A pointer to one of the entries in GInputToggleConfigTable
+ *
+ * @notapi
+ */
+unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) {
+ return palReadBus((IOBus *)ptc->id);
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */
+/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
new file mode 100644
index 00000000..20fc44b5
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
@@ -0,0 +1,61 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
+ * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the example board.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GDISP_LLD_TOGGLE_BOARD_H
+#define _GDISP_LLD_TOGGLE_BOARD_H
+
+#error "GINPUT Toggle Pal Driver: You need to define your board definitions"
+
+// The below are example values
+
+#define GINPUT_TOGGLE_NUM_PORTS 7 // The total number of toggle inputs
+#define GINPUT_TOGGLE_CONFIG_ENTRIES 2 // The total number of GToggleConfig entries
+
+#define GINPUT_TOGGLE_SW1 0 // Switch 1
+#define GINPUT_TOGGLE_SW2 1 // Switch 2
+#define GINPUT_TOGGLE_UP 2 // Joystick Up
+#define GINPUT_TOGGLE_DOWN 3 // Joystick Down
+#define GINPUT_TOGGLE_LEFT 4 // Joystick Left
+#define GINPUT_TOGGLE_RIGHT 5 // Joystick Right
+#define GINPUT_TOGGLE_CENTER 6 // Joystick Center
+
+#define GINPUT_TOGGLE_DECLARE_STRUCTURE() \
+ const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = { \
+ {AT91C_BASE_PIOB, /* Switch 1 and Switch 2 */ \
+ PIOB_SW1_MASK|PIOB_SW2_MASK, \
+ PIOB_SW1_MASK|PIOB_SW2_MASK, \
+ PAL_MODE_INPUT}, \
+ {AT91C_BASE_PIOA, /* B1..4 Joystick */ \
+ PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, \
+ PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, \
+ PAL_MODE_INPUT}, \
+ }
+
+#endif /* _GDISP_LLD_TOGGLE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
new file mode 100644
index 00000000..4f3d6800
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
@@ -0,0 +1,57 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
+ * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the Olimex SAM7EX256 board.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GDISP_LLD_TOGGLE_BOARD_H
+#define _GDISP_LLD_TOGGLE_BOARD_H
+
+#define GINPUT_TOGGLE_NUM_PORTS 7 // The total number of toggle inputs
+#define GINPUT_TOGGLE_CONFIG_ENTRIES 2 // The total number of GToggleConfig entries
+
+#define GINPUT_TOGGLE_SW1 0 // Switch 1
+#define GINPUT_TOGGLE_SW2 1 // Switch 2
+#define GINPUT_TOGGLE_UP 2 // Joystick Up
+#define GINPUT_TOGGLE_DOWN 3 // Joystick Down
+#define GINPUT_TOGGLE_LEFT 4 // Joystick Left
+#define GINPUT_TOGGLE_RIGHT 5 // Joystick Right
+#define GINPUT_TOGGLE_CENTER 6 // Joystick Center
+
+#define GINPUT_TOGGLE_DECLARE_STRUCTURE() \
+ const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = { \
+ {AT91C_BASE_PIOB, /* Switch 1 and Switch 2 */ \
+ PIOB_SW1_MASK|PIOB_SW2_MASK, \
+ PIOB_SW1_MASK|PIOB_SW2_MASK, \
+ PAL_MODE_INPUT}, \
+ {AT91C_BASE_PIOA, /* B1..4 Joystick */ \
+ PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, \
+ PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, \
+ PAL_MODE_INPUT}, \
+ }
+
+#endif /* _GDISP_LLD_TOGGLE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
new file mode 100644
index 00000000..162d35df
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
@@ -0,0 +1,48 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
+ * @brief GINPUT Toggle Driver configuration header.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H
+#define _GINPUT_LLD_TOGGLE_CONFIG_H
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+
+#if GINPUT_TOGGLE_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "ginput_lld_toggle_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+ #include "ginput_lld_toggle_board_olimexsam7ex256.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "ginput_lld_toggle_board.h"
+#endif
+
+#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
+
+#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */
+/** @} */
diff --git a/drivers/ginput/toggle/Pal/readme.txt b/drivers/ginput/toggle/Pal/readme.txt
new file mode 100644
index 00000000..e6976f7d
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/readme.txt
@@ -0,0 +1,13 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GINPUT TRUE
+ #define GINPUT_NEED_TOGGLE TRUE
+ d) If you are not using a known board then create a ginput_lld_toggle_board.h file
+ and ensure it is on your include path.
+ Use the ginput_lld_toggle_board_example.h file as a basis.
+ Currently known boards are:
+ Olimex SAM7-EX256
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/ginput/togglePal/ginput_lld.mk
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld.mk b/drivers/ginput/touch/ADS7843/ginput_lld.mk
new file mode 100644
index 00000000..b6ac0ea6
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/ginput/touch/ADS7843
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c b/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
new file mode 100644
index 00000000..65065176
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
@@ -0,0 +1,144 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
+ * @brief GINPUT Touch low level driver source for the ADS7843.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
+
+#include "ginput/lld/mouse.h"
+
+#if defined(GINPUT_MOUSE_USE_CUSTOM_BOARD) && GINPUT_MOUSE_USE_CUSTOM_BOARD
+ #include "ginput_lld_mouse_board.h"
+#elif defined(BOARD_FIREBULL_STM32_F103)
+ #include "ginput_lld_mouse_board_firebull_stm32f103.h"
+#elif defined(BOARD_OLIMEX_STM32_E407)
+ #include "ginput_lld_mouse_board_olimex_stm32_e407.h"
+#else
+ #include "ginput_lld_mouse_board_example.h"
+#endif
+
+static uint16_t sampleBuf[7];
+static coord_t lastx, lasty;
+
+/**
+ * @brief 7-point median filtering code for touch samples
+ *
+ * @note This is an internally used routine only.
+ *
+ * @notapi
+ */
+static void filter(void) {
+ uint16_t temp;
+ int i,j;
+
+ for(i = 0; i < 4; i++) {
+ for(j = i; j < 7; j++) {
+ if(sampleBuf[i] > sampleBuf[j]) {
+ /* Swap the values */
+ temp = sampleBuf[i];
+ sampleBuf[i] = sampleBuf[j];
+ sampleBuf[j] = temp;
+ }
+ }
+ }
+}
+
+/**
+ * @brief Initialise the mouse/touch.
+ *
+ * @notapi
+ */
+void ginput_lld_mouse_init(void) {
+ init_board();
+}
+
+/**
+ * @brief Read the mouse/touch position.
+ *
+ * @param[in] pt A pointer to the structure to fill
+ *
+ * @note For drivers that don't support returning a position
+ * when the touch is up (most touch devices), it should
+ * return the previous position with the new Z value.
+ * The z value is the pressure for those touch devices
+ * that support it (-100 to 100 where > 0 is touched)
+ * or, 0 or 100 for those drivers that don't.
+ *
+ * @notapi
+ */
+void ginput_lld_mouse_get_reading(MouseReading *pt) {
+ uint16_t i;
+
+ // If touch-off return the previous results
+ if (!getpin_pressed()) {
+ pt->x = lastx;
+ pt->y = lasty;
+ pt->z = 0;
+ pt->buttons = 0;
+ return;
+ }
+
+ // Read the port to get the touch settings
+ aquire_bus();
+
+ /* Get the X value
+ * Discard the first conversion - very noisy and keep the ADC on hereafter
+ * till we are done with the sampling. Note that PENIRQ is disabled while reading.
+ * Finally switch on PENIRQ once again - perform a dummy read.
+ * Once we have the readings, find the medium using our filter function
+ */
+ read_value(0xD1);
+ for(i = 0; i < 7; i++)
+ sampleBuf[i] = read_value(0xD1);
+ read_value(0xD0);
+ filter();
+ lastx = (coord_t)sampleBuf[3];
+
+ /* Get the Y value using the same process as above */
+ read_value(0x91);
+ for(i = 0; i < 7; i++)
+ sampleBuf[i] = read_value(0x91);
+ read_value(0x90);
+ filter();
+ lasty = (coord_t)sampleBuf[3];
+
+ // Release the bus
+ release_bus();
+
+ // Return the results
+ pt->x = lastx;
+ pt->y = lasty;
+ pt->z = 100;
+ pt->buttons = GINPUT_TOUCH_PRESSED;
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
+/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h
new file mode 100644
index 00000000..9f4f2dc1
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h
@@ -0,0 +1,88 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h
+ * @brief GINPUT Touch low level driver source for the ADS7843 on the example board.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+/**
+ * @brief Initialise the board for the touch.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+ #error "ginputADS7843: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Check whether the surface is currently touched
+ * @return TRUE if the surface is currently touched
+ *
+ * @notapi
+ */
+static __inline bool_t getpin_pressed(void) {
+ /* Code here */
+ #error "ginputADS7843: You must supply a definition for getpin_pressed for your board"
+}
+
+/**
+ * @brief Aquire the bus ready for readings
+ *
+ * @notapi
+ */
+static __inline void aquire_bus(void) {
+ /* Code here */
+ #error "ginputADS7843: You must supply a definition for aquire_bus for your board"
+}
+
+/**
+ * @brief Release the bus after readings
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Code here */
+ #error "ginputADS7843: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Read a value from touch controller
+ * @return The value read from the controller
+ *
+ * params[in] port The controller port to read.
+ *
+ * @notapi
+ */
+static __inline uint16_t read_value(uint16_t port) {
+ /* Code here */
+ #error "ginputADS7843: You must supply a definition for read_value for your board"
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
new file mode 100644
index 00000000..bc018b89
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
@@ -0,0 +1,103 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
+ * @brief GINPUT ouch low level driver source for the ADS7843 on the FireBull STM32F103-FB board.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+static const SPIConfig spicfg = {
+ NULL,
+ GPIOC,
+ 6,
+ /* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
+};
+
+/**
+ * @brief Initialise the board for the touch.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ spiStart(&SPID1, &spicfg);
+}
+
+/**
+ * @brief Check whether the surface is currently touched
+ * @return TRUE if the surface is currently touched
+ *
+ * @notapi
+ */
+static __inline bool_t getpin_pressed(void) {
+ return (!palReadPad(GPIOC, 4));
+}
+/**
+ * @brief Aquire the bus ready for readings
+ *
+ * @notapi
+ */
+static __inline void aquire_bus(void) {
+ spiAcquireBus(&SPID1);
+ //TOUCHSCREEN_SPI_PROLOGUE();
+ palClearPad(GPIOC, 6);
+}
+
+/**
+ * @brief Release the bus after readings
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ palSetPad(GPIOC, 6);
+ spiReleaseBus(&SPID1);
+ //TOUCHSCREEN_SPI_EPILOGUE();
+}
+
+/**
+ * @brief Read a value from touch controller
+ * @return The value read from the controller
+ *
+ * params[in] port The controller port to read.
+ *
+ * @notapi
+ */
+static __inline uint16_t read_value(uint16_t port) {
+ static uint8_t txbuf[3] = {0};
+ static uint8_t rxbuf[3] = {0};
+ uint16_t ret;
+
+ txbuf[0] = port;
+
+ spiExchange(&SPID1, 3, txbuf, rxbuf);
+
+ ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
+
+ return ret;
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
new file mode 100644
index 00000000..6c5f7e37
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
@@ -0,0 +1,103 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
+ * @brief GINPUT Touch low level driver source for the ADS7843 on an Olimex STM32E407.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+static const SPIConfig spicfg = {
+ NULL,
+ GPIOG,
+ 10,
+ /* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
+};
+
+/**
+ * @brief Initialise the board for the touch.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ spiStart(&SPID2, &spicfg);
+}
+
+/**
+ * @brief Check whether the surface is currently touched
+ * @return TRUE if the surface is currently touched
+ *
+ * @notapi
+ */
+static __inline bool_t getpin_pressed(void) {
+ return (!palReadPad(GPIOG, 0));
+}
+/**
+ * @brief Aquire the bus ready for readings
+ *
+ * @notapi
+ */
+static __inline void aquire_bus(void) {
+ spiAcquireBus(&SPID2);
+ //TOUCHSCREEN_SPI_PROLOGUE();
+ palClearPad(GPIOG, 10);
+}
+
+/**
+ * @brief Release the bus after readings
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ palSetPad(GPIOG, 10);
+ spiReleaseBus(&SPID2);
+ //TOUCHSCREEN_SPI_EPILOGUE();
+}
+
+/**
+ * @brief Read a value from touch controller
+ * @return The value read from the controller
+ *
+ * params[in] port The controller port to read.
+ *
+ * @notapi
+ */
+static __inline uint16_t read_value(uint16_t port) {
+ static uint8_t txbuf[3] = {0};
+ static uint8_t rxbuf[3] = {0};
+ uint16_t ret;
+
+ txbuf[0] = port;
+
+ spiExchange(&SPID2, 3, txbuf, rxbuf);
+
+ ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
+
+ return ret;
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h
new file mode 100644
index 00000000..30a13841
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h
@@ -0,0 +1,44 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h
+ * @brief GINPUT LLD header file for mouse/touch driver.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _LLD_GINPUT_MOUSE_CONFIG_H
+#define _LLD_GINPUT_MOUSE_CONFIG_H
+
+#define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH
+#define GINPUT_MOUSE_NEED_CALIBRATION TRUE
+#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 5
+#define GINPUT_MOUSE_READ_CYCLES 4
+#define GINPUT_MOUSE_POLL_PERIOD 25
+#define GINPUT_MOUSE_MAX_CLICK_JITTER 10
+#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
+#define GINPUT_MOUSE_CLICK_TIME 500
+
+#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
+/** @} */
diff --git a/drivers/ginput/touch/ADS7843/readme.txt b/drivers/ginput/touch/ADS7843/readme.txt
new file mode 100644
index 00000000..852a1ea0
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/readme.txt
@@ -0,0 +1,9 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GINPUT TRUE
+ b) #define GINPUT_NEED_MOUSE TRUE
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/ginput/touch/ADS7843/ginput_lld.mk
+
diff --git a/drivers/ginput/touch/MCU/ginput_lld.mk b/drivers/ginput/touch/MCU/ginput_lld.mk
new file mode 100644
index 00000000..eb8fb2d8
--- /dev/null
+++ b/drivers/ginput/touch/MCU/ginput_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld_mouse.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/ginput/touch/MCU
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse.c b/drivers/ginput/touch/MCU/ginput_lld_mouse.c
new file mode 100644
index 00000000..b43a14e7
--- /dev/null
+++ b/drivers/ginput/touch/MCU/ginput_lld_mouse.c
@@ -0,0 +1,140 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/MCU/ginput_lld_mouse.c
+ * @brief GINPUT Touch low level driver source for the MCU.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
+
+#include "ginput/lld/mouse.h"
+
+#if defined(GINPUT_MOUSE_USE_CUSTOM_BOARD) && GINPUT_MOUSE_USE_CUSTOM_BOARD
+ #include "ginput_lld_mouse_board.h"
+#elif defined(BOARD_OLIMEX_STM32_LCD)
+ #include "ginput_lld_mouse_board_olimex_stm32_lcd.h"
+#else
+ #include "ginput_lld_mouse_board.h"
+#endif
+
+static uint16_t sampleBuf[7];
+static coord_t lastx, lasty;
+
+/**
+ * @brief 7-point median filtering code for touchscreen samples
+ *
+ * @note This is an internally used routine only.
+ *
+ * @notapi
+ */
+static void filter(void) {
+ uint16_t temp;
+ int i,j;
+
+ for(i = 0; i < 4; i++) {
+ for(j = i; j < 7; j++) {
+ if(sampleBuf[i] > sampleBuf[j]) {
+ /* Swap the values */
+ temp = sampleBuf[i];
+ sampleBuf[i] = sampleBuf[j];
+ sampleBuf[j] = temp;
+ }
+ }
+ }
+}
+
+/**
+ * @brief Initialise the mouse/touch.
+ *
+ * @notapi
+ */
+void ginput_lld_mouse_init(void) {
+ init_board();
+}
+
+/**
+ * @brief Read the mouse/touch position.
+ *
+ * @param[in] pt A pointer to the structure to fill
+ *
+ * @note For drivers that don't support returning a position
+ * when the touch is up (most touch devices), it should
+ * return the previous position with the new Z value.
+ * The z value is the pressure for those touch devices
+ * that support it (-100 to 100 where > 0 is touched)
+ * or, 0 or 100 for those drivers that don't.
+ *
+ * @notapi
+ */
+void ginput_lld_mouse_get_reading(MouseReading *pt) {
+ uint16_t i;
+
+ // If touch-off return the previous results
+ if (!getpin_pressed()) {
+ pt->x = lastx;
+ pt->y = lasty;
+ pt->z = 0;
+ pt->buttons = 0;
+ return;
+ }
+
+ // Read the port to get the touch settings
+ aquire_bus();
+
+ /* Get the X value
+ * Discard the first conversion - very noisy and keep the ADC on hereafter
+ * till we are done with the sampling.
+ * Once we have the readings, find the medium using our filter function
+ */
+ read_x_value();
+ for(i = 0; i < 7; i++)
+ sampleBuf[i] = read_x_value();
+ filter();
+ lastx = (coord_t)sampleBuf[3];
+
+ /* Get the Y value using the same process as above */
+ read_y_value();
+ for(i = 0; i < 7; i++)
+ sampleBuf[i] = read_y_value();
+ filter();
+ lasty = (coord_t)sampleBuf[3];
+
+ // Release the bus
+ release_bus();
+
+ // Return the results
+ pt->x = lastx;
+ pt->y = lasty;
+ pt->z = 100;
+ pt->buttons = GINPUT_TOUCH_PRESSED;
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
+/** @} */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h
new file mode 100644
index 00000000..913d50c9
--- /dev/null
+++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h
@@ -0,0 +1,98 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h
+ * @brief GINPUT Touch low level driver source for the MCU on the example board.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+/**
+ * @brief Initialise the board for the touch.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for init_board for your board"
+}
+
+/**
+ * @brief Check whether the surface is currently touched
+ * @return TRUE if the surface is currently touched
+ *
+ * @notapi
+ */
+static __inline bool_t getpin_pressed(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for getpin_pressed for your board"
+}
+
+/**
+ * @brief Aquire the bus ready for readings
+ *
+ * @notapi
+ */
+static __inline void aquire_bus(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for aquire_bus for your board"
+}
+
+/**
+ * @brief Release the bus after readings
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for release_bus for your board"
+}
+
+/**
+ * @brief Read an x value from touch controller
+ * @return The value read from the controller
+ *
+ * @notapi
+ */
+static __inline uint16_t read_x_value(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for read_x_value for your board"
+}
+
+/**
+ * @brief Read an y value from touch controller
+ * @return The value read from the controller
+ *
+ * @notapi
+ */
+static __inline uint16_t read_y_value(void) {
+ /* Code here */
+ #error "ginputMCU: You must supply a definition for read_y_value for your board"
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
new file mode 100644
index 00000000..510e8e81
--- /dev/null
+++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
@@ -0,0 +1,165 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
+ * @brief GINPUT Touch low level driver source for the MCU on the example board.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+#define ADC_NUM_CHANNELS 2
+#define ADC_BUF_DEPTH 1
+
+static const ADCConversionGroup adc_y_config = {
+ FALSE,
+ ADC_NUM_CHANNELS,
+ NULL,
+ NULL,
+ 0, 0,
+ 0, 0,
+ ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
+ 0,
+ ADC_SQR3_SQ2_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN13)
+};
+
+static const ADCConversionGroup adc_x_config = {
+ FALSE,
+ ADC_NUM_CHANNELS,
+ NULL,
+ NULL,
+ 0, 0,
+ 0, 0,
+ ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
+ 0,
+ ADC_SQR3_SQ2_N(ADC_CHANNEL_IN10) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN11)
+};
+
+/**
+ * @brief Initialise the board for the touch.
+ *
+ * @notapi
+ */
+static __inline void init_board(void) {
+ adcStart(&ADCD1, NULL);
+}
+
+/**
+ * @brief Check whether the surface is currently touched
+ * @return TRUE if the surface is currently touched
+ *
+ * @notapi
+ */
+static __inline bool_t getpin_pressed(void) {
+ palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOC, 1, PAL_MODE_INPUT);
+ palSetPadMode(GPIOC, 2, PAL_MODE_INPUT);
+ palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPad(GPIOC, 3);
+
+ return palReadPad(GPIOC, 0);
+}
+
+/**
+ * @brief Aquire the bus ready for readings
+ *
+ * @notapi
+ */
+static __inline void aquire_bus(void) {
+
+}
+
+/**
+ * @brief Release the bus after readings
+ *
+ * @notapi
+ */
+static __inline void release_bus(void) {
+
+}
+
+/**
+ * @brief Read an x value from touch controller
+ * @return The value read from the controller
+ *
+ * @notapi
+ */
+static __inline uint16_t read_x_value(void) {
+ uint16_t val1, val2;
+ adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
+
+ palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
+ palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG);
+ palSetPadMode(GPIOC, 2, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
+
+ palSetPad(GPIOC, 2);
+ palClearPad(GPIOC, 3);
+ chThdSleepMilliseconds(1);
+ adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
+ val1 = ((samples[0] + samples[1])/2);
+
+ palClearPad(GPIOC, 2);
+ palSetPad(GPIOC, 3);
+ chThdSleepMilliseconds(1);
+ adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
+ val2 = ((samples[0] + samples[1])/2);
+
+ return ((val1+((1<<12)-val2))/4);
+}
+
+/**
+ * @brief Read an y value from touch controller
+ * @return The value read from the controller
+ *
+ * @notapi
+ */
+static __inline uint16_t read_y_value(void) {
+ uint16_t val1, val2;
+ adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
+
+ palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG);
+ palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
+ palSetPadMode(GPIOC, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 1, PAL_MODE_OUTPUT_PUSHPULL);
+
+ palSetPad(GPIOC, 1);
+ palClearPad(GPIOC, 0);
+ chThdSleepMilliseconds(1);
+ adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
+ val1 = ((samples[0] + samples[1])/2);
+
+ palClearPad(GPIOC, 1);
+ palSetPad(GPIOC, 0);
+ chThdSleepMilliseconds(1);
+ adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
+ val2 = ((samples[0] + samples[1])/2);
+
+ return ((val1+((1<<12)-val2))/4);
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h
new file mode 100644
index 00000000..1b5c7b6b
--- /dev/null
+++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h
@@ -0,0 +1,44 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file drivers/ginput/touch/MCU/ginput_lld_mouse_config.h
+ * @brief GINPUT LLD header file for touch driver.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _LLD_GINPUT_MOUSE_CONFIG_H
+#define _LLD_GINPUT_MOUSE_CONFIG_H
+
+#define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH
+#define GINPUT_MOUSE_NEED_CALIBRATION TRUE
+#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 12
+#define GINPUT_MOUSE_READ_CYCLES 4
+#define GINPUT_MOUSE_POLL_PERIOD 25
+#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
+#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
+#define GINPUT_MOUSE_CLICK_TIME 500
+
+#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
+/** @} */
diff --git a/drivers/ginput/touch/MCU/readme.txt b/drivers/ginput/touch/MCU/readme.txt
new file mode 100644
index 00000000..4dbe5543
--- /dev/null
+++ b/drivers/ginput/touch/MCU/readme.txt
@@ -0,0 +1,9 @@
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GINPUT TRUE
+ b) #define GINPUT_NEED_MOUSE TRUE
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
+
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
new file mode 100644
index 00000000..8a46abc9
--- /dev/null
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -0,0 +1,1026 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/multiple/Win32/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for Win32.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 640
+#endif
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 480
+#endif
+
+#if GINPUT_NEED_TOGGLE
+ /* Include toggle support code */
+ #include "ginput/lld/toggle.h"
+
+ const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
+ {0, 0xFF, 0x00, PAL_MODE_INPUT},
+ };
+#endif
+
+#if GINPUT_NEED_MOUSE
+ /* Include mouse support code */
+ #include "ginput/lld/mouse.h"
+#endif
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local routines . */
+/*===========================================================================*/
+
+#define WIN32_USE_MSG_REDRAW FALSE
+#if GINPUT_NEED_TOGGLE
+ #define WIN32_BUTTON_AREA 16
+#else
+ #define WIN32_BUTTON_AREA 0
+#endif
+
+#define APP_NAME "GDISP"
+
+#define COLOR2BGR(c) ((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF))
+#define BGR2COLOR(c) COLOR2BGR(c)
+
+static HWND winRootWindow = NULL;
+static HDC dcBuffer = NULL;
+static HBITMAP dcBitmap = NULL;
+static HBITMAP dcOldBitmap;
+static volatile bool_t isReady = FALSE;
+static coord_t wWidth, wHeight;
+
+#if GINPUT_NEED_MOUSE
+ static coord_t mousex, mousey;
+ static uint16_t mousebuttons;
+#endif
+#if GINPUT_NEED_TOGGLE
+ static uint8_t toggles = 0;
+#endif
+
+static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC dc;
+ PAINTSTRUCT ps;
+ #if GINPUT_NEED_TOGGLE
+ HBRUSH hbrOn, hbrOff;
+ HPEN pen;
+ RECT rect;
+ HGDIOBJ old;
+ POINT p;
+ coord_t pos;
+ uint8_t bit;
+ #endif
+
+ switch (Msg) {
+ case WM_CREATE:
+ break;
+ case WM_LBUTTONDOWN:
+ #if GINPUT_NEED_MOUSE
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
+ goto mousemove;
+ }
+ #endif
+ #if GINPUT_NEED_TOGGLE
+ bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth);
+ toggles ^= bit;
+ rect.left = 0;
+ rect.right = wWidth;
+ rect.top = wHeight;
+ rect.bottom = wHeight + WIN32_BUTTON_AREA;
+ InvalidateRect(hWnd, &rect, FALSE);
+ UpdateWindow(hWnd);
+ #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+ ginputToggleWakeup();
+ #endif
+ #endif
+ break;
+ case WM_LBUTTONUP:
+ #if GINPUT_NEED_TOGGLE
+ if ((toggles & 0xF0)) {
+ toggles &= 0x0F;
+ rect.left = 0;
+ rect.right = wWidth;
+ rect.top = wHeight;
+ rect.bottom = wHeight + WIN32_BUTTON_AREA;
+ InvalidateRect(hWnd, &rect, FALSE);
+ UpdateWindow(hWnd);
+ #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+ ginputToggleWakeup();
+ #endif
+ }
+ #endif
+ #if GINPUT_NEED_MOUSE
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
+ goto mousemove;
+ }
+ #endif
+ break;
+#if GINPUT_NEED_MOUSE
+ case WM_MBUTTONDOWN:
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
+ goto mousemove;
+ }
+ break;
+ case WM_MBUTTONUP:
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
+ goto mousemove;
+ }
+ break;
+ case WM_RBUTTONDOWN:
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
+ goto mousemove;
+ }
+ break;
+ case WM_RBUTTONUP:
+ if ((coord_t)HIWORD(lParam) < wHeight) {
+ mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
+ goto mousemove;
+ }
+ break;
+ case WM_MOUSEMOVE:
+ if ((coord_t)HIWORD(lParam) >= wHeight)
+ break;
+ mousemove:
+ mousex = (coord_t)LOWORD(lParam);
+ mousey = (coord_t)HIWORD(lParam);
+ #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+ ginputMouseWakeup();
+ #endif
+ break;
+#endif
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ break;
+ case WM_CHAR:
+ case WM_DEADCHAR:
+ case WM_SYSCHAR:
+ case WM_SYSDEADCHAR:
+ break;
+ case WM_PAINT:
+ dc = BeginPaint(hWnd, &ps);
+ BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left,
+ (ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top,
+ dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
+ #if GINPUT_NEED_TOGGLE
+ if (ps.rcPaint.bottom >= wHeight) {
+ pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
+ hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
+ hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
+ old = SelectObject(dc, pen);
+ MoveToEx(dc, 0, wHeight, &p);
+ LineTo(dc, wWidth, wHeight);
+ for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
+ rect.left = pos;
+ rect.right = pos + wWidth/8;
+ rect.top = wHeight;
+ rect.bottom = wHeight + WIN32_BUTTON_AREA;
+ FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff);
+ if (pos > 0) {
+ MoveToEx(dc, rect.left, rect.top, &p);
+ LineTo(dc, rect.left, rect.bottom);
+ }
+ }
+ DeleteObject(hbrOn);
+ DeleteObject(hbrOff);
+ SelectObject(dc, old);
+ }
+ #endif
+ EndPaint(hWnd, &ps);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ SelectObject(dcBuffer, dcOldBitmap);
+ DeleteDC(dcBuffer);
+ DeleteObject(dcBitmap);
+ winRootWindow = NULL;
+ break;
+ default:
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+ }
+ return 0;
+}
+
+static DWORD WINAPI WindowThread(LPVOID lpParameter) {
+ (void)lpParameter;
+
+ MSG msg;
+ HANDLE hInstance;
+ WNDCLASS wc;
+ RECT rect;
+ HDC dc;
+
+ hInstance = GetModuleHandle(NULL);
+
+ wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC)myWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = APP_NAME;
+ RegisterClass(&wc);
+
+ rect.top = 0; rect.bottom = wHeight+WIN32_BUTTON_AREA;
+ rect.left = 0; rect.right = wWidth;
+ AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
+ winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0,
+ rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL);
+ assert(winRootWindow != NULL);
+
+
+ GetClientRect(winRootWindow, &rect);
+ wWidth = rect.right-rect.left;
+ wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
+
+ dc = GetDC(winRootWindow);
+ dcBitmap = CreateCompatibleBitmap(dc, wWidth, wHeight);
+ dcBuffer = CreateCompatibleDC(dc);
+ ReleaseDC(winRootWindow, dc);
+ dcOldBitmap = SelectObject(dcBuffer, dcBitmap);
+
+ ShowWindow(winRootWindow, SW_SHOW);
+ UpdateWindow(winRootWindow);
+ isReady = TRUE;
+
+ while(GetMessage(&msg, NULL, 0, 0) > 0) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ ExitProcess(0);
+ return msg.wParam;
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialisation.
+ * @return TRUE if successful, FALSE on error.
+ *
+ * @notapi
+ */
+bool_t lld_gdisp_init(void) {
+ RECT rect;
+
+ /* Set the window dimensions */
+ GetWindowRect(GetDesktopWindow(), &rect);
+ wWidth = rect.right - rect.left;
+ wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
+ if (wWidth > GDISP_SCREEN_WIDTH)
+ wWidth = GDISP_SCREEN_WIDTH;
+ if (wHeight > GDISP_SCREEN_HEIGHT)
+ wHeight = GDISP_SCREEN_HEIGHT;
+
+ /* Initialise the window */
+ CreateThread(0, 0, WindowThread, 0, 0, 0);
+ while (!isReady)
+ Sleep(1);
+
+ /* Initialise the GDISP structure to match */
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = 100;
+ GDISP.Contrast = 50;
+ GDISP.Width = wWidth;
+ GDISP.Height = wHeight;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void lld_gdisp_draw_pixel(coord_t x, coord_t y, color_t color) {
+ HDC dc;
+ #if WIN32_USE_MSG_REDRAW
+ RECT rect;
+ #endif
+ #if GDISP_NEED_CONTROL
+ coord_t t;
+ #endif
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ break;
+ case GDISP_ROTATE_90:
+ t = GDISP.Height - 1 - y;
+ y = x;
+ x = t;
+ break;
+ case GDISP_ROTATE_180:
+ x = GDISP.Width - 1 - x;
+ y = GDISP.Height - 1 - y;
+ break;
+ case GDISP_ROTATE_270:
+ t = GDISP.Width - 1 - x;
+ x = y;
+ y = t;
+ break;
+ }
+ #endif
+
+ // Draw the pixel in the buffer
+ color = COLOR2BGR(color);
+ SetPixel(dcBuffer, x, y, color);
+
+ #if WIN32_USE_MSG_REDRAW
+ rect.left = x; rect.right = x+1;
+ rect.top = y; rect.bottom = y+1;
+ InvalidateRect(winRootWindow, &rect, FALSE);
+ UpdateWindow(winRootWindow);
+ #else
+ // Draw the pixel again directly on the screen.
+ // This is cheaper than invalidating a single pixel in the window
+ dc = GetDC(winRootWindow);
+ SetPixel(dc, x, y, color);
+ ReleaseDC(winRootWindow, dc);
+ #endif
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a line.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x0, y0 The start of the line
+ * @param[in] x1, y1 The end of the line
+ * @param[in] color The color of the line
+ *
+ * @notapi
+ */
+ void lld_gdisp_draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
+ POINT p;
+ HPEN pen;
+ HDC dc;
+ HGDIOBJ old;
+ #if GDISP_NEED_CLIP
+ HRGN clip;
+ #endif
+ #if WIN32_USE_MSG_REDRAW
+ RECT rect;
+ #endif
+ #if GDISP_NEED_CONTROL
+ coord_t t;
+ #endif
+
+ #if GDISP_NEED_CLIP
+ clip = NULL;
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ #if GDISP_NEED_CLIP
+ // Clip post orientation change
+ if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
+ clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1);
+ #endif
+ break;
+ case GDISP_ROTATE_90:
+ t = GDISP.Height - 1 - y0;
+ y0 = x0;
+ x0 = t;
+ t = GDISP.Height - 1 - y1;
+ y1 = x1;
+ x1 = t;
+ #if GDISP_NEED_CLIP
+ // Clip post orientation change
+ if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
+ clip = CreateRectRgn(GDISP.Height-1-GDISP.clipy1, GDISP.clipx0, GDISP.Height-1-GDISP.clipy0, GDISP.clipx1);
+ #endif
+ break;
+ case GDISP_ROTATE_180:
+ x0 = GDISP.Width - 1 - x0;
+ y0 = GDISP.Height - 1 - y0;
+ x1 = GDISP.Width - 1 - x1;
+ y1 = GDISP.Height - 1 - y1;
+ #if GDISP_NEED_CLIP
+ // Clip post orientation change
+ if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
+ clip = CreateRectRgn(GDISP.Width-1-GDISP.clipx1, GDISP.Height-1-GDISP.clipy1, GDISP.Width-1-GDISP.clipx0, GDISP.Height-1-GDISP.clipy0);
+ #endif
+ break;
+ case GDISP_ROTATE_270:
+ t = GDISP.Width - 1 - x0;
+ x0 = y0;
+ y0 = t;
+ t = GDISP.Width - 1 - x1;
+ x1 = y1;
+ y1 = t;
+ #if GDISP_NEED_CLIP
+ // Clip post orientation change
+ if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
+ clip = CreateRectRgn(GDISP.clipy0, GDISP.Width-1-GDISP.clipx1, GDISP.clipy1, GDISP.Width-1-GDISP.clipx0);
+ #endif
+ break;
+ }
+ #else
+ #if GDISP_NEED_CLIP
+ clip = NULL;
+ if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
+ clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1);
+ #endif
+ #endif
+
+ color = COLOR2BGR(color);
+ pen = CreatePen(PS_SOLID, 1, color);
+ if (pen) {
+ // Draw the line in the buffer
+ #if GDISP_NEED_CLIP
+ if (clip) SelectClipRgn(dcBuffer, clip);
+ #endif
+ old = SelectObject(dcBuffer, pen);
+ MoveToEx(dcBuffer, x0, y0, &p);
+ LineTo(dcBuffer, x1, y1);
+ SelectObject(dcBuffer, old);
+ SetPixel(dcBuffer, x1, y1, color);
+ #if GDISP_NEED_CLIP
+ if (clip) SelectClipRgn(dcBuffer, NULL);
+ #endif
+
+ #if WIN32_USE_MSG_REDRAW
+ rect.left = x0; rect.right = x1+1;
+ rect.top = y0; rect.bottom = y1+1;
+ InvalidateRect(winRootWindow, &rect, FALSE);
+ UpdateWindow(winRootWindow);
+ #else
+ // Redrawing the line on the screen is cheaper than invalidating the whole rectangular area
+ dc = GetDC(winRootWindow);
+ #if GDISP_NEED_CLIP
+ if (clip) SelectClipRgn(dc, clip);
+ #endif
+ old = SelectObject(dc, pen);
+ MoveToEx(dc, x0, y0, &p);
+ LineTo(dc, x1, y1);
+ SelectObject(dc, old);
+ SetPixel(dc, x1, y1, color);
+ #if GDISP_NEED_CLIP
+ if (clip) SelectClipRgn(dc, NULL);
+ #endif
+ ReleaseDC(winRootWindow, dc);
+ #endif
+
+ DeleteObject(pen);
+ }
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ HDC dc;
+ RECT rect;
+ HBRUSH hbr;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ break;
+ case GDISP_ROTATE_90:
+ rect.top = x;
+ rect.bottom = rect.top+cx;
+ rect.right = GDISP.Height - y;
+ rect.left = rect.right-cy;
+ break;
+ case GDISP_ROTATE_180:
+ rect.bottom = GDISP.Height - y;
+ rect.top = rect.bottom-cy;
+ rect.right = GDISP.Width - x;
+ rect.left = rect.right-cx;
+ break;
+ case GDISP_ROTATE_270:
+ rect.bottom = GDISP.Width - x;
+ rect.top = rect.bottom-cx;
+ rect.left = y;
+ rect.right = rect.left+cy;
+ break;
+ }
+ #else
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ #endif
+
+ color = COLOR2BGR(color);
+ hbr = CreateSolidBrush(color);
+
+ if (hbr) {
+ // Fill the area
+ FillRect(dcBuffer, &rect, hbr);
+
+ #if WIN32_USE_MSG_REDRAW
+ InvalidateRect(winRootWindow, &rect, FALSE);
+ UpdateWindow(winRootWindow);
+ #else
+ // Filling the area directly on the screen is likely to be cheaper than invalidating it
+ dc = GetDC(winRootWindow);
+ FillRect(dc, &rect, hbr);
+ ReleaseDC(winRootWindow, dc);
+ #endif
+
+ DeleteObject(hbr);
+ }
+ }
+#endif
+
+#if (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL) || defined(__DOXYGEN__)
+ static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) {
+ pixel_t *dstbuf;
+ pixel_t *dst;
+ const pixel_t *src;
+ size_t sz;
+ coord_t i, j;
+
+ // Shortcut.
+ if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
+ return (pixel_t *)buffer;
+
+ // Allocate the destination buffer
+ sz = (size_t)cx * (size_t)cy;
+ if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
+ return 0;
+
+ // Copy the bits we need
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ for(dst = dstbuf, src = buffer+srcx, j = 0; j < cy; j++)
+ for(i = 0; i < cx; i++, src += srccx - cx)
+ *dst++ = *src++;
+ break;
+ case GDISP_ROTATE_90:
+ for(src = buffer+srcx, j = 0; j < cy; j++) {
+ dst = dstbuf+cy-j-1;
+ for(i = 0; i < cx; i++, src += srccx - cx, dst += cy)
+ *dst = *src++;
+ }
+ break;
+ case GDISP_ROTATE_180:
+ for(dst = dstbuf+sz, src = buffer+srcx, j = 0; j < cy; j++)
+ for(i = 0; i < cx; i++, src += srccx - cx)
+ *--dst = *src++;
+ break;
+ case GDISP_ROTATE_270:
+ for(src = buffer+srcx, j = 0; j < cy; j++) {
+ dst = dstbuf+sz-cy+j;
+ for(i = 0; i < cx; i++, src += srccx - cx, dst -= cy)
+ *dst = *src++;
+ }
+ break;
+ }
+ return dstbuf;
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @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.
+ *
+ * @notapi
+ */
+ void lld_gdisp_blit_area_ex(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) {
+ BITMAPV4HEADER bmpInfo;
+ RECT rect;
+ #if GDISP_NEED_CONTROL
+ pixel_t *srcimg;
+ #endif
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ // Make everything relative to the start of the line
+ buffer += srccx*srcy;
+ srcy = 0;
+
+ memset(&bmpInfo, 0, sizeof(bmpInfo));
+ bmpInfo.bV4Size = sizeof(bmpInfo);
+ bmpInfo.bV4Planes = 1;
+ bmpInfo.bV4BitCount = 32;
+ bmpInfo.bV4AlphaMask = 0;
+ bmpInfo.bV4RedMask = RGB2COLOR(255,0,0);
+ bmpInfo.bV4GreenMask = RGB2COLOR(0,255,0);
+ bmpInfo.bV4BlueMask = RGB2COLOR(0,0,255);
+ bmpInfo.bV4V4Compression = BI_BITFIELDS;
+ bmpInfo.bV4XPelsPerMeter = 3078;
+ bmpInfo.bV4YPelsPerMeter = 3078;
+ bmpInfo.bV4ClrUsed = 0;
+ bmpInfo.bV4ClrImportant = 0;
+ bmpInfo.bV4CSType = 0; //LCS_sRGB;
+
+ #if GDISP_NEED_CONTROL
+ bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t);
+ srcimg = rotateimg(cx, cy, srcx, srccx, buffer);
+ if (!srcimg) return;
+
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ bmpInfo.bV4Width = cx;
+ bmpInfo.bV4Height = -cy; /* top-down image */
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ break;
+ case GDISP_ROTATE_90:
+ bmpInfo.bV4Width = cy;
+ bmpInfo.bV4Height = -cx; /* top-down image */
+ rect.top = x;
+ rect.bottom = rect.top+cx;
+ rect.right = GDISP.Height - y;
+ rect.left = rect.right-cy;
+ break;
+ case GDISP_ROTATE_180:
+ bmpInfo.bV4Width = cx;
+ bmpInfo.bV4Height = -cy; /* top-down image */
+ rect.bottom = GDISP.Height - y;
+ rect.top = rect.bottom-cy;
+ rect.right = GDISP.Width - x;
+ rect.left = rect.right-cx;
+ break;
+ case GDISP_ROTATE_270:
+ bmpInfo.bV4Width = cy;
+ bmpInfo.bV4Height = -cx; /* top-down image */
+ rect.bottom = GDISP.Width - x;
+ rect.top = rect.bottom-cx;
+ rect.left = y;
+ rect.right = rect.left+cy;
+ break;
+ }
+ SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+ if (srcimg != (pixel_t *)buffer)
+ free(srcimg);
+
+ #else
+ bmpInfo.bV4Width = srccx;
+ bmpInfo.bV4Height = -cy; /* top-down image */
+ bmpInfo.bV4SizeImage = (cy*srccx) * sizeof(pixel_t);
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ SetDIBitsToDevice(dcBuffer, x, y, cx, cy, srcx, 0, 0, cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+ #endif
+
+ // Invalidate the region to get it on the screen.
+ InvalidateRect(winRootWindow, &rect, FALSE);
+ UpdateWindow(winRootWindow);
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note Optional.
+ * @note If x,y is off the screen, the result is undefined.
+ * @return The color of the specified pixel.
+ *
+ * @param[in] x, y The start of the text
+ *
+ * @notapi
+ */
+ color_t lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_90:
+ t = GDISP.Height - 1 - y;
+ y = x;
+ x = t;
+ break;
+ case GDISP_ROTATE_180:
+ x = GDISP.Width - 1 - x;
+ y = GDISP.Height - 1 - y;
+ break;
+ case GDISP_ROTATE_270:
+ t = GDISP.Width - 1 - x;
+ x = y;
+ y = t;
+ break;
+ }
+ #endif
+
+ color = GetPixel(dcBuffer, x, y);
+ return BGR2COLOR(color);
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void lld_gdisp_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ RECT rect, frect, srect;
+ HBRUSH hbr;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ if (lines > cy) lines = cy;
+ else if (-lines > cy) lines = -cy;
+
+ bgcolor = COLOR2BGR(bgcolor);
+ hbr = CreateSolidBrush(bgcolor);
+
+ #if GDISP_NEED_CONTROL
+ switch(GDISP.Orientation) {
+ case GDISP_ROTATE_0:
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ lines = -lines;
+ goto vertical_scroll;
+ case GDISP_ROTATE_90:
+ rect.top = x;
+ rect.bottom = rect.top+cx;
+ rect.right = GDISP.Height - y;
+ rect.left = rect.right-cy;
+ goto horizontal_scroll;
+ case GDISP_ROTATE_180:
+ rect.bottom = GDISP.Height - y;
+ rect.top = rect.bottom-cy;
+ rect.right = GDISP.Width - x;
+ rect.left = rect.right-cx;
+ vertical_scroll:
+ srect.left = frect.left = rect.left;
+ srect.right = frect.right = rect.right;
+ if (lines > 0) {
+ srect.top = frect.top = rect.top;
+ frect.bottom = rect.top+lines;
+ srect.bottom = rect.bottom-lines;
+ } else {
+ srect.bottom = frect.bottom = rect.bottom;
+ frect.top = rect.bottom+lines;
+ srect.top = rect.top-lines;
+ }
+ if (cy >= lines && cy >= -lines)
+ ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
+ break;
+ case GDISP_ROTATE_270:
+ rect.bottom = GDISP.Width - x;
+ rect.top = rect.bottom-cx;
+ rect.left = y;
+ rect.right = rect.left+cy;
+ lines = -lines;
+ horizontal_scroll:
+ srect.top = frect.top = rect.top;
+ srect.bottom = frect.bottom = rect.bottom;
+ if (lines > 0) {
+ srect.left = frect.left = rect.left;
+ frect.right = rect.left+lines;
+ srect.right = rect.right-lines;
+ } else {
+ srect.right = frect.right = rect.right;
+ frect.left = rect.right+lines;
+ srect.left = rect.left-lines;
+ }
+ if (cy >= lines && cy >= -lines)
+ ScrollDC(dcBuffer, lines, 0, &srect, 0, 0, 0);
+ break;
+ }
+ #else
+ rect.top = y;
+ rect.bottom = rect.top+cy;
+ rect.left = x;
+ rect.right = rect.left+cx;
+ lines = -lines;
+ srect.left = frect.left = rect.left;
+ srect.right = frect.right = rect.right;
+ if (lines > 0) {
+ srect.top = frect.top = rect.top;
+ frect.bottom = rect.top+lines;
+ srect.bottom = rect.bottom-lines;
+ } else {
+ srect.bottom = frect.bottom = rect.bottom;
+ frect.top = rect.bottom+lines;
+ srect.top = rect.top-lines;
+ }
+ if (cy >= lines && cy >= -lines)
+ ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
+ #endif
+
+ if (hbr)
+ FillRect(dcBuffer, &frect, hbr);
+ InvalidateRect(winRootWindow, &rect, FALSE);
+ UpdateWindow(winRootWindow);
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @detail Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void lld_gdisp_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ GDISP.Width = wWidth;
+ GDISP.Height = wHeight;
+ break;
+ case GDISP_ROTATE_90:
+ GDISP.Height = wWidth;
+ GDISP.Width = wHeight;
+ break;
+ case GDISP_ROTATE_180:
+ GDISP.Width = wWidth;
+ GDISP.Height = wHeight;
+ break;
+ case GDISP_ROTATE_270:
+ GDISP.Height = wWidth;
+ GDISP.Width = wHeight;
+ break;
+ default:
+ return;
+ }
+
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+/*
+ case GDISP_CONTROL_POWER:
+ case GDISP_CONTROL_BACKLIGHT:
+ case GDISP_CONTROL_CONTRAST:
+*/
+ }
+ }
+#endif
+
+#if GINPUT_NEED_MOUSE
+
+ void ginput_lld_mouse_init(void) {}
+
+ void ginput_lld_mouse_get_reading(MouseReading *pt) {
+ pt->x = mousex;
+ pt->y = mousey > wHeight ? wHeight : mousey;
+ pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+ pt->buttons = mousebuttons;
+ }
+
+#endif /* GINPUT_NEED_MOUSE */
+
+#if GINPUT_NEED_TOGGLE
+
+ void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; }
+ unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; }
+
+#endif /* GINPUT_NEED_MOUSE */
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/multiple/Win32/gdisp_lld.mk b/drivers/multiple/Win32/gdisp_lld.mk
new file mode 100644
index 00000000..b116088b
--- /dev/null
+++ b/drivers/multiple/Win32/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/multiple/Win32
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
new file mode 100644
index 00000000..bebd76b9
--- /dev/null
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/multiple/Win32/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for Win32.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "Win32"
+#define GDISP_LLD(x) gdisp_lld_##x##_Win32
+
+#define GDISP_HARDWARE_LINES TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_SCROLL TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
+
diff --git a/drivers/multiple/Win32/ginput_lld_mouse_config.h b/drivers/multiple/Win32/ginput_lld_mouse_config.h
new file mode 100644
index 00000000..ceeedcb9
--- /dev/null
+++ b/drivers/multiple/Win32/ginput_lld_mouse_config.h
@@ -0,0 +1,62 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file drivers/multiple/Win32/ginput_lld_mouse_config.h
+ * @brief GINPUT LLD header file for mouse/touch driver.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _LLD_GINPUT_MOUSE_CONFIG_H
+#define _LLD_GINPUT_MOUSE_CONFIG_H
+
+// This driver supports being both a mouse or a touch device (we don't actually know which it really is)
+// When operating in mouse mode a long left button click does not generate a context click.
+// When operating in touch mode we allow sloppier clicks etc
+#if 1
+ #define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE
+ #define GINPUT_MOUSE_CLICK_TIME TIME_INFINITE // Long click != Context Click
+ #define GINPUT_MOUSE_NEED_CALIBRATION FALSE
+ #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+ #define GINPUT_MOUSE_READ_CYCLES 1
+ #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1
+ #define GINPUT_MOUSE_MAX_CLICK_JITTER 0
+ #define GINPUT_MOUSE_MAX_MOVE_JITTER 0
+#else
+ #define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH
+ #define GINPUT_MOUSE_CLICK_TIME 700 // Long click = Context Click
+ #define GINPUT_MOUSE_NEED_CALIBRATION FALSE // Can be set to TRUE just for testing
+ #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+ #define GINPUT_MOUSE_READ_CYCLES 1
+ #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2
+ #define GINPUT_MOUSE_MAX_CLICK_JITTER 2
+ #define GINPUT_MOUSE_MAX_MOVE_JITTER 2
+#endif
+
+// This driver supports both an "interrupt" mode, and a polled mode
+#define GINPUT_MOUSE_POLL_PERIOD TIME_INFINITE // Interrupt driven by the Window thread
+//#define GINPUT_MOUSE_POLL_PERIOD 25 // Poll driven
+
+#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
+/** @} */
+
diff --git a/drivers/multiple/Win32/ginput_lld_toggle_config.h b/drivers/multiple/Win32/ginput_lld_toggle_config.h
new file mode 100644
index 00000000..84ebaaa2
--- /dev/null
+++ b/drivers/multiple/Win32/ginput_lld_toggle_config.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/multiple/Win32/ginput_lld_toggle_config.h
+ * @brief GINPUT Toggle Driver configuration header.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H
+#define _GINPUT_LLD_TOGGLE_CONFIG_H
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+
+#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here)
+#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs
+#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries
+
+#define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle
+#define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle
+#define GINPUT_TOGGLE_SW3 2 // Switch 3 - Toggle
+#define GINPUT_TOGGLE_SW4 3 // Switch 4 - Toggle
+
+#define GINPUT_TOGGLE_MOMENTARY1 4 // Switch 5 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary
+
+#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
+
+#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */
+/** @} */
+
diff --git a/drivers/multiple/Win32/readme.txt b/drivers/multiple/Win32/readme.txt
new file mode 100644
index 00000000..6151f2f2
--- /dev/null
+++ b/drivers/multiple/Win32/readme.txt
@@ -0,0 +1,22 @@
+To use this driver:
+
+This driver is special in that it implements both the gdisp low level driver
+and a touchscreen driver.
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) #define GFX_USE_GINPUT TRUE
+ #define GINPUT_USE_MOUSE TRUE
+ c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+ d) All of the following (with appropriate values):
+ #define GDISP_SCREEN_WIDTH 640
+ #define GDISP_SCREEN_HEIGHT 480
+
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/gfx.mk
+ include $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.mk
+
+3. Modify your makefile to add -lgdi32 to the DLIBS line. i.e.
+ DLIBS = -lws2_32 -lgdi32
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld.c b/drivers/tdisp/HD44780/tdisp_lld.c
new file mode 100644
index 00000000..d0f4af0d
--- /dev/null
+++ b/drivers/tdisp/HD44780/tdisp_lld.c
@@ -0,0 +1,153 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/tdisp/HD44780/tdisp_lld.c
+ * @brief TDISP driver subsystem low level driver source for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
+
+#include "tdisp_lld_board_example.h"
+
+static void _writeData(uint8_t data) {
+ write_bus(data);
+
+ setpin_e(TRUE);
+ chThdSleepMicroseconds(1);
+ setpin_e(FALSE);
+ chThdSleepMicroseconds(5);
+}
+
+void tdisp_lld_write_cmd(uint8_t data) {
+ setpin_rs(FALSE);
+ setpin_rw(FALSE);
+
+ #if TDISP_NEED_4BIT_MODE
+ _writeData(data>>4);
+ #endif
+ _writeData(data);
+}
+
+void tdisp_lld_write_data(uint8_t data) {
+ setpin_rs(TRUE);
+ setpin_rw(FALSE);
+
+ #if TDISP_NEED_4BIT_MODE
+ _writeData(data>>4);
+ #endif
+ _writeData(data);
+}
+
+bool_t tdisp_lld_init(void) {
+ /* initialise MCU hardware */
+ init_board();
+
+ /* wait some time */
+ chThdSleepMilliseconds(50);
+
+ tdisp_lld_write_cmd(0x38);
+ chThdSleepMilliseconds(64);
+
+ tdisp_lld_write_cmd(0x0f);
+ chThdSleepMicroseconds(50);
+
+ tdisp_lld_write_cmd(0x01);
+ chThdSleepMilliseconds(5);
+
+ tdisp_lld_write_cmd(0x06);
+ chThdSleepMicroseconds(50);
+
+ return TRUE;
+}
+
+void tdisp_lld_set_cursor(coord_t col, coord_t row) {
+ uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+
+ if(row >= TDISP_ROWS)
+ row = TDISP_ROWS - 1;
+
+ tdisp_lld_write_cmd(0x80 | (col + row_offsets[row]));
+}
+
+void tdisp_lld_create_char(uint8_t address, char *charmap) {
+ uint8_t i;
+
+ /* make sure we don't write somewhere we're not supposed to */
+ address &= TDISP_MAX_CUSTOM_CHARS;
+
+ tdisp_lld_write_cmd(0x40 | (address << 3));
+
+ for(i = 0; i < 8; i++) {
+ tdisp_lld_write_data(charmap[i]);
+ }
+}
+
+void tdisp_lld_clear(void) {
+ tdisp_lld_write_cmd(0x01);
+}
+
+void tdisp_lld_home(void) {
+ tdisp_lld_write_cmd(0x02);
+}
+
+void tdisp_lld_control(uint16_t what, void *value) {
+ (void)what;
+ (void)value;
+/*
+ switch(attributes) {
+ case TDISP_ON:
+ _displaycontrol |= 0x04;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ case TDISP_OFF:
+ _displaycontrol &=~ 0x04;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ case TDISP_CURSOR_ON:
+ _displaycontrol |= 0x02;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ case TDISP_CURSOR_OFF:
+ _displaycontrol &=~ 0x02;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ case TDISP_CURSOR_BLINK_ON:
+ _displaycontrol |= 0x00;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ case TDISP_CURSOR_BLINK_OFF:
+ _displaycontrol &=~ 0x00;
+ tdisp_lld_write_cmd(0x08 | _displaycontrol);
+ break;
+ }
+*/
+}
+
+#endif /* GFX_USE_TDISP */
+/** @} */
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld.mk b/drivers/tdisp/HD44780/tdisp_lld.mk
new file mode 100644
index 00000000..88780bea
--- /dev/null
+++ b/drivers/tdisp/HD44780/tdisp_lld.mk
@@ -0,0 +1,6 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/tdisp/HD44780/tdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/tdisp/HD44780
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_example.h b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
new file mode 100644
index 00000000..3f5c47d7
--- /dev/null
+++ b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
@@ -0,0 +1,64 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/tdisp/HD44780/tdisp_lld_board_example.h
+ * @brief TDISP driver subsystem board interface for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_LLD_BOARD_H
+#define _TDISP_LLD_BOARD_H
+
+void init_board(void) {
+ palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetGroupMode(GPIOG, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
+void setpin_e(bool_t state) {
+ if(state)
+ palSetPad(GPIOE, 2);
+ else
+ palClearPad(GPIOE, 2);
+}
+
+void setpin_rs(bool_t state) {
+ if(state)
+ palSetPad(GPIOE, 0);
+ else
+ palClearPad(GPIOE, 0);
+}
+
+void setpin_rw(bool_t state) {
+ if(state)
+ palSetPad(GPIOE, 1);
+ else
+ palClearPad(GPIOE, 1);
+}
+
+void write_bus(uint8_t data) {
+ palWritePort(GPIOG, data);
+}
+
+#endif /* _TDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld_config.h b/drivers/tdisp/HD44780/tdisp_lld_config.h
new file mode 100644
index 00000000..3b37cd70
--- /dev/null
+++ b/drivers/tdisp/HD44780/tdisp_lld_config.h
@@ -0,0 +1,45 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file drivers/tdisp/HD44780/tdisp_lld_config.h
+ * @brief TDISP Driver subsystem low level driver header for the HD44780 display.
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_LLD_CONFIG_H
+#define _TDISP_LLD_CONFIG_H
+
+#if GFX_USE_TDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define TDISP_DRIVER_NAME "HD44780"
+
+#define TDISP_MAX_CUSTOM_CHARS 0x07
+
+#endif /* GFX_USE_TDISP */
+
+#endif /* _TDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/gfx.mk b/gfx.mk
new file mode 100644
index 00000000..c98211fa
--- /dev/null
+++ b/gfx.mk
@@ -0,0 +1,18 @@
+# don't re-define GFXLIB if it has been set elsewhere, e.g in Makefile
+ifeq ($(GFXLIB),)
+ GFXLIB = $(CHIBIOS)/ext/gfx
+endif
+
+GFXINC += $(GFXLIB)/include
+GFXSRC +=
+
+include $(GFXLIB)/src/gdisp/gdisp.mk
+include $(GFXLIB)/src/tdisp/tdisp.mk
+include $(GFXLIB)/src/gevent/gevent.mk
+include $(GFXLIB)/src/gtimer/gtimer.mk
+include $(GFXLIB)/src/gwin/gwin.mk
+include $(GFXLIB)/src/ginput/ginput.mk
+include $(GFXLIB)/src/gadc/gadc.mk
+include $(GFXLIB)/src/gaudin/gaudin.mk
+include $(GFXLIB)/src/gaudout/gaudout.mk
+include $(GFXLIB)/src/gmisc/gmisc.mk
diff --git a/gfxconf.example.h b/gfxconf.example.h
new file mode 100644
index 00000000..11e0e94e
--- /dev/null
+++ b/gfxconf.example.h
@@ -0,0 +1,106 @@
+/**
+ * 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 subsystems to turn on */
+#define GFX_USE_GDISP FALSE
+#define GFX_USE_TDISP FALSE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+#define GFX_USE_GADC FALSE
+#define GFX_USE_GAUDIN FALSE
+#define GFX_USE_GAUDOUT FALSE
+#define GFX_USE_GMISC FALSE
+
+/* Features for the GDISP subsystem */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_CIRCLE TRUE
+#define GDISP_NEED_ELLIPSE TRUE
+#define GDISP_NEED_ARC FALSE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL FALSE
+#define GDISP_NEED_MULTITHREAD FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* GDISP - builtin fonts */
+#define GDISP_OLD_FONT_DEFINITIONS FALSE
+#define GDISP_INCLUDE_FONT_SMALL TRUE
+#define GDISP_INCLUDE_FONT_LARGER TRUE
+#define GDISP_INCLUDE_FONT_UI1 TRUE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS TRUE
+
+/* TDISP options */
+#define TDISP_COLUMNS 16
+#define TDISP_ROWS 2
+#define TDISP_NEED_4BIT_MODE FALSE
+#define TDISP_NEED_8BIT_MODE FALSE
+
+/* Features for the GWIN subsystem. */
+#define GWIN_NEED_BUTTON FALSE
+#define GWIN_NEED_CONSOLE FALSE
+#define GWIN_NEED_GRAPH FALSE
+
+/* Features for the GEVENT subsystem. */
+#define GEVENT_ASSERT_NO_RESOURCE FALSE
+
+/* Features for the GTIMER subsystem. */
+/* NONE */
+
+/* Features for the GINPUT subsystem. */
+#define GINPUT_NEED_MOUSE FALSE
+#define GINPUT_NEED_KEYBOARD FALSE
+#define GINPUT_NEED_TOGGLE FALSE
+#define GINPUT_NEED_DIAL FALSE
+
+/* Features for the GADC subsystem. */
+/* NONE */
+
+/* Features for the GAUDIN subsystem. */
+/* NONE */
+
+/* Features for the GAUDOUT subsystem. */
+/* NONE */
+
+/* Features for the GMISC subsystem. */
+#define GMISC_NEED_ARRAYOPS FALSE
+
+/* Optional Parameters for various subsystems */
+/*
+ #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
+*/
+
+#endif /* _GFXCONF_H */
diff --git a/include/gadc/gadc.h b/include/gadc/gadc.h
new file mode 100644
index 00000000..5c490cb9
--- /dev/null
+++ b/include/gadc/gadc.h
@@ -0,0 +1,250 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gadc/gadc.h
+ * @brief GADC - Periodic ADC subsystem header file.
+ *
+ * @addtogroup GADC
+ *
+ * @details The reason why ChibiOS/GFX has it's own ADC abstraction is because
+ * the Chibi-OS drivers are very CPU specific and do not
+ * provide a way across all hardware platforms to create periodic
+ * ADC conversions. There are also issues with devices with different
+ * characteristics or periodic requirements on the same ADC
+ * device (but different channels). This layer attempts to solve these
+ * problems to provide a architecture neutral API. It also provides extra
+ * features such as multi-buffer chaining for high speed ADC sources.
+ * It provides one high speed virtual ADC device (eg a microphone) and
+ * numerous low speed (less than 100Hz) virtual ADC devices (eg dials,
+ * temperature sensors etc). The high speed device has timer based polling
+ * to ensure exact conversion periods and a buffer management system.
+ * The low speed devices are assumed to be non-critical timing devices
+ * and do not have any buffer management.
+ * Note that while only one high speed device has been provided it can
+ * be used to read multiple physical ADC channels on the one physical
+ * ADC device.
+ * All callback routines are thread based unlike the Chibi-OS interrupt based
+ * routines.
+ *
+ * @{
+ */
+
+#ifndef _GADC_H
+#define _GADC_H
+
+#include "gfx.h"
+
+#if GFX_USE_GADC || defined(__DOXYGEN__)
+
+/* Include the driver defines */
+#include "gadc_lld_config.h"
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+// Event types for GADC
+#define GEVENT_ADC (GEVENT_GADC_FIRST+0)
+
+/**
+ * @brief The High Speed ADC event structure.
+ * @{
+ */
+typedef struct GEventADC_t {
+ /**
+ * @brief The type of this event (GEVENT_ADC)
+ */
+ GEventType type;
+ /**
+ * @brief The event flags
+ */
+ uint16_t flags;
+ /**
+ * @brief The event flag values.
+ * @{
+ */
+ #define GADC_HSADC_LOSTEVENT 0x0001 /**< @brief The last GEVENT_HSDADC event was lost */
+ /** @} */
+ /**
+ * @brief The number of conversions in the buffer
+ */
+ size_t count;
+ /**
+ * @brief The buffer containing the conversion samples
+ */
+ adcsample_t *buffer;
+ } GEventADC;
+
+/**
+ * @brief A callback function (executed in a thread context)
+ */
+typedef void (*GADCCallbackFunction)(adcsample_t *buffer, void *param);
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise the high speed ADC.
+ * @details Initialises but does not start the conversions.
+ *
+ * @param[in] physdev A value passed to describe which physical ADC devices/channels to use.
+ * @param[in] frequency The frequency to create ADC conversions
+ * @param[in] buffer The static buffer to put the ADC 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 high speed ADC is running it will be stopped.
+ * @note Due to a bug 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'
+ * and 'countPerEvent' parameters describe the number of conversions not the
+ * number of samples.
+ * As an example, if physdev turns on 2 devices then the buffer contains
+ * alternate device samples and the buffer must contain 2 * bufcount samples.
+ * The exact meaning of physdev is hardware dependent.
+ * @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.
+ * @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).
+ *
+ * @api
+ */
+void gadcHighSpeedInit(uint32_t physdev, 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_ADC events.
+ *
+ * @note The high speed ADC 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 the high speed ADC.
+ * Once turned on it cannot be turned off.
+ * @note The high speed ADC is capable of signalling via this method and a binary semaphore
+ * at the same time.
+ *
+ * @api
+ */
+ GSourceHandle gadcHighSpeedGetSource(void);
+#endif
+
+/**
+ * @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.
+ * @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 high speed ADC is capable of signalling via this method and the GEVENT
+ * sub-system at the same time.
+ *
+ * @api
+ */
+void gadcHighSpeedSetBSem(BinarySemaphore *pbsem, GEventADC *pEvent);
+
+/**
+ * @brief Start the high speed ADC conversions.
+ * @pre It must have been initialised first with @p gadcHighSpeedInit()
+ *
+ * @api
+ */
+GSourceHandle gadcHighSpeedStart(void);
+
+/**
+ * @brief Stop the high speed ADC conversions.
+ *
+ * @api
+ */
+void gadcHighSpeedStop(void);
+
+/**
+ * @brief Perform a single low speed ADC conversion
+ * @details Blocks until the conversion is complete
+ * @pre This should not be called from within a GTimer callback as this routine
+ * blocks until the conversion is ready.
+ *
+ * @param[in] physdev A value passed to describe which physical ADC devices/channels to use.
+ * @param[in] buffer The static buffer to put the ADC samples into.
+ *
+ * @note This may take a while to complete if the high speed ADC is running as the
+ * conversion is interleaved with the high speed ADC conversions on a buffer
+ * completion.
+ * @note The result buffer must be large enough to store one sample per device
+ * described by the 'physdev' parameter.
+ * @note If calling this routine would exceed @p GADC_MAX_LOWSPEED_DEVICES simultaneous low
+ * speed devices, the routine will wait for an available slot to complete the
+ * conversion.
+ * @note Specifying more than one device in physdev is possible but discouraged as the
+ * calculations to ensure the high speed ADC correctness will be incorrect. Symptoms
+ * from over-running the high speed ADC include high speed samples being lost.
+ *
+ * @api
+ */
+void gadcLowSpeedGet(uint32_t physdev, adcsample_t *buffer);
+
+/**
+ * @brief Perform a low speed ADC conversion with callback (in a thread context)
+ * @details Returns FALSE if there are no free low speed ADC slots. See @p GADC_MAX_LOWSPEED_DEVICES for details.
+ *
+ * @param[in] physdev A value passed to describe which physical ADC devices/channels to use.
+ * @param[in] buffer The static buffer to put the ADC samples into.
+ * @param[in] fn The callback function to call when the conversion is complete.
+ * @param[in] param A parameter to pass to the callback function.
+ *
+ * @note This may be safely called from within a GTimer callback.
+ * @note The callback may take a while to occur if the high speed ADC is running as the
+ * conversion is interleaved with the high speed ADC conversions on a buffer
+ * completion.
+ * @note The result buffer must be large enough to store one sample per device
+ * described by the 'physdev' parameter.
+ * @note As this routine uses a low speed ADC, it asserts if you try to run more than @p GADC_MAX_LOWSPEED_DEVICES
+ * at the same time.
+ * @note Specifying more than one device in physdev is possible but discouraged as the
+ * calculations to ensure the high speed ADC correctness will be incorrect. Symptoms
+ * from over-running the high speed ADC include high speed samples being lost.
+ *
+ * @api
+ */
+bool gadcLowSpeedStart(uint32_t physdev, adcsample_t *buffer, GADCCallbackFunction fn, void *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GADC */
+
+#endif /* _GADC_H */
+/** @} */
+
diff --git a/include/gadc/options.h b/include/gadc/options.h
new file mode 100644
index 00000000..dc5bd300
--- /dev/null
+++ b/include/gadc/options.h
@@ -0,0 +1,57 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gadc/options.h
+ * @brief GADC - Periodic ADC subsystem options header file.
+ *
+ * @addtogroup GADC
+ * @{
+ */
+
+#ifndef _GADC_OPTIONS_H
+#define _GADC_OPTIONS_H
+
+/**
+ * @name GADC Functionality to be included
+ * @{
+ */
+/**
+ * @}
+ *
+ * @name GADC Optional Sizing Parameters
+ * @{
+ */
+ /**
+ * @brief The maximum simultaneous GADC low speed device conversions
+ * @details Defaults to 4
+ * @note This value must be less than the number of conversions that can occur
+ * in a single high speed ADC cycle including the high speed ADC conversion.
+ * For example, if the ADC can run at 132k samples per second and the high speed
+ * virtual ADC is using 44kHz then GADC_MAX_LOWSPEED_DEVICES should be set to
+ * 132/44 - 1 = 2
+ */
+ #ifndef GADC_MAX_LOWSPEED_DEVICES
+ #define GADC_MAX_LOWSPEED_DEVICES 4
+ #endif
+/** @} */
+
+#endif /* _GADC_OPTIONS_H */
+/** @} */
diff --git a/include/gaudin/gaudin.h b/include/gaudin/gaudin.h
new file mode 100644
index 00000000..6f35ba19
--- /dev/null
+++ b/include/gaudin/gaudin.h
@@ -0,0 +1,170 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @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 */
+/** @} */
+
diff --git a/include/gaudin/options.h b/include/gaudin/options.h
new file mode 100644
index 00000000..fdff5197
--- /dev/null
+++ b/include/gaudin/options.h
@@ -0,0 +1,45 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gaudin/options.h
+ * @brief GAUDIN - Audio Input subsystem options header file.
+ *
+ * @addtogroup GAUDIN
+ * @{
+ */
+
+#ifndef _GAUDIN_OPTIONS_H
+#define _GAUDIN_OPTIONS_H
+
+/**
+ * @name GAUDIN Functionality to be included
+ * @{
+ */
+/**
+ * @}
+ *
+ * @name GAUDIN Optional Sizing Parameters
+ * @{
+ */
+/** @} */
+
+#endif /* _GAUDIN_OPTIONS_H */
+/** @} */
diff --git a/include/gaudout/gaudout.h b/include/gaudout/gaudout.h
new file mode 100644
index 00000000..a85bb6f2
--- /dev/null
+++ b/include/gaudout/gaudout.h
@@ -0,0 +1,56 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gaudout/gaudout.h
+ * @brief GAUDOUT - Audio Output subsystem header file.
+ *
+ * @addtogroup GAUDOUT
+ *
+ * @{
+ */
+
+#ifndef _GAUDOUT_H
+#define _GAUDOUT_H
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GAUDOUT */
+
+#endif /* _GAUDOUT_H */
+/** @} */
+
diff --git a/include/gaudout/options.h b/include/gaudout/options.h
new file mode 100644
index 00000000..34c03ac5
--- /dev/null
+++ b/include/gaudout/options.h
@@ -0,0 +1,45 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gaudout/options.h
+ * @brief GAUDOUT - Audio Output subsystem options header file.
+ *
+ * @addtogroup GAUDOUT
+ * @{
+ */
+
+#ifndef _GAUDOUT_OPTIONS_H
+#define _GAUDOUT_OPTIONS_H
+
+/**
+ * @name GAUDOUT Functionality to be included
+ * @{
+ */
+/**
+ * @}
+ *
+ * @name GAUDOUT Optional Sizing Parameters
+ * @{
+ */
+/** @} */
+
+#endif /* _GAUDOUT_OPTIONS_H */
+/** @} */
diff --git a/include/gdisp/fonts.h b/include/gdisp/fonts.h
new file mode 100644
index 00000000..f92f1b81
--- /dev/null
+++ b/include/gdisp/fonts.h
@@ -0,0 +1,80 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/fonts.h
+ * @brief GDISP internal font definitions.
+ * @details This is not generally needed by an application. It is used
+ * by the low level drivers that need to understand a font.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_FONTS_H
+#define _GDISP_FONTS_H
+
+/* Don't test against GFX_USE_GDISP as we may want to use this in other non-GDISP utilities. */
+
+/**
+ * @brief The type of a font column.
+ * @note Set by defining @p GDISP_MAX_FNT_HEIGHT appropriately.
+ */
+#if GDISP_MAX_FONT_HEIGHT == 16
+ typedef uint16_t fontcolumn_t;
+#elif GDISP_MAX_FONT_HEIGHT == 32
+ typedef uint32_t fontcolumn_t;
+#else
+ #error "GDISP: GDISP_MAX_FONT_HEIGHT must be either 16 or 32"
+#endif
+
+/**
+ * @brief Internal font structure.
+ * @note This structure is followed by:
+ * 1. An array of character widths (uint8_t)
+ * 2. An array of column data offsets (relative to the font structure)
+ * 3. Each characters array of column data (fontcolumn_t)
+ * Each sub-structure must be padded to a multiple of 8 bytes
+ * to allow the tables to work across many different compilers.
+ */
+struct font {
+ const char * name;
+ uint8_t height;
+ uint8_t charPadding;
+ uint8_t lineSpacing;
+ uint8_t descenderHeight;
+ uint8_t minWidth;
+ uint8_t maxWidth;
+ char minChar;
+ char maxChar;
+ uint8_t xscale;
+ uint8_t yscale;
+ const uint8_t *widthTable;
+ const uint16_t *offsetTable;
+ const fontcolumn_t *dataTable;
+};
+
+#define _getCharWidth(f,c) (((c) < (f)->minChar || (c) > (f)->maxChar) ? 0 : (f)->widthTable[(c) - (f)->minChar])
+#define _getCharOffset(f,c) ((f)->offsetTable[(c) - (f)->minChar])
+#define _getCharData(f,c) (&(f)->dataTable[_getCharOffset(f, c)])
+
+#endif /* _GDISP_FONTS_H */
+/** @} */
+
diff --git a/include/gdisp/gdisp.h b/include/gdisp/gdisp.h
new file mode 100644
index 00000000..b2e6df53
--- /dev/null
+++ b/include/gdisp/gdisp.h
@@ -0,0 +1,291 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/gdisp.h
+ * @brief GDISP Graphic Driver subsystem header file.
+ *
+ * @addtogroup GDISP
+ *
+ * @details The GDISP module provides high level abstraction to interface pixel oriented graphic displays.
+ *
+ * @pre GFX_USE_GDISP must be set to TRUE in gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GDISP_H
+#define _GDISP_H
+
+#include "gfx.h"
+
+/* This type definition is defined here as it gets used in other gfx sub-systems even
+ * if GFX_USE_GDISP is FALSE.
+ */
+
+/**
+ * @brief The type for a coordinate or length on the screen.
+ */
+typedef int16_t coord_t;
+
+#if GFX_USE_GDISP || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Some basic colors
+ * @{
+ */
+#define White HTML2COLOR(0xFFFFFF)
+#define Black HTML2COLOR(0x000000)
+#define Gray HTML2COLOR(0x808080)
+#define Grey Gray
+#define Blue HTML2COLOR(0x0000FF)
+#define Red HTML2COLOR(0xFF0000)
+#define Fuchsia HTML2COLOR(0xFF00FF)
+#define Magenta Fuchsia
+#define Green HTML2COLOR(0x008000)
+#define Yellow HTML2COLOR(0xFFFF00)
+#define Aqua HTML2COLOR(0x00FFFF)
+#define Cyan Aqua
+#define Lime HTML2COLOR(0x00FF00)
+#define Maroon HTML2COLOR(0x800000)
+#define Navy HTML2COLOR(0x000080)
+#define Olive HTML2COLOR(0x808000)
+#define Purple HTML2COLOR(0x800080)
+#define Silver HTML2COLOR(0xC0C0C0)
+#define Teal HTML2COLOR(0x008080)
+#define Orange HTML2COLOR(0xFFA500)
+#define Pink HTML2COLOR(0xFFC0CB)
+#define SkyBlue HTML2COLOR(0x87CEEB)
+/** @} */
+
+/*===========================================================================*/
+/* Low Level Driver details and error checks. */
+/*===========================================================================*/
+
+/* Include the low level driver information */
+#include "gdisp/lld/gdisp_lld.h"
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/**
+ * @brief Type for the text justification.
+ */
+typedef enum justify {justifyLeft, justifyCenter, justifyRight} justify_t;
+/**
+ * @brief Type for the font metric.
+ */
+typedef enum fontmetric {fontHeight, fontDescendersHeight, fontLineSpacing, fontCharPadding, fontMinWidth, fontMaxWidth} fontmetric_t;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (GDISP_NEED_TEXT && GDISP_OLD_FONT_DEFINITIONS) || defined(__DOXYGEN__)
+ #if GDISP_INCLUDE_FONT_SMALL
+ extern const struct font fontSmall;
+ extern const struct font fontSmallDouble;
+ extern const struct font fontSmallNarrow;
+ #endif
+ #if GDISP_INCLUDE_FONT_LARGER
+ extern const struct font fontLarger;
+ extern const struct font fontLargerDouble;
+ extern const struct font fontLargerNarrow;
+ #endif
+ #if GDISP_INCLUDE_FONT_UI1
+ extern const struct font fontUI1;
+ extern const struct font fontUI1Double;
+ extern const struct font fontUI1Narrow;
+ #endif
+ #if GDISP_INCLUDE_FONT_UI2
+ extern const struct font fontUI2;
+ extern const struct font fontUI2Double;
+ extern const struct font fontUI2Narrow;
+ #endif
+ #if GDISP_INCLUDE_FONT_LARGENUMBERS
+ extern const struct font fontLargeNumbers;
+ extern const struct font fontLargeNumbersDouble;
+ extern const struct font fontLargeNumbersNarrow;
+ #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC
+ /* These routines can be hardware accelerated
+ * - Do not add a routine here unless it has also been added to the hardware acceleration layer
+ */
+
+ /* Base Functions */
+ bool_t gdispInit(void);
+ bool_t gdispIsBusy(void);
+
+ /* Drawing Functions */
+ void gdispClear(color_t color);
+ void gdispDrawPixel(coord_t x, coord_t y, color_t color);
+ void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color);
+ void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+ void gdispBlitAreaEx(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);
+
+ /* Clipping Functions */
+ #if GDISP_NEED_CLIP
+ void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy);
+ #endif
+
+ /* Circle Functions */
+ #if GDISP_NEED_CIRCLE
+ void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color);
+ void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color);
+ #endif
+
+ /* Ellipse Functions */
+ #if GDISP_NEED_ELLIPSE
+ void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ #endif
+
+ /* Arc Functions */
+ #if GDISP_NEED_ARC
+ void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ #endif
+
+ /* Basic Text Rendering Functions */
+ #if GDISP_NEED_TEXT
+ void gdispDrawChar(coord_t x, coord_t y, char c, font_t font, color_t color);
+ void gdispFillChar(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor);
+ #endif
+
+ /* Read a pixel Function */
+ #if GDISP_NEED_PIXELREAD
+ color_t gdispGetPixelColor(coord_t x, coord_t y);
+ #endif
+
+ /* Scrolling Function - clears the area scrolled out */
+ #if GDISP_NEED_SCROLL
+ void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor);
+ #endif
+
+ /* Set driver specific control */
+ #if GDISP_NEED_CONTROL
+ void gdispControl(unsigned what, void *value);
+ #endif
+
+ /* Query driver specific data */
+ void *gdispQuery(unsigned what);
+
+#else
+
+ /* The same as above but use the low level driver directly if no multi-thread support is needed */
+ #define gdispInit(gdisp) lld_gdisp_init()
+ #define gdispIsBusy() FALSE
+ #define gdispClear(color) lld_gdisp_clear(color)
+ #define gdispDrawPixel(x, y, color) lld_gdisp_draw_pixel(x, y, color)
+ #define gdispDrawLine(x0, y0, x1, y1, color) lld_gdisp_draw_line(x0, y0, x1, y1, color)
+ #define gdispFillArea(x, y, cx, cy, color) lld_gdisp_fill_area(x, y, cx, cy, color)
+ #define gdispBlitAreaEx(x, y, cx, cy, sx, sy, scx, buf) lld_gdisp_blit_area_ex(x, y, cx, cy, sx, sy, scx, buf)
+ #define gdispSetClip(x, y, cx, cy) lld_gdisp_set_clip(x, y, cx, cy)
+ #define gdispDrawCircle(x, y, radius, color) lld_gdisp_draw_circle(x, y, radius, color)
+ #define gdispFillCircle(x, y, radius, color) lld_gdisp_fill_circle(x, y, radius, color)
+ #define gdispDrawArc(x, y, radius, sangle, eangle, color) lld_gdisp_draw_arc(x, y, radius, sangle, eangle, color)
+ #define gdispFillArc(x, y, radius, sangle, eangle, color) lld_gdisp_fill_arc(x, y, radius, sangle, eangle, color)
+ #define gdispDrawEllipse(x, y, a, b, color) lld_gdisp_draw_ellipse(x, y, a, b, color)
+ #define gdispFillEllipse(x, y, a, b, color) lld_gdisp_fill_ellipse(x, y, a, b, color)
+ #define gdispDrawChar(x, y, c, font, color) lld_gdisp_draw_char(x, y, c, font, color)
+ #define gdispFillChar(x, y, c, font, color, bgcolor) lld_gdisp_fill_char(x, y, c, font, color, bgcolor)
+ #define gdispGetPixelColor(x, y) lld_gdisp_get_pixel_color(x, y)
+ #define gdispVerticalScroll(x, y, cx, cy, lines, bgcolor) lld_gdisp_vertical_scroll(x, y, cx, cy, lines, bgcolor)
+ #define gdispControl(what, value) lld_gdisp_control(what, value)
+ #define gdispQuery(what) lld_gdisp_query(what)
+
+#endif
+
+/* These routines are not hardware accelerated
+ * - Do not add a hardware accelerated routines here.
+ */
+
+/* Extra drawing functions */
+void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+
+/* Extra Text Functions */
+#if GDISP_NEED_TEXT
+ void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color);
+ void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor);
+ void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify);
+ void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgColor, justify_t justify);
+ coord_t gdispGetFontMetric(font_t font, fontmetric_t metric);
+ coord_t gdispGetCharWidth(char c, font_t font);
+ coord_t gdispGetStringWidth(const char* str, font_t font);
+ font_t gdispOpenFont(const char *name);
+ void gdispCloseFont(font_t font);
+ const char *gdispGetFontName(font_t font);
+#endif
+
+/* Extra Arc Functions */
+#if GDISP_NEED_ARC
+ void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color);
+ void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color);
+#endif
+
+/* Support routine for packed pixel formats */
+#ifndef gdispPackPixels
+ void gdispPackPixels(const pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color);
+#endif
+
+/*
+ * Macro definitions
+ */
+
+/* Now obsolete functions */
+#define gdispBlitArea(x, y, cx, cy, buffer) gdispBlitAreaEx(x, y, cx, cy, 0, 0, cx, buffer)
+
+/* Macro definitions for common gets and sets */
+#define gdispSetPowerMode(powerMode) gdispControl(GDISP_CONTROL_POWER, (void *)(unsigned)(powerMode))
+#define gdispSetOrientation(newOrientation) gdispControl(GDISP_CONTROL_ORIENTATION, (void *)(unsigned)(newOrientation))
+#define gdispSetBacklight(percent) gdispControl(GDISP_CONTROL_BACKLIGHT, (void *)(unsigned)(percent))
+#define gdispSetContrast(percent) gdispControl(GDISP_CONTROL_CONTRAST, (void *)(unsigned)(percent))
+
+#define gdispGetWidth() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_WIDTH))
+#define gdispGetHeight() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_HEIGHT))
+#define gdispGetPowerMode() ((gdisp_powermode_t)(unsigned)gdispQuery(GDISP_QUERY_POWER))
+#define gdispGetOrientation() ((gdisp_orientation_t)(unsigned)gdispQuery(GDISP_QUERY_ORIENTATION))
+#define gdispGetBacklight() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_BACKLIGHT))
+#define gdispGetContrast() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_CONTRAST))
+
+/* More interesting macro's */
+#define gdispUnsetClip() gdispSetClip(0,0,gdispGetWidth(),gdispGetHeight())
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_H */
+/** @} */
+
diff --git a/include/gdisp/lld/emulation.c b/include/gdisp/lld/emulation.c
new file mode 100644
index 00000000..bd9394af
--- /dev/null
+++ b/include/gdisp/lld/emulation.c
@@ -0,0 +1,772 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/lld/emulation.c
+ * @brief GDISP emulation routines for stuff the driver dosen't support
+ *
+ * @addtogroup GDISP
+ *
+ * @details Even though this is a software emulation of a low level driver
+ * most validation doesn't need to happen here as eventually
+ * we call a real low level driver routine and if validation is
+ * required - it will do it.
+ *
+ * @{
+ */
+#ifndef GDISP_EMULATION_C
+#define GDISP_EMULATION_C
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__) */
+
+#ifndef GDISP_LLD_NO_STRUCT
+ static struct GDISPDriver {
+ coord_t Width;
+ coord_t Height;
+ gdisp_orientation_t Orientation;
+ gdisp_powermode_t Powermode;
+ uint8_t Backlight;
+ uint8_t Contrast;
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ coord_t clipx0, clipy0;
+ coord_t clipx1, clipy1; /* not inclusive */
+ #endif
+ } GDISP;
+#endif
+
+#if !GDISP_HARDWARE_CLEARS
+ void lld_gdisp_clear(color_t color) {
+ lld_gdisp_fill_area(0, 0, GDISP.Width, GDISP.Height, color);
+ }
+#endif
+
+#if !GDISP_HARDWARE_LINES
+ void lld_gdisp_draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
+ int16_t dy, dx;
+ int16_t addx, addy;
+ int16_t P, diff, i;
+
+ #if GDISP_HARDWARE_FILLS || GDISP_HARDWARE_SCROLL
+ // speed improvement if vertical or horizontal
+ if (x0 == x1) {
+ if (y1 > y0)
+ lld_gdisp_fill_area(x0, y0, 1, y1-y0+1, color);
+ else
+ lld_gdisp_fill_area(x0, y1, 1, y0-y1+1, color);
+ return;
+ }
+ if (y0 == y1) {
+ if (x1 > x0)
+ lld_gdisp_fill_area(x0, y0, x1-x0+1, 1, color);
+ else
+ lld_gdisp_fill_area(x0, y1, x0-x1+1, 1, color);
+ return;
+ }
+ #endif
+
+ if (x1 >= x0) {
+ dx = x1 - x0;
+ addx = 1;
+ } else {
+ dx = x0 - x1;
+ addx = -1;
+ }
+ if (y1 >= y0) {
+ dy = y1 - y0;
+ addy = 1;
+ } else {
+ dy = y0 - y1;
+ addy = -1;
+ }
+
+ if (dx >= dy) {
+ dy *= 2;
+ P = dy - dx;
+ diff = P - dx;
+
+ for(i=0; i<=dx; ++i) {
+ lld_gdisp_draw_pixel(x0, y0, color);
+ if (P < 0) {
+ P += dy;
+ x0 += addx;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ } else {
+ dx *= 2;
+ P = dx - dy;
+ diff = P - dy;
+
+ for(i=0; i<=dy; ++i) {
+ lld_gdisp_draw_pixel(x0, y0, color);
+ if (P < 0) {
+ P += dx;
+ y0 += addy;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ }
+ }
+#endif
+
+#if !GDISP_HARDWARE_FILLS
+ void lld_gdisp_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ #if GDISP_HARDWARE_SCROLL
+ lld_gdisp_vertical_scroll(x, y, cx, cy, cy, color);
+ #elif GDISP_HARDWARE_LINES
+ coord_t x1, y1;
+
+ x1 = x + cx - 1;
+ y1 = y + cy;
+ for(; y < y1; y++)
+ lld_gdisp_draw_line(x, y, x1, y, color);
+ #else
+ coord_t x0, x1, y1;
+
+ x0 = x;
+ x1 = x + cx;
+ y1 = y + cy;
+ for(; y < y1; y++)
+ for(x = x0; x < x1; x++)
+ lld_gdisp_draw_pixel(x, y, color);
+ #endif
+ }
+#endif
+
+#if !GDISP_HARDWARE_BITFILLS
+ void lld_gdisp_blit_area_ex(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) {
+ coord_t x0, x1, y1;
+
+ x0 = x;
+ x1 = x + cx;
+ y1 = y + cy;
+ buffer += srcy*srccx+srcx;
+ srccx -= cx;
+ for(; y < y1; y++, buffer += srccx)
+ for(x=x0; x < x1; x++)
+ lld_gdisp_draw_pixel(x, y, *buffer++);
+ }
+#endif
+
+#if GDISP_NEED_CLIP && !GDISP_HARDWARE_CLIP
+ void lld_gdisp_set_clip(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ #if GDISP_NEED_VALIDATION
+ if (x >= GDISP.Width || y >= GDISP.Height || cx < 0 || cy < 0)
+ return;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x+cx > GDISP.Width) cx = GDISP.Width - x;
+ if (y+cy > GDISP.Height) cy = GDISP.Height - y;
+ #endif
+ GDISP.clipx0 = x;
+ GDISP.clipy0 = y;
+ GDISP.clipx1 = x+cx;
+ GDISP.clipy1 = y+cy;
+ }
+#endif
+
+#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLES
+ void lld_gdisp_draw_circle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ coord_t a, b, P;
+
+ a = 0;
+ b = radius;
+ P = 1 - radius;
+
+ do {
+ lld_gdisp_draw_pixel(x+a, y+b, color);
+ lld_gdisp_draw_pixel(x+b, y+a, color);
+ lld_gdisp_draw_pixel(x-a, y+b, color);
+ lld_gdisp_draw_pixel(x-b, y+a, color);
+ lld_gdisp_draw_pixel(x+b, y-a, color);
+ lld_gdisp_draw_pixel(x+a, y-b, color);
+ lld_gdisp_draw_pixel(x-a, y-b, color);
+ lld_gdisp_draw_pixel(x-b, y-a, color);
+ if (P < 0)
+ P += 3 + 2*a++;
+ else
+ P += 5 + 2*(a++ - b--);
+ } while(a <= b);
+ }
+#endif
+
+#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLEFILLS
+ void lld_gdisp_fill_circle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ coord_t a, b, P;
+
+ a = 0;
+ b = radius;
+ P = 1 - radius;
+
+ do {
+ lld_gdisp_draw_line(x-a, y+b, x+a, y+b, color);
+ lld_gdisp_draw_line(x-a, y-b, x+a, y-b, color);
+ lld_gdisp_draw_line(x-b, y+a, x+b, y+a, color);
+ lld_gdisp_draw_line(x-b, y-a, x+b, y-a, color);
+ if (P < 0)
+ P += 3 + 2*a++;
+ else
+ P += 5 + 2*(a++ - b--);
+ } while(a <= b);
+ }
+#endif
+
+#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSES
+ void lld_gdisp_draw_ellipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */
+ long a2 = a*a, b2 = b*b;
+ long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */
+
+ do {
+ lld_gdisp_draw_pixel(x+dx, y+dy, color); /* I. Quadrant */
+ lld_gdisp_draw_pixel(x-dx, y+dy, color); /* II. Quadrant */
+ lld_gdisp_draw_pixel(x-dx, y-dy, color); /* III. Quadrant */
+ lld_gdisp_draw_pixel(x+dx, y-dy, color); /* IV. Quadrant */
+
+ e2 = 2*err;
+ if(e2 < (2*dx+1)*b2) {
+ dx++;
+ err += (2*dx+1)*b2;
+ }
+ if(e2 > -(2*dy-1)*a2) {
+ dy--;
+ err -= (2*dy-1)*a2;
+ }
+ } while(dy >= 0);
+
+ while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */
+ lld_gdisp_draw_pixel(x+dx, y, color); /* -> Spitze der Ellipse vollenden */
+ lld_gdisp_draw_pixel(x-dx, y, color);
+ }
+ }
+#endif
+
+#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSEFILLS
+ void lld_gdisp_fill_ellipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */
+ long a2 = a*a, b2 = b*b;
+ long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */
+
+ do {
+ lld_gdisp_draw_line(x-dx,y+dy,x+dx,y+dy, color);
+ lld_gdisp_draw_line(x-dx,y-dy,x+dx,y-dy, color);
+
+ e2 = 2*err;
+ if(e2 < (2*dx+1)*b2) {
+ dx++;
+ err += (2*dx+1)*b2;
+ }
+ if(e2 > -(2*dy-1)*a2) {
+ dy--;
+ err -= (2*dy-1)*a2;
+ }
+ } while(dy >= 0);
+
+ while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */
+ lld_gdisp_draw_pixel(x+dx, y, color); /* -> Spitze der Ellipse vollenden */
+ lld_gdisp_draw_pixel(x-dx, y, color);
+ }
+ }
+#endif
+
+#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCS
+
+ #include
+
+ /*
+ * @brief Internal helper function for gdispDrawArc()
+ *
+ * @note DO NOT USE DIRECTLY!
+ *
+ * @param[in] x, y The middle point of the arc
+ * @param[in] start The start angle of the arc
+ * @param[in] end The end angle of the arc
+ * @param[in] radius The radius of the arc
+ * @param[in] color The color in which the arc will be drawn
+ *
+ * @notapi
+ */
+ static void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
+ if (/*start >= 0 && */start <= 180) {
+ float x_maxI = x + radius*cos(start*M_PI/180);
+ float x_minI;
+
+ if (end > 180)
+ x_minI = x - radius;
+ else
+ x_minI = x + radius*cos(end*M_PI/180);
+
+ int a = 0;
+ int b = radius;
+ int P = 1 - radius;
+
+ do {
+ if(x-a <= x_maxI && x-a >= x_minI)
+ lld_gdisp_draw_pixel(x-a, y-b, color);
+ if(x+a <= x_maxI && x+a >= x_minI)
+ lld_gdisp_draw_pixel(x+a, y-b, color);
+ if(x-b <= x_maxI && x-b >= x_minI)
+ lld_gdisp_draw_pixel(x-b, y-a, color);
+ if(x+b <= x_maxI && x+b >= x_minI)
+ lld_gdisp_draw_pixel(x+b, y-a, color);
+
+ if (P < 0) {
+ P = P + 3 + 2*a;
+ a = a + 1;
+ } else {
+ P = P + 5 + 2*(a - b);
+ a = a + 1;
+ b = b - 1;
+ }
+ } while(a <= b);
+ }
+
+ if (end > 180 && end <= 360) {
+ float x_maxII = x+radius*cos(end*M_PI/180);
+ float x_minII;
+
+ if(start <= 180)
+ x_minII = x - radius;
+ else
+ x_minII = x+radius*cos(start*M_PI/180);
+
+ int a = 0;
+ int b = radius;
+ int P = 1 - radius;
+
+ do {
+ if(x-a <= x_maxII && x-a >= x_minII)
+ lld_gdisp_draw_pixel(x-a, y+b, color);
+ if(x+a <= x_maxII && x+a >= x_minII)
+ lld_gdisp_draw_pixel(x+a, y+b, color);
+ if(x-b <= x_maxII && x-b >= x_minII)
+ lld_gdisp_draw_pixel(x-b, y+a, color);
+ if(x+b <= x_maxII && x+b >= x_minII)
+ lld_gdisp_draw_pixel(x+b, y+a, color);
+
+ if (P < 0) {
+ P = P + 3 + 2*a;
+ a = a + 1;
+ } else {
+ P = P + 5 + 2*(a - b);
+ a = a + 1;
+ b = b - 1;
+ }
+ } while (a <= b);
+ }
+ }
+
+ void lld_gdisp_draw_arc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) {
+ if(endangle < startangle) {
+ _draw_arc(x, y, startangle, 360, radius, color);
+ _draw_arc(x, y, 0, endangle, radius, color);
+ } else {
+ _draw_arc(x, y, startangle, endangle, radius, color);
+ }
+ }
+#endif
+
+#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCFILLS
+ /*
+ * @brief Internal helper function for gdispDrawArc()
+ *
+ * @note DO NOT USE DIRECTLY!
+ *
+ * @param[in] x, y The middle point of the arc
+ * @param[in] start The start angle of the arc
+ * @param[in] end The end angle of the arc
+ * @param[in] radius The radius of the arc
+ * @param[in] color The color in which the arc will be drawn
+ *
+ * @notapi
+ */
+ static void _fill_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
+ if (/*start >= 0 && */start <= 180) {
+ float x_maxI = x + radius*cos(start*M_PI/180);
+ float x_minI;
+
+ if (end > 180)
+ x_minI = x - radius;
+ else
+ x_minI = x + radius*cos(end*M_PI/180);
+
+ int a = 0;
+ int b = radius;
+ int P = 1 - radius;
+
+ do {
+ if(x-a <= x_maxI && x-a >= x_minI)
+ lld_gdisp_draw_line(x, y, x-a, y-b, color);
+ if(x+a <= x_maxI && x+a >= x_minI)
+ lld_gdisp_draw_line(x, y, x+a, y-b, color);
+ if(x-b <= x_maxI && x-b >= x_minI)
+ lld_gdisp_draw_line(x, y, x-b, y-a, color);
+ if(x+b <= x_maxI && x+b >= x_minI)
+ lld_gdisp_draw_line(x, y, x+b, y-a, color);
+
+ if (P < 0) {
+ P = P + 3 + 2*a;
+ a = a + 1;
+ } else {
+ P = P + 5 + 2*(a - b);
+ a = a + 1;
+ b = b - 1;
+ }
+ } while(a <= b);
+ }
+
+ if (end > 180 && end <= 360) {
+ float x_maxII = x+radius*cos(end*M_PI/180);
+ float x_minII;
+
+ if(start <= 180)
+ x_minII = x - radius;
+ else
+ x_minII = x+radius*cos(start*M_PI/180);
+
+ int a = 0;
+ int b = radius;
+ int P = 1 - radius;
+
+ do {
+ if(x-a <= x_maxII && x-a >= x_minII)
+ lld_gdisp_draw_line(x, y, x-a, y+b, color);
+ if(x+a <= x_maxII && x+a >= x_minII)
+ lld_gdisp_draw_line(x, y, x+a, y+b, color);
+ if(x-b <= x_maxII && x-b >= x_minII)
+ lld_gdisp_draw_line(x, y, x-b, y+a, color);
+ if(x+b <= x_maxII && x+b >= x_minII)
+ lld_gdisp_draw_line(x, y, x+b, y+a, color);
+
+ if (P < 0) {
+ P = P + 3 + 2*a;
+ a = a + 1;
+ } else {
+ P = P + 5 + 2*(a - b);
+ a = a + 1;
+ b = b - 1;
+ }
+ } while (a <= b);
+ }
+ }
+
+ void lld_gdisp_fill_arc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) {
+ if(endangle < startangle) {
+ _fill_arc(x, y, startangle, 360, radius, color);
+ _fill_arc(x, y, 0, endangle, radius, color);
+ } else {
+ _fill_arc(x, y, startangle, endangle, radius, color);
+ }
+ }
+#endif
+
+#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT
+ #include "gdisp/fonts.h"
+#endif
+
+#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT
+ void lld_gdisp_draw_char(coord_t x, coord_t y, char c, font_t font, color_t color) {
+ const fontcolumn_t *ptr;
+ fontcolumn_t column;
+ coord_t width, height, xscale, yscale;
+ coord_t i, j, xs, ys;
+
+ /* Check we actually have something to print */
+ width = _getCharWidth(font, c);
+ if (!width) return;
+
+ xscale = font->xscale;
+ yscale = font->yscale;
+ height = font->height * yscale;
+ width *= xscale;
+
+ ptr = _getCharData(font, c);
+
+ /* Loop through the data and display. The font data is LSBit first, down the column */
+ for(i=0; i < width; i+=xscale) {
+ /* Get the font bitmap data for the column */
+ column = *ptr++;
+
+ /* Draw each pixel */
+ for(j=0; j < height; j+=yscale, column >>= 1) {
+ if (column & 0x01) {
+ for(xs=0; xs < xscale; xs++)
+ for(ys=0; ys < yscale; ys++)
+ lld_gdisp_draw_pixel(x+i+xs, y+j+ys, color);
+ }
+ }
+ }
+ }
+#endif
+
+#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXTFILLS
+ void lld_gdisp_fill_char(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) {
+ coord_t width, height;
+ coord_t xscale, yscale;
+
+ /* Check we actually have something to print */
+ width = _getCharWidth(font, c);
+ if (!width) return;
+
+ xscale = font->xscale;
+ yscale = font->yscale;
+ height = font->height * yscale;
+ width *= xscale;
+
+ /* Method 1: Use background fill and then draw the text */
+ #if GDISP_HARDWARE_TEXT || GDISP_SOFTWARE_TEXTFILLDRAW
+
+ /* Fill the area */
+ lld_gdisp_fill_area(x, y, width, height, bgcolor);
+
+ /* Draw the text */
+ lld_gdisp_draw_char(x, y, c, font, color);
+
+ /* Method 2: Create a single column bitmap and then blit it */
+ #elif GDISP_HARDWARE_BITFILLS && GDISP_SOFTWARE_TEXTBLITCOLUMN
+ {
+ const fontcolumn_t *ptr;
+ fontcolumn_t column;
+ coord_t i, j, xs, ys;
+
+ /* Working buffer for fast non-transparent text rendering [patch by Badger]
+ This needs to be larger than the largest character we can print.
+ Assume the max is double sized by one column.
+ */
+ static pixel_t buf[sizeof(fontcolumn_t)*8*2];
+
+ #if GDISP_NEED_VALIDATION
+ /* Check our buffer is big enough */
+ if ((unsigned)height > sizeof(buf)/sizeof(buf[0])) return;
+ #endif
+
+ ptr = _getCharData(font, c);
+
+ /* Loop through the data and display. The font data is LSBit first, down the column */
+ for(i = 0; i < width; i+=xscale) {
+ /* Get the font bitmap data for the column */
+ column = *ptr++;
+
+ /* Draw each pixel */
+ for(j = 0; j < height; j+=yscale, column >>= 1) {
+ if (column & 0x01) {
+ for(ys=0; ys < yscale; ys++)
+ gdispPackPixels(buf, 1, j+ys, 0, color);
+ } else {
+ for(ys=0; ys < yscale; ys++)
+ gdispPackPixels(buf, 1, j+ys, 0, bgcolor);
+ }
+ }
+
+ for(xs=0; xs < xscale; xs++)
+ lld_gdisp_blit_area_ex(x+i+xs, y, 1, height, 0, 0, 1, buf);
+ }
+ }
+
+ /* Method 3: Create a character bitmap and then blit it */
+ #elif GDISP_HARDWARE_BITFILLS
+ {
+ const fontcolumn_t *ptr;
+ fontcolumn_t column;
+ coord_t i, j, xs, ys;
+
+ /* Working buffer for fast non-transparent text rendering [patch by Badger]
+ This needs to be larger than the largest character we can print.
+ Assume the max is double sized.
+ */
+ static pixel_t buf[20*(sizeof(fontcolumn_t)*8)*2];
+
+ #if GDISP_NEED_VALIDATION
+ /* Check our buffer is big enough */
+ if ((unsigned)(width * height) > sizeof(buf)/sizeof(buf[0])) return;
+ #endif
+
+ ptr = _getCharData(font, c);
+
+ /* Loop through the data and display. The font data is LSBit first, down the column */
+ for(i = 0; i < width; i+=xscale) {
+ /* Get the font bitmap data for the column */
+ column = *ptr++;
+
+ /* Draw each pixel */
+ for(j = 0; j < height; j+=yscale, column >>= 1) {
+ if (column & 0x01) {
+ for(xs=0; xs < xscale; xs++)
+ for(ys=0; ys < yscale; ys++)
+ gdispPackPixels(buf, width, i+xs, j+ys, color);
+ } else {
+ for(xs=0; xs < xscale; xs++)
+ for(ys=0; ys < yscale; ys++)
+ gdispPackPixels(buf, width, i+xs, j+ys, bgcolor);
+ }
+ }
+ }
+
+ /* [Patch by Badger] Write all in one stroke */
+ lld_gdisp_blit_area_ex(x, y, width, height, 0, 0, width, buf);
+ }
+
+ /* Method 4: Draw pixel by pixel */
+ #else
+ {
+ const fontcolumn_t *ptr;
+ fontcolumn_t column;
+ coord_t i, j, xs, ys;
+
+ ptr = _getCharData(font, c);
+
+ /* Loop through the data and display. The font data is LSBit first, down the column */
+ for(i = 0; i < width; i+=xscale) {
+ /* Get the font bitmap data for the column */
+ column = *ptr++;
+
+ /* Draw each pixel */
+ for(j = 0; j < height; j+=yscale, column >>= 1) {
+ if (column & 0x01) {
+ for(xs=0; xs < xscale; xs++)
+ for(ys=0; ys < yscale; ys++)
+ lld_gdisp_draw_pixel(x+i+xs, y+j+ys, color);
+ } else {
+ for(xs=0; xs < xscale; xs++)
+ for(ys=0; ys < yscale; ys++)
+ lld_gdisp_draw_pixel(x+i+xs, y+j+ys, bgcolor);
+ }
+ }
+ }
+ }
+ #endif
+ }
+#endif
+
+
+#if GDISP_NEED_CONTROL && !GDISP_HARDWARE_CONTROL
+ void lld_gdisp_control(unsigned what, void *value) {
+ (void)what;
+ (void)value;
+ /* Ignore everything */
+ }
+#endif
+
+#if !GDISP_HARDWARE_QUERY
+void *lld_gdisp_query(unsigned what) {
+ switch(what) {
+ case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width;
+ case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height;
+ case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode;
+ case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation;
+ case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight;
+ case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast;
+ default: return (void *)-1;
+ }
+}
+#endif
+
+#if GDISP_NEED_MSGAPI
+ void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg) {
+ switch(msg->action) {
+ case GDISP_LLD_MSG_NOP:
+ break;
+ case GDISP_LLD_MSG_INIT:
+ lld_gdisp_init();
+ break;
+ case GDISP_LLD_MSG_CLEAR:
+ lld_gdisp_clear(msg->clear.color);
+ break;
+ case GDISP_LLD_MSG_DRAWPIXEL:
+ lld_gdisp_draw_pixel(msg->drawpixel.x, msg->drawpixel.y, msg->drawpixel.color);
+ break;
+ case GDISP_LLD_MSG_FILLAREA:
+ lld_gdisp_fill_area(msg->fillarea.x, msg->fillarea.y, msg->fillarea.cx, msg->fillarea.cy, msg->fillarea.color);
+ break;
+ case GDISP_LLD_MSG_BLITAREA:
+ lld_gdisp_blit_area_ex(msg->blitarea.x, msg->blitarea.y, msg->blitarea.cx, msg->blitarea.cy, msg->blitarea.srcx, msg->blitarea.srcy, msg->blitarea.srccx, msg->blitarea.buffer);
+ break;
+ case GDISP_LLD_MSG_DRAWLINE:
+ lld_gdisp_draw_line(msg->drawline.x0, msg->drawline.y0, msg->drawline.x1, msg->drawline.y1, msg->drawline.color);
+ break;
+ #if GDISP_NEED_CLIP
+ case GDISP_LLD_MSG_SETCLIP:
+ lld_gdisp_set_clip(msg->setclip.x, msg->setclip.y, msg->setclip.cx, msg->setclip.cy);
+ break;
+ #endif
+ #if GDISP_NEED_CIRCLE
+ case GDISP_LLD_MSG_DRAWCIRCLE:
+ lld_gdisp_draw_circle(msg->drawcircle.x, msg->drawcircle.y, msg->drawcircle.radius, msg->drawcircle.color);
+ break;
+ case GDISP_LLD_MSG_FILLCIRCLE:
+ lld_gdisp_fill_circle(msg->fillcircle.x, msg->fillcircle.y, msg->fillcircle.radius, msg->fillcircle.color);
+ break;
+ #endif
+ #if GDISP_NEED_ELLIPSE
+ case GDISP_LLD_MSG_DRAWELLIPSE:
+ lld_gdisp_draw_ellipse(msg->drawellipse.x, msg->drawellipse.y, msg->drawellipse.a, msg->drawellipse.b, msg->drawellipse.color);
+ break;
+ case GDISP_LLD_MSG_FILLELLIPSE:
+ lld_gdisp_fill_ellipse(msg->fillellipse.x, msg->fillellipse.y, msg->fillellipse.a, msg->fillellipse.b, msg->fillellipse.color);
+ break;
+ #endif
+ #if GDISP_NEED_ARC
+ case GDISP_LLD_MSG_DRAWARC:
+ lld_gdisp_draw_circle(msg->drawarc.x, msg->drawarc.y, msg->drawarc.radius, msg->drawarc.startangle, msg->drawarc.endangle, msg->drawarc.color);
+ break;
+ case GDISP_LLD_MSG_FILLARC:
+ lld_gdisp_fill_circle(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color);
+ break;
+ #endif
+ #if GDISP_NEED_TEXT
+ case GDISP_LLD_MSG_DRAWCHAR:
+ lld_gdisp_draw_char(msg->drawchar.x, msg->drawchar.y, msg->drawchar.c, msg->drawchar.font, msg->drawchar.color);
+ break;
+ case GDISP_LLD_MSG_FILLCHAR:
+ lld_gdisp_fill_char(msg->fillchar.x, msg->fillchar.y, msg->fillchar.c, msg->fillchar.font, msg->fillchar.color, msg->fillchar.bgcolor);
+ break;
+ #endif
+ #if GDISP_NEED_PIXELREAD
+ case GDISP_LLD_MSG_GETPIXELCOLOR:
+ msg->getpixelcolor.result = lld_gdisp_get_pixel_color(msg->getpixelcolor.x, msg->getpixelcolor.y);
+ break;
+ #endif
+ #if GDISP_NEED_SCROLL
+ case GDISP_LLD_MSG_VERTICALSCROLL:
+ lld_gdisp_vertical_scroll(msg->verticalscroll.x, msg->verticalscroll.y, msg->verticalscroll.cx, msg->verticalscroll.cy, msg->verticalscroll.lines, msg->verticalscroll.bgcolor);
+ break;
+ #endif
+ #if GDISP_NEED_CONTROL
+ case GDISP_LLD_MSG_CONTROL:
+ lld_gdisp_control(msg->control.what, msg->control.value);
+ break;
+ #endif
+ case GDISP_LLD_MSG_QUERY:
+ msg->query.result = lld_gdisp_query(msg->query.what);
+ break;
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+#endif /* GDISP_EMULATION_C */
+/** @} */
+
diff --git a/include/gdisp/lld/gdisp_lld.h b/include/gdisp/lld/gdisp_lld.h
new file mode 100644
index 00000000..d648f6e3
--- /dev/null
+++ b/include/gdisp/lld/gdisp_lld.h
@@ -0,0 +1,544 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/lld/gdisp_lld.h
+ * @brief GDISP Graphic Driver subsystem low level driver header.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_H
+#define _GDISP_LLD_H
+
+#if GFX_USE_GDISP || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Low level driver configuration needs */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Include the low level driver configuration information */
+/*===========================================================================*/
+
+#include "gdisp_lld_config.h"
+
+/*===========================================================================*/
+/* Constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver Control Constants
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
+ * GDISP_CONTROL_LLD - Low level driver control constants start at
+ * this value.
+ */
+#define GDISP_CONTROL_POWER 0
+#define GDISP_CONTROL_ORIENTATION 1
+#define GDISP_CONTROL_BACKLIGHT 2
+#define GDISP_CONTROL_CONTRAST 3
+#define GDISP_CONTROL_LLD 1000
+
+/**
+ * @brief Driver Query Constants
+ * @details Unsupported query codes return (void *)-1.
+ * @note There are some predefined and some specific to the low level driver.
+ * @note The result should be typecast the required type.
+ * @note GDISP_QUERY_WIDTH - Gets the width of the screen
+ * GDISP_QUERY_HEIGHT - Gets the height of the screen
+ * GDISP_QUERY_POWER - Get the current powermode
+ * GDISP_QUERY_ORIENTATION - Get the current orientation
+ * GDISP_QUERY_BACKLIGHT - Get the backlight state (0 to 100)
+ * GDISP_QUERY_CONTRAST - Get the contrast.
+ * GDISP_QUERY_LLD - Low level driver control constants start at
+ * this value.
+ */
+#define GDISP_QUERY_WIDTH 0
+#define GDISP_QUERY_HEIGHT 1
+#define GDISP_QUERY_POWER 2
+#define GDISP_QUERY_ORIENTATION 3
+#define GDISP_QUERY_BACKLIGHT 4
+#define GDISP_QUERY_CONTRAST 5
+#define GDISP_QUERY_LLD 1000
+
+/**
+ * @brief Driver Pixel Format Constants
+ */
+#define GDISP_PIXELFORMAT_RGB565 565
+#define GDISP_PIXELFORMAT_RGB888 888
+#define GDISP_PIXELFORMAT_RGB444 444
+#define GDISP_PIXELFORMAT_RGB332 332
+#define GDISP_PIXELFORMAT_RGB666 666
+#define GDISP_PIXELFORMAT_CUSTOM 99999
+#define GDISP_PIXELFORMAT_ERROR 88888
+
+/*===========================================================================*/
+/* Error checks. */
+/*===========================================================================*/
+
+/**
+ * @name GDISP hardware accelerated support
+ * @{
+ */
+ /**
+ * @brief Hardware accelerated line drawing.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_LINES
+ #define GDISP_HARDWARE_LINES FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated screen clears.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_CLEARS
+ #define GDISP_HARDWARE_CLEARS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated rectangular fills.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_FILLS
+ #define GDISP_HARDWARE_FILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated fills from an image.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_BITFILLS
+ #define GDISP_HARDWARE_BITFILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated circles.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_CIRCLES
+ #define GDISP_HARDWARE_CIRCLES FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated filled circles.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_CIRCLEFILLS
+ #define GDISP_HARDWARE_CIRCLEFILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated ellipses.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_ELLIPSES
+ #define GDISP_HARDWARE_ELLIPSES FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated filled ellipses.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_ELLIPSEFILLS
+ #define GDISP_HARDWARE_ELLIPSEFILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated arc's.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_ARCS
+ #define GDISP_HARDWARE_ARCS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated filled arcs.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_ARCFILLS
+ #define GDISP_HARDWARE_ARCFILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated text drawing.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_TEXT
+ #define GDISP_HARDWARE_TEXT FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated text drawing with a filled background.
+ * @details If set to @p FALSE software emulation is used.
+ */
+ #ifndef GDISP_HARDWARE_TEXTFILLS
+ #define GDISP_HARDWARE_TEXTFILLS FALSE
+ #endif
+
+ /**
+ * @brief Hardware accelerated scrolling.
+ * @details If set to @p FALSE there is no support for scrolling.
+ */
+ #ifndef GDISP_HARDWARE_SCROLL
+ #define GDISP_HARDWARE_SCROLL FALSE
+ #endif
+
+ /**
+ * @brief Reading back of pixel values.
+ * @details If set to @p FALSE there is no support for pixel read-back.
+ */
+ #ifndef GDISP_HARDWARE_PIXELREAD
+ #define GDISP_HARDWARE_PIXELREAD FALSE
+ #endif
+
+ /**
+ * @brief The driver supports one or more control commands.
+ * @details If set to @p FALSE there is no support for control commands.
+ */
+ #ifndef GDISP_HARDWARE_CONTROL
+ #define GDISP_HARDWARE_CONTROL FALSE
+ #endif
+
+ /**
+ * @brief The driver supports a non-standard query.
+ * @details If set to @p FALSE there is no support for non-standard queries.
+ */
+ #ifndef GDISP_HARDWARE_QUERY
+ #define GDISP_HARDWARE_QUERY FALSE
+ #endif
+
+ /**
+ * @brief The driver supports a clipping in hardware.
+ * @details If set to @p FALSE there is no support for non-standard queries.
+ */
+ #ifndef GDISP_HARDWARE_CLIP
+ #define GDISP_HARDWARE_CLIP FALSE
+ #endif
+/** @} */
+
+/**
+ * @name GDISP software algorithm choices
+ * @{
+ */
+ /**
+ * @brief For filled text drawing, use a background fill and then draw
+ * the text instead of using a blit or direct pixel drawing.
+ * @details If set to @p TRUE background fill and then text draw is used.
+ * @note This is ignored if hardware accelerated text is supported.
+ */
+ #ifndef GDISP_SOFTWARE_TEXTFILLDRAW
+ #define GDISP_SOFTWARE_TEXTFILLDRAW FALSE
+ #endif
+
+ /**
+ * @brief For filled text drawing, when using a bitmap blit
+ * use a column by column buffer rather than a full character
+ * buffer to save memory at a small performance cost.
+ * @details If set to @p TRUE background fill one character column at a time.
+ * @note This is ignored if software text using blit is not being used.
+ */
+ #ifndef GDISP_SOFTWARE_TEXTBLITCOLUMN
+ #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE
+ #endif
+/** @} */
+
+/**
+ * @name GDISP pixel format choices
+ * @{
+ */
+ /**
+ * @brief The native pixel format for this device
+ * @note Should be set to one of the following:
+ * GDISP_PIXELFORMAT_RGB565
+ * GDISP_PIXELFORMAT_RGB888
+ * GDISP_PIXELFORMAT_RGB444
+ * GDISP_PIXELFORMAT_RGB332
+ * GDISP_PIXELFORMAT_RGB666
+ * GDISP_PIXELFORMAT_CUSTOM
+ * @note If you set GDISP_PIXELFORMAT_CUSTOM you need to also define
+ * color_t, RGB2COLOR(r,g,b), HTML2COLOR(h),
+ * RED_OF(c), GREEN_OF(c), BLUE_OF(c),
+ * COLOR(c) and MASKCOLOR.
+ */
+ #ifndef GDISP_PIXELFORMAT
+ #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_ERROR
+ #endif
+
+ /**
+ * @brief Do pixels require packing for a blit
+ * @note Is only valid for a pixel format that doesn't fill it's datatype. ie formats:
+ * GDISP_PIXELFORMAT_RGB888
+ * GDISP_PIXELFORMAT_RGB444
+ * GDISP_PIXELFORMAT_RGB666
+ * GDISP_PIXELFORMAT_CUSTOM
+ * @note If you use GDISP_PIXELFORMAT_CUSTOM and packed bit fills
+ * you need to also define @p gdispPackPixels(buf,cx,x,y,c)
+ * @note If you are using GDISP_HARDWARE_BITFILLS = FALSE then the pixel
+ * format must not be a packed format as the software blit does
+ * not support packed pixels
+ * @note Very few cases should actually require packed pixels as the low
+ * level driver can also pack on the fly as it is sending it
+ * to the graphics device.
+ */
+ #ifndef GDISP_PACKED_PIXELS
+ #define GDISP_PACKED_PIXELS FALSE
+ #endif
+
+ /**
+ * @brief Do lines of pixels require packing for a blit
+ * @note Ignored if GDISP_PACKED_PIXELS is FALSE
+ */
+ #ifndef GDISP_PACKED_LINES
+ #define GDISP_PACKED_LINES FALSE
+ #endif
+/** @} */
+
+/*===========================================================================*/
+/* Define the macro's for the various pixel formats */
+/*===========================================================================*/
+
+#if defined(__DOXYGEN__)
+ /**
+ * @brief The color of a pixel.
+ */
+ typedef uint16_t color_t;
+ /**
+ * @brief Convert a number (of any type) to a color_t.
+ * @details Masks any invalid bits in the color
+ */
+ #define COLOR(c) ((color_t)(c))
+ /**
+ * @brief Does the color_t type contain invalid bits that need masking.
+ */
+ #define MASKCOLOR FALSE
+ /**
+ * @brief Convert red, green, blue (each 0 to 255) into a color value.
+ */
+ #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3)))
+ /**
+ * @brief Convert a 6 digit HTML code (hex) into a color value.
+ */
+ #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3)))
+ /**
+ * @brief Extract the red component (0 to 255) of a color value.
+ */
+ #define RED_OF(c) (((c) & 0xF800)>>8)
+ /**
+ * @brief Extract the green component (0 to 255) of a color value.
+ */
+ #define GREEN_OF(c) (((c)&0x007E)>>3)
+ /**
+ * @brief Extract the blue component (0 to 255) of a color value.
+ */
+ #define BLUE_OF(c) (((c)&0x001F)<<3)
+
+#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
+ typedef uint16_t color_t;
+ #define COLOR(c) ((color_t)(c))
+ #define MASKCOLOR FALSE
+ #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3)))
+ #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3)))
+ #define RED_OF(c) (((c) & 0xF800)>>8)
+ #define GREEN_OF(c) (((c)&0x07E0)>>3)
+ #define BLUE_OF(c) (((c)&0x001F)<<3)
+
+#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+ typedef uint32_t color_t;
+ #define COLOR(c) ((color_t)(((c) & 0xFFFFFF)))
+ #define MASKCOLOR TRUE
+ #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFF)<<16) | (((g) & 0xFF) << 8) | ((b) & 0xFF)))
+ #define HTML2COLOR(h) ((color_t)(h))
+ #define RED_OF(c) (((c) & 0xFF0000)>>16)
+ #define GREEN_OF(c) (((c)&0x00FF00)>>8)
+ #define BLUE_OF(c) ((c)&0x0000FF)
+
+#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB444
+ typedef uint16_t color_t;
+ #define COLOR(c) ((color_t)(((c) & 0x0FFF)))
+ #define MASKCOLOR TRUE
+ #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF0)<<4) | ((g) & 0xF0) | (((b) & 0xF0)>>4)))
+ #define HTML2COLOR(h) ((color_t)((((h) & 0xF00000)>>12) | (((h) & 0x00F000)>>8) | (((h) & 0x0000F0)>>4)))
+ #define RED_OF(c) (((c) & 0x0F00)>>4)
+ #define GREEN_OF(c) ((c)&0x00F0)
+ #define BLUE_OF(c) (((c)&0x000F)<<4)
+
+#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB332
+ typedef uint8_t color_t;
+ #define COLOR(c) ((color_t)(c))
+ #define MASKCOLOR FALSE
+ #define RGB2COLOR(r,g,b) ((color_t)(((r) & 0xE0) | (((g) & 0xE0)>>3) | (((b) & 0xC0)>>6)))
+ #define HTML2COLOR(h) ((color_t)((((h) & 0xE00000)>>16) | (((h) & 0x00E000)>>11) | (((h) & 0x0000C0)>>6)))
+ #define RED_OF(c) ((c) & 0xE0)
+ #define GREEN_OF(c) (((c)&0x1C)<<3)
+ #define BLUE_OF(c) (((c)&0x03)<<6)
+
+#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB666
+ typedef uint32_t color_t;
+ #define COLOR(c) ((color_t)(((c) & 0x03FFFF)))
+ #define MASKCOLOR TRUE
+ #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFC)<<10) | (((g) & 0xFC)<<4) | (((b) & 0xFC)>>2)))
+ #define HTML2COLOR(h) ((color_t)((((h) & 0xFC0000)>>6) | (((h) & 0x00FC00)>>4) | (((h) & 0x0000FC)>>2)))
+ #define RED_OF(c) (((c) & 0x03F000)>>12)
+ #define GREEN_OF(c) (((c)&0x00FC00)>>8)
+ #define BLUE_OF(c) (((c)&0x00003F)<<2)
+
+#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM
+ #error "GDISP: No supported pixel format has been specified."
+#endif
+
+/* Verify information for packed pixels and define a non-packed pixel macro */
+#if !GDISP_PACKED_PIXELS
+ #define gdispPackPixels(buf,cx,x,y,c) { ((color_t *)(buf))[(y)*(cx)+(x)] = (c); }
+#elif !GDISP_HARDWARE_BITFILLS
+ #error "GDISP: packed pixel formats are only supported for hardware accelerated drivers."
+#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888 \
+ && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB444 \
+ && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB666 \
+ && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM
+ #error "GDISP: A packed pixel format has been specified for an unsupported pixel format."
+#endif
+
+#if GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL
+ #error "GDISP: Hardware scrolling is wanted but not supported."
+#endif
+
+#if GDISP_NEED_PIXELREAD && !GDISP_HARDWARE_PIXELREAD
+ #error "GDISP: Pixel read-back is wanted but not supported."
+#endif
+
+/*===========================================================================*/
+/* Driver types. */
+/*===========================================================================*/
+
+/**
+ * @brief The type of a pixel.
+ */
+typedef color_t pixel_t;
+/**
+ * @brief The type of a font.
+ */
+typedef const struct font *font_t;
+/**
+ * @brief Type for the screen orientation.
+ */
+typedef enum orientation {GDISP_ROTATE_0, GDISP_ROTATE_90, GDISP_ROTATE_180, GDISP_ROTATE_270} gdisp_orientation_t;
+/**
+ * @brief Type for the available power modes for the screen.
+ */
+typedef enum powermode {powerOff, powerSleep, powerDeepSleep, powerOn} gdisp_powermode_t;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifndef GDISP_LLD_VMT
+ /* Special magic stuff for the VMT driver */
+ #define GDISP_LLD_VMT(x) GDISP_LLD(x)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Core functions */
+ extern bool_t lld_gdisp_init(void);
+
+ /* Some of these functions will be implemented in software by the high level driver
+ depending on the GDISP_HARDWARE_XXX macros defined in gdisp_lld_config.h.
+ */
+
+ /* Drawing functions */
+ extern void GDISP_LLD_VMT(clear)(color_t color);
+ extern void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color);
+ extern void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
+ extern void GDISP_LLD_VMT(blitareaex)(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);
+ extern void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color);
+
+ /* Circular Drawing Functions */
+ #if GDISP_NEED_CIRCLE
+ extern void GDISP_LLD_VMT(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+ extern void GDISP_LLD_VMT(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color);
+ #endif
+
+ #if GDISP_NEED_ELLIPSE
+ extern void GDISP_LLD_VMT(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ extern void GDISP_LLD_VMT(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color);
+ #endif
+
+ /* Arc Drawing Functions */
+ #if GDISP_NEED_ARC
+ extern void GDISP_LLD_VMT(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ extern void GDISP_LLD_VMT(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
+ #endif
+
+ /* Text Rendering Functions */
+ #if GDISP_NEED_TEXT
+ extern void GDISP_LLD_VMT(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color);
+ extern void GDISP_LLD_VMT(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor);
+ #endif
+
+ /* Pixel readback */
+ #if GDISP_NEED_PIXELREAD
+ extern color_t GDISP_LLD_VMT(getpixelcolor)(coord_t x, coord_t y);
+ #endif
+
+ /* Scrolling Function - clears the area scrolled out */
+ #if GDISP_NEED_SCROLL
+ extern void GDISP_LLD_VMT(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor);
+ #endif
+
+ /* Set driver specific control */
+ #if GDISP_NEED_CONTROL
+ extern void GDISP_LLD_VMT(control)(unsigned what, void *value);
+ #endif
+
+ /* Query driver specific data */
+ extern void *GDISP_LLD_VMT(query)(unsigned what);
+
+ /* Clipping Functions */
+ #if GDISP_NEED_CLIP
+ extern void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy);
+ #endif
+
+ /* Messaging API */
+ #if GDISP_NEED_MSGAPI
+ #include "gdisp_lld_msgs.h"
+ extern void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg);
+ #endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_H */
+/** @} */
+
diff --git a/include/gdisp/lld/gdisp_lld_msgs.h b/include/gdisp/lld/gdisp_lld_msgs.h
new file mode 100644
index 00000000..6fe78567
--- /dev/null
+++ b/include/gdisp/lld/gdisp_lld_msgs.h
@@ -0,0 +1,193 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/lld/gdisp_lld_msgs.h
+ * @brief GDISP Graphic Driver subsystem low level driver message structures.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_MSGS_H
+#define _GDISP_LLD_MSGS_H
+
+/* This file describes the message API for gdisp_lld */
+#if GFX_USE_GDISP && GDISP_NEED_MSGAPI
+
+typedef enum gdisp_msgaction {
+ GDISP_LLD_MSG_NOP,
+ GDISP_LLD_MSG_INIT,
+ GDISP_LLD_MSG_CLEAR,
+ GDISP_LLD_MSG_DRAWPIXEL,
+ GDISP_LLD_MSG_FILLAREA,
+ GDISP_LLD_MSG_BLITAREA,
+ GDISP_LLD_MSG_DRAWLINE,
+ #if GDISP_NEED_CLIP
+ GDISP_LLD_MSG_SETCLIP,
+ #endif
+ #if GDISP_NEED_CIRCLE
+ GDISP_LLD_MSG_DRAWCIRCLE,
+ GDISP_LLD_MSG_FILLCIRCLE,
+ #endif
+ #if GDISP_NEED_ELLIPSE
+ GDISP_LLD_MSG_DRAWELLIPSE,
+ GDISP_LLD_MSG_FILLELLIPSE,
+ #endif
+ #if GDISP_NEED_ARC
+ GDISP_LLD_MSG_DRAWARC,
+ GDISP_LLD_MSG_FILLARC,
+ #endif
+ #if GDISP_NEED_TEXT
+ GDISP_LLD_MSG_DRAWCHAR,
+ GDISP_LLD_MSG_FILLCHAR,
+ #endif
+ #if GDISP_NEED_PIXELREAD
+ GDISP_LLD_MSG_GETPIXELCOLOR,
+ #endif
+ #if GDISP_NEED_SCROLL
+ GDISP_LLD_MSG_VERTICALSCROLL,
+ #endif
+ #if GDISP_NEED_CONTROL
+ GDISP_LLD_MSG_CONTROL,
+ #endif
+ GDISP_LLD_MSG_QUERY,
+} gdisp_msgaction_t;
+
+typedef union gdisp_lld_msg {
+ gdisp_msgaction_t action;
+ struct gdisp_lld_msg_init {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_INIT
+ } init;
+ struct gdisp_lld_msg_clear {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_CLEAR
+ color_t color;
+ } clear;
+ struct gdisp_lld_msg_drawpixel {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWPIXEL
+ coord_t x, y;
+ color_t color;
+ } drawpixel;
+ struct gdisp_lld_msg_fillarea {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLAREA
+ coord_t x, y;
+ coord_t cx, cy;
+ color_t color;
+ } fillarea;
+ struct gdisp_lld_msg_blitarea {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_BLITAREA
+ coord_t x, y;
+ coord_t cx, cy;
+ coord_t srcx, srcy;
+ coord_t srccx;
+ const pixel_t *buffer;
+ } blitarea;
+ struct gdisp_lld_msg_setclip {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_SETCLIP
+ coord_t x, y;
+ coord_t cx, cy;
+ } setclip;
+ struct gdisp_lld_msg_drawline {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWLINE
+ coord_t x0, y0;
+ coord_t x1, y1;
+ color_t color;
+ } drawline;
+ struct gdisp_lld_msg_drawcircle {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCIRCLE
+ coord_t x, y;
+ coord_t radius;
+ color_t color;
+ } drawcircle;
+ struct gdisp_lld_msg_fillcircle {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCIRCLE
+ coord_t x, y;
+ coord_t radius;
+ color_t color;
+ } fillcircle;
+ struct gdisp_lld_msg_drawellipse {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWELLIPSE
+ coord_t x, y;
+ coord_t a, b;
+ color_t color;
+ } drawellipse;
+ struct gdisp_lld_msg_fillellipse {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLELLIPSE
+ coord_t x, y;
+ coord_t a, b;
+ color_t color;
+ } fillellipse;
+ struct gdisp_lld_msg_drawarc {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWARC
+ coord_t x, y;
+ coord_t radius;
+ coord_t startangle, endangle;
+ color_t color;
+ } drawcircle;
+ struct gdisp_lld_msg_fillarc {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLARC
+ coord_t x, y;
+ coord_t radius;
+ coord_t startangle, endangle;
+ color_t color;
+ } fillcircle;
+ struct gdisp_lld_msg_drawchar {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCHAR
+ coord_t x, y;
+ char c;
+ font_t font;
+ color_t color;
+ } drawchar;
+ struct gdisp_lld_msg_fillchar {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCHAR
+ coord_t x, y;
+ char c;
+ font_t font;
+ color_t color;
+ color_t bgcolor;
+ } fillchar;
+ struct gdisp_lld_msg_getpixelcolor {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_GETPIXELCOLOR
+ coord_t x, y;
+ color_t result;
+ } getpixelcolor;
+ struct gdisp_lld_msg_verticalscroll {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_VERTICALSCROLL
+ coord_t x, y;
+ coord_t cx, cy;
+ int lines;
+ color_t bgcolor;
+ } verticalscroll;
+ struct gdisp_lld_msg_control {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_CONTROL
+ int what;
+ void * value;
+ } control;
+ struct gdisp_lld_msg_query {
+ gdisp_msgaction_t action; // GDISP_LLD_MSG_QUERY
+ int what;
+ void * result;
+ } query;
+} gdisp_lld_msg_t;
+
+#endif /* GFX_USE_GDISP && GDISP_NEED_MSGAPI */
+#endif /* _GDISP_LLD_MSGS_H */
+/** @} */
+
diff --git a/include/gdisp/options.h b/include/gdisp/options.h
new file mode 100644
index 00000000..2fedd34d
--- /dev/null
+++ b/include/gdisp/options.h
@@ -0,0 +1,241 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gdisp/options.h
+ * @brief GDISP sub-system options header file.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_OPTIONS_H
+#define _GDISP_OPTIONS_H
+
+/**
+ * @name GDISP Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Should all operations be clipped to the screen and colors validated.
+ * @details Defaults to TRUE.
+ * @note If this is FALSE, any operations that extend beyond the
+ * edge of the screen will have undefined results. Any
+ * out-of-range colors will produce undefined results.
+ * @note If defined then all low level and high level GDISP driver routines
+ * must check the validity of inputs and do something sensible
+ * if they are out of range. It doesn't have to be efficient,
+ * just valid.
+ */
+ #ifndef GDISP_NEED_VALIDATION
+ #define GDISP_NEED_VALIDATION TRUE
+ #endif
+ /**
+ * @brief Are clipping functions needed.
+ * @details Defaults to TRUE
+ */
+ #ifndef GDISP_NEED_CLIP
+ #define GDISP_NEED_CLIP TRUE
+ #endif
+ /**
+ * @brief Are text functions needed.
+ * @details Defaults to TRUE
+ */
+ #ifndef GDISP_NEED_TEXT
+ #define GDISP_NEED_TEXT TRUE
+ #endif
+ /**
+ * @brief Are circle functions needed.
+ * @details Defaults to TRUE
+ */
+ #ifndef GDISP_NEED_CIRCLE
+ #define GDISP_NEED_CIRCLE TRUE
+ #endif
+ /**
+ * @brief Are ellipse functions needed.
+ * @details Defaults to TRUE
+ */
+ #ifndef GDISP_NEED_ELLIPSE
+ #define GDISP_NEED_ELLIPSE TRUE
+ #endif
+ /**
+ * @brief Are arc functions needed.
+ * @details Defaults to FALSE
+ * @note Requires the maths library to be included in the link. ie -lm
+ */
+ #ifndef GDISP_NEED_ARC
+ #define GDISP_NEED_ARC FALSE
+ #endif
+ /**
+ * @brief Are scrolling functions needed.
+ * @details Defaults to FALSE
+ * @note This function must be supported by the low level GDISP driver
+ * you have included in your project. If it isn't, defining this
+ * option will cause a compile error.
+ */
+ #ifndef GDISP_NEED_SCROLL
+ #define GDISP_NEED_SCROLL FALSE
+ #endif
+ /**
+ * @brief Is the capability to read pixels back needed.
+ * @details Defaults to FALSE
+ * @note This function must be supported by the low level GDISP driver
+ * you have included in your project. If it isn't, defining this
+ * option will cause a compile error.
+ */
+ #ifndef GDISP_NEED_PIXELREAD
+ #define GDISP_NEED_PIXELREAD FALSE
+ #endif
+ /**
+ * @brief Control some aspect of the hardware operation.
+ * @details Defaults to FALSE
+ * @note This allows control of hardware specific features such as
+ * screen rotation, backlight levels, contrast etc
+ */
+ #ifndef GDISP_NEED_CONTROL
+ #define GDISP_NEED_CONTROL FALSE
+ #endif
+ /**
+ * @brief Is the messaging api interface required.
+ * @details Defaults to FALSE
+ */
+ #ifndef GDISP_NEED_MSGAPI
+ #define GDISP_NEED_MSGAPI FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GDISP Multi-Threading Options
+ * @{
+ */
+ /**
+ * @brief Do the drawing functions need to be thread-safe.
+ * @details Defaults to FALSE
+ * @note Both GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC make
+ * the gdisp API thread-safe.
+ * @note This is more efficient than GDISP_NEED_ASYNC as it only
+ * requires a context switch if something else is already
+ * drawing.
+ */
+ #ifndef GDISP_NEED_MULTITHREAD
+ #define GDISP_NEED_MULTITHREAD FALSE
+ #endif
+ /**
+ * @brief Use asynchronous calls (multi-thread safe).
+ * @details Defaults to FALSE
+ * @note Both GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC make
+ * the gdisp API thread-safe.
+ * @note Turning this on adds two context switches per transaction
+ * so it can significantly slow graphics drawing but it allows
+ * drawing operations to continue in the background.
+ */
+ #ifndef GDISP_NEED_ASYNC
+ #define GDISP_NEED_ASYNC FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GDISP Fonts
+ * @{
+ */
+ /**
+ * @brief Include the old global font variable definitions
+ * @details Defaults to FALSE
+ */
+ #ifndef GDISP_OLD_FONT_DEFINITIONS
+ #define GDISP_OLD_FONT_DEFINITIONS FALSE
+ #endif
+ /**
+ * @brief Predefined built in fonts
+ * @note Turning off the ones you are not using can save program size.
+ */
+ #ifndef GDISP_INCLUDE_FONT_SMALL
+ #define GDISP_INCLUDE_FONT_SMALL TRUE
+ #endif
+ #ifndef GDISP_INCLUDE_FONT_LARGER
+ #define GDISP_INCLUDE_FONT_LARGER TRUE
+ #endif
+ #ifndef GDISP_INCLUDE_FONT_UI1
+ #define GDISP_INCLUDE_FONT_UI1 TRUE
+ #endif
+ #ifndef GDISP_INCLUDE_FONT_UI2
+ #define GDISP_INCLUDE_FONT_UI2 TRUE
+ #endif
+ #ifndef GDISP_INCLUDE_FONT_LARGENUMBERS
+ #define GDISP_INCLUDE_FONT_LARGENUMBERS TRUE
+ #endif
+
+/**
+ * @}
+ *
+ * @name GDISP Optional Sizing Parameters
+ * @{
+ */
+ /**
+ * @brief The maximum height of a font.
+ * @details Either 16 or 32. Defaults to 16
+ * @note Setting this to 32 causes the font tables to take
+ * twice the internal program memory. Don't do it unless
+ * you realy must define an unscaled font larger than 16 bits high.
+ */
+ #ifndef GDISP_MAX_FONT_HEIGHT
+ #define GDISP_MAX_FONT_HEIGHT 16
+ #endif
+/**
+ * @}
+ *
+ * @name GDISP Optional Low Level Driver Defines
+ * @{
+ */
+ /**
+ * @brief Use a custom board definition even if a board definition exists.
+ * @details Defaults to FALSE
+ * @details If TRUE, add gdisp_lld_board.h to your project directory and customise it.
+ * @note Not all GDISP low level drivers currently use board definition files.
+ */
+ #ifndef GDISP_USE_CUSTOM_BOARD
+ #define GDISP_USE_CUSTOM_BOARD FALSE
+ #endif
+ /**
+ * @brief Set the screen height and width.
+ * @note Ignored by some low level GDISP drivers, optional for others.
+ * @note Where these values are allowed, a default is always provided be the low level driver.
+ * @note The list of GDISP low level drivers that allow these to be set are...
+ * WIN32, SSD1289, SSD1963, TestStub
+ */
+ /* #define GDISP_SCREEN_WIDTH nnnn */
+ /* #define GDISP_SCREEN_HEIGHT nnnn */
+ /**
+ * @brief Define which bus interface to use.
+ * @details Only required by the SSD1963 driver.
+ * @note This will be replaced eventually by board definition files
+ */
+ /* #define GDISP_USE_FSMC */
+ /* #define GDISP_USE_GPIO */
+ /**
+ * @brief Define which two drivers will be used by the VMT layer.
+ * @details Only required by the VMT driver.
+ */
+ /* #define GDISP_VMT_NAME1(x) x##YourDriver1 */
+ /* #define GDISP_VMT_NAME2(x) x##YourDriver2 */
+/** @} */
+
+#endif /* _GDISP_OPTIONS_H */
+/** @} */
diff --git a/include/gevent/gevent.h b/include/gevent/gevent.h
new file mode 100644
index 00000000..f9764336
--- /dev/null
+++ b/include/gevent/gevent.h
@@ -0,0 +1,250 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gevent/gevent.h
+ * @brief GEVENT GFX User Event subsystem header file.
+ *
+ * @addtogroup GEVENT
+ *
+ * @details GEVENT provides a simple to use but yet powerful event
+ * system.
+ *
+ * @pre GFX_USE_GEVENT must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+#ifndef _GEVENT_H
+#define _GEVENT_H
+
+#include "gfx.h"
+
+#if GFX_USE_GEVENT || defined(__DOXYGEN__)
+
+/* Data part of a static GListener initializer */
+#define _GLISTENER_DATA(name) { _SEMAPHORE_DATA(name.waitqueue, 0), _BSEMAPHORE_DATA(name.eventlock, FALSE), 0, 0, {0} }
+/* Static GListener initializer */
+#define GLISTENER_DECL(name) GListener name = _GLISTENER_DATA(name)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+typedef uint16_t GEventType;
+ #define GEVENT_NULL 0x0000 // Null Event - Do nothing
+ #define GEVENT_EXIT 0x0001 // The listener is being forced to exit (someone is destroying the listener)
+
+ /* Other event types are allocated in ranges in their respective include files */
+ #define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF
+ #define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF
+ #define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F
+ #define GEVENT_GAUDIN_FIRST 0x0340 // GAUDIN events range from 0x0340 to 0x037F
+ #define GEVENT_GAUDOUT_FIRST 0x0380 // GAUDOUT events range from 0x0380 to 0x03BF
+ #define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000
+
+// This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events.
+// The prerequisite is that the new status structure type starts with a field named 'type' of type 'GEventType'.
+// The total status structure also must not exceed GEVENT_MAXIMUM_SIZE bytes.
+// For example, this is used by GWIN button events, GINPUT data streams etc.
+typedef union GEvent_u {
+ GEventType type; // The type of this event
+ char pad[GEVENT_MAXIMUM_SIZE]; // This is here to allow static initialisation of GEventObject's in the application.
+ } GEvent;
+
+// A special callback function
+typedef void (*GEventCallbackFn)(void *param, GEvent *pe);
+
+// The Listener Object
+typedef struct GListener {
+ Semaphore waitqueue; // Private: Semaphore for the listener to wait on.
+ BinarySemaphore eventlock; // Private: Protect against more than one sources trying to use this event lock at the same time
+ GEventCallbackFn callback; // Private: Call back Function
+ void *param; // Private: Parameter for the callback function.
+ GEvent event; // Public: The event object into which the event information is stored.
+ } GListener;
+
+// The Source Object
+typedef struct GSource_t GSource, *GSourceHandle;
+
+// This structure is passed to a source to describe a contender listener for sending the current event.
+typedef struct GSourceListener_t {
+ GListener *pListener; // The listener
+ GSource *pSource; // The source
+ unsigned listenflags; // The flags the listener passed when the source was assigned to it.
+ unsigned srcflags; // For the source's exclusive use. Initialised as 0 for a new listener source assignment.
+ } GSourceListener;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* How to listen for events (act as a Listener)...
+ 1. Get handles for all the event sources you are interested in.
+ 2. Initialise a listener
+ 3. Attach sources to your listener.
+ - Sources can be attached or detached from a listener at any time.
+ - A source can be attached to more than one listener.
+ 4. Loop on getting listener events
+ 5. When finished detach all sources from the listener
+
+ How to create events (act as a Source)...
+ 1. Provide a funtion to the application that returns a GSourceHandle (which can be a pointer to whatever the source wants)
+ 2. Whenever a possible event occurs call geventGetSourceListener to get a pointer to a GSourceListener.
+ This will return NULL when there are no more listeners.
+ For each listener - check the flags to see if an event should be sent.
+ - use geventGetEvent() to get the event buffer supplied by the listener
+ and then call geventSendEvent to send the event.
+ - Note: geventGetEvent() may return FALSE to indicate the listener is currently not listening and
+ therefore no event should be sent. This situation enables the source to (optionally) flag
+ to the listener on its next wait that there have been missed events.
+ - Note: The GSourceListener pointer (and the GEvent buffer) are only valid between
+ the geventGetSourceListener call and either the geventSendEvent call or the next
+ geventGetSourceListener call.
+ - Note: All listeners must be processed for this event before anything else is processed.
+*/
+
+/*---------- Listener Functions --------------------------------------------*/
+
+/**
+ * @brief Create a Listener
+ * @details If insufficient resources are available it will either assert or return NULL
+ * depending on the value of GEVENT_ASSERT_NO_RESOURCE.
+ *
+ * @param[in] pl A listener
+ */
+void geventListenerInit(GListener *pl);
+
+/**
+ * @brief Attach a source to a listener
+ * @details Flags are interpreted by the source when generating events for each listener.
+ * If this source is already assigned to the listener it will update the flags.
+ * If insufficient resources are available it will either assert or return FALSE
+ * depending on the value of GEVENT_ASSERT_NO_RESOURCE.
+ *
+ * @param[in] pl The listener
+ * @param[in] gsh The source which has to be attached to the listener
+ * @param[in] flags The flags
+ *
+ * @return TRUE if succeeded, FALSE otherwise
+ */
+bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags);
+
+/**
+ * @brief Detach a source from a listener
+ * @details If gsh is NULL detach all sources from this listener and if there is still
+ * a thread waiting for events on this listener, it is sent the exit event.
+ *
+ * @param[in] pl The listener
+ * @param[in] gsh The source
+ */
+void geventDetachSource(GListener *pl, GSourceHandle gsh);
+
+/**
+ * @brief Wait for an event on a listener from an assigned source.
+ * @details The type of the event should be checked (pevent->type) and then pevent should
+ * be typecast to the actual event type if it needs to be processed.
+ * timeout specifies the time to wait in system ticks.
+ * TIME_INFINITE means no timeout - wait forever for an event.
+ * TIME_IMMEDIATE means return immediately
+ * @note The GEvent buffer is staticly allocated within the GListener so the event does not
+ * need to be dynamicly freed however it will get overwritten by the next call to
+ * this routine.
+ *
+ * @param[in] pl The listener
+ * @param[in] timeout The timeout
+ *
+ * @return NULL on timeout
+ */
+GEvent *geventEventWait(GListener *pl, systime_t timeout);
+
+/* @brief Register a callback for an event on a listener from an assigned source.
+ * @details The type of the event should be checked (pevent->type) and then pevent should be typecast to the
+ * actual event type if it needs to be processed.
+ *
+ * @params[in] pl The Listener
+ * @params[in] fn The function to call back
+ * @params[in] param A parameter to pass the callback function
+ *
+ * @note The GEvent buffer is valid only during the time of the callback. The callback MUST NOT save
+ * a pointer to the buffer for use outside the callback.
+ * @note An existing callback function is de-registered by passing a NULL for 'fn'. Any existing
+ * callback function is replaced. Any thread currently waiting using geventEventWait will be sent the exit event.
+ * @note Callbacks occur in a thread context but stack space must be kept to a minumum and
+ * the callback must process quickly as all other events are performed on a single thread.
+ * @note In the callback function you should never call ANY event functions using your own GListener handle
+ * as it WILL create a deadlock and lock the system up.
+ * @note Applications should not use this call - geventEventWait() is the preferred mechanism for an
+ * application. This call is provided for GUI objects that may not have their own thread.
+ */
+void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param);
+
+/*---------- Source Functions --------------------------------------------*/
+
+/**
+ * @brief Called by a source with a possible event to get a listener record.
+ * @details @p lastlr should be NULL on the first call and thereafter the result of the previous call.
+ *
+ * @param[in] gsh The source handler
+ * @param[in] lastlr The source listener
+ *
+ * @return NULL when there are no more listeners for this source
+ */
+GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr);
+
+/**
+ * @brief Get the event buffer from the GSourceListener.
+ * @details A NULL return allows the source to record (perhaps in glr->scrflags) that the listener
+ * has missed events. This can then be notified as part of the next event for the listener.
+ * The buffer can only be accessed untill the next call to geventGetSourceListener
+ * or geventSendEvent
+ *
+ * @param[in] psl The source listener
+ *
+ * @return NULL if the listener is not currently listening.
+ */
+GEvent *geventGetEventBuffer(GSourceListener *psl);
+
+/**
+ * @brief Called by a source to indicate the listener's event buffer has been filled.
+ * @details After calling this function the source must not reference in fields in the GSourceListener or the event buffer.
+ *
+ * @param[in] psl The source listener
+ */
+void geventSendEvent(GSourceListener *psl);
+
+/**
+ * @brief Detach any listener that has this source attached
+ *
+ * @param[in] gsh The source handle
+ */
+void geventDetachSourceListeners(GSourceHandle gsh);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GEVENT */
+
+#endif /* _GEVENT_H */
+/** @} */
+
diff --git a/include/gevent/options.h b/include/gevent/options.h
new file mode 100644
index 00000000..576233bf
--- /dev/null
+++ b/include/gevent/options.h
@@ -0,0 +1,68 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gevent/options.h
+ * @brief GEVENT sub-system options header file.
+ *
+ * @addtogroup GEVENT
+ * @{
+ */
+
+#ifndef _GEVENT_OPTIONS_H
+#define _GEVENT_OPTIONS_H
+
+/**
+ * @name GEVENT Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Should routines assert() if they run out of resources.
+ * @details Defaults to FALSE.
+ * @details If FALSE the application must be prepared to handle these
+ * failures.
+ */
+ #ifndef GEVENT_ASSERT_NO_RESOURCE
+ #define GEVENT_ASSERT_NO_RESOURCE FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GEVENT Optional Sizing Parameters
+ * @{
+ */
+ /**
+ * @brief Defines the maximum size of an event status variable.
+ * @details Defaults to 32 bytes
+ */
+ #ifndef GEVENT_MAXIMUM_SIZE
+ #define GEVENT_MAXIMUM_SIZE 32
+ #endif
+ /**
+ * @brief Defines the maximum Source/Listener pairs in the system.
+ * @details Defaults to 32
+ */
+ #ifndef GEVENT_MAX_SOURCE_LISTENERS
+ #define GEVENT_MAX_SOURCE_LISTENERS 32
+ #endif
+/** @} */
+
+#endif /* _GEVENT_OPTIONS_H */
+/** @} */
diff --git a/include/gfx.h b/include/gfx.h
new file mode 100644
index 00000000..552e3294
--- /dev/null
+++ b/include/gfx.h
@@ -0,0 +1,170 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @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 */
+/** @} */
diff --git a/include/gfx_rules.h b/include/gfx_rules.h
new file mode 100644
index 00000000..c132de54
--- /dev/null
+++ b/include/gfx_rules.h
@@ -0,0 +1,128 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gfx_rules.h
+ * @brief GFX system safety rules header file.
+ *
+ * @addtogroup GFX
+ * @{
+ */
+
+#ifndef _GFX_RULES_H
+#define _GFX_RULES_H
+
+/**
+ * Safety checks on all the defines.
+ *
+ * These are defined in the order of their inter-dependancies.
+ */
+
+#if GFX_USE_GWIN
+ #if !GFX_USE_GDISP
+ #error "GWIN: GFX_USE_GDISP must be TRUE when using GWIN"
+ #endif
+ #if !GDISP_NEED_CLIP
+ #warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
+ #endif
+ #if GWIN_NEED_BUTTON
+ #if !GDISP_NEED_TEXT
+ #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_BUTTON is TRUE."
+ #endif
+ #if !GFX_USE_GEVENT
+ #warning "GWIN: GFX_USE_GEVENT is required if GWIN_NEED_BUTTON is TRUE. It has been turned on for you."
+ #undef GFX_USE_GEVENT
+ #define GFX_USE_GEVENT TRUE
+ #endif
+ #if !GFX_USE_GINPUT || !(GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE)
+ #warning "GWIN: You have set GWIN_NEED_BUTTON to TRUE but no supported GINPUT (mouse/toggle) devices have been included"
+ #endif
+ #if !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
+ #warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_BUTTON is TRUE."
+ #warning "GWIN: GDISP_NEED_MULTITHREAD has been turned on for you."
+ #undef GDISP_NEED_MULTITHREAD
+ #define GDISP_NEED_MULTITHREAD TRUE
+ #endif
+ #endif
+ #if GWIN_NEED_CONSOLE
+ #if !GDISP_NEED_TEXT
+ #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
+ #endif
+ #endif
+ #if GWIN_NEED_GRAPH
+ #endif
+#endif
+
+#if GFX_USE_GINPUT
+ #if !GFX_USE_GEVENT
+ #warning "GINPUT: GFX_USE_GEVENT is required if GFX_USE_GINPUT is TRUE. It has been turned on for you."
+ #undef GFX_USE_GEVENT
+ #define GFX_USE_GEVENT TRUE
+ #endif
+ #if !GFX_USE_GTIMER
+ #warning "GINPUT: GFX_USE_GTIMER is required if GFX_USE_GINPUT is TRUE. It has been turned on for you."
+ #undef GFX_USE_GTIMER
+ #define GFX_USE_GTIMER TRUE
+ #endif
+#endif
+
+#if GFX_USE_GDISP
+ #if GDISP_NEED_MULTITHREAD && GDISP_NEED_ASYNC
+ #error "GDISP: Only one of GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC should be defined."
+ #endif
+ #if GDISP_NEED_ASYNC
+ #if !GDISP_NEED_MSGAPI
+ #warning "GDISP: Messaging API is required for Async Multi-Thread. It has been turned on for you."
+ #undef GDISP_NEED_MSGAPI
+ #define GDISP_NEED_MSGAPI TRUE
+ #endif
+ #endif
+#endif
+
+#if GFX_USE_TDISP
+#endif
+
+#if GFX_USE_GEVENT
+ #if !CH_USE_MUTEXES || !CH_USE_SEMAPHORES
+ #error "GEVENT: CH_USE_MUTEXES and CH_USE_SEMAPHORES must be defined in chconf.h"
+ #endif
+#endif
+
+#if GFX_USE_GTIMER
+ #if GFX_USE_GDISP && !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
+ #warning "GTIMER: Neither GDISP_NEED_MULTITHREAD nor GDISP_NEED_ASYNC has been specified."
+ #warning "GTIMER: Make sure you are not performing any GDISP/GWIN drawing operations in the timer callback!"
+ #endif
+#endif
+
+#if GFX_USE_GAUDIN
+#endif
+
+#if GFX_USE_GAUDOUT
+#endif
+
+#if GFX_USE_GADC
+#endif
+
+#if GFX_USE_GMISC
+#endif
+
+#endif /* _GFX_H */
+/** @} */
diff --git a/include/ginput/dial.h b/include/ginput/dial.h
new file mode 100644
index 00000000..5679685e
--- /dev/null
+++ b/include/ginput/dial.h
@@ -0,0 +1,123 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/dial.h
+ * @brief GINPUT GFX User Input subsystem header file.
+ *
+ * @defgroup Dial Dial
+ * @ingroup GINPUT
+ *
+ * @details A dial provides a powerful way to navigate through menus
+ * on a display.
+ *
+ * @pre GFX_USE_GINPUT must be set to TRUE in your gfxconf.h
+ * @pre GINPUT_NEED_DIAL must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+#ifndef _GINPUT_DIAL_H
+#define _GINPUT_DIAL_H
+
+#if GINPUT_NEED_DIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+// Event types for various ginput sources
+#define GEVENT_DIAL (GEVENT_GINPUT_FIRST+4)
+
+typedef struct GEventDial_t {
+ GEventType type; // The type of this event (GEVENT_DIAL)
+ uint16_t instance; // The dial instance
+ uint16_t value; // The dial value
+ } GEventDial;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * @brief Create a dial input instance
+ *
+ * @param[in] instance The ID of the dial input instance (from 0 to 9999)
+ *
+ * @return The soure handle of the created dial instance
+ */
+ GSourceHandle ginputGetDial(uint16_t instance);
+
+ /**
+ * @brief Reset the value back to the hardware default
+ *
+ * @param[in] instance The ID of the dial input instance
+ */
+ void ginputResetDialRange(uint16_t instance);
+
+ /**
+ * @brief Get the maximum value
+ * @details The readings are scaled to be 0 ... max-1.
+ * 0 means over the full uint16_t range.
+ *
+ * @param[in] instance The ID of the dial input instance
+ *
+ * @return The maximum value
+ */
+ uint16_t ginputGetDialRange(uint16_t instance);
+
+ /**
+ * @brief Set the maximum value
+ * @note This shouldn't be set higher that the hardwares possible maximum value
+ *
+ * @param[in] instance The ID of the dial input instance
+ * @param[in] max The maximum value to be set
+ */
+ void ginputSetDialRange(uint16_t instance, uint16_t max);
+
+ /**
+ * @brief Set the level change required before a dial even is generated (threshold)
+ * @note This is done after range scaling
+ *
+ * @param[in] instance The ID of the dial input instance
+ * @param[in] diff The amount of level changes
+ */
+ void ginputSetDialSensitivity(uint16_t instance, uint16_t diff);
+
+ /**
+ * @brief Get the current dial status
+ *
+ * @param[in] instance The ID of the dial input instance
+ * @param[in] pdial The dial event struct
+ *
+ * @return Returns FALSE on an error (eg invalid instance)
+ */
+ bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GINPUT_NEED_DIAL */
+
+#endif /* _GINPUT_DIAL_H */
+/** @} */
diff --git a/include/ginput/ginput.h b/include/ginput/ginput.h
new file mode 100644
index 00000000..59f7640c
--- /dev/null
+++ b/include/ginput/ginput.h
@@ -0,0 +1,61 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/ginput.h
+ * @brief GINPUT GFX User Input subsystem header file.
+ *
+ * @addtogroup GINPUT
+ *
+ * @details GINPUT provides an easy and common interface to use different input devices
+ * such as touchscreens and mices.
+ *
+ * @pre GFX_USE_GINPUT must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+#ifndef _GINPUT_H
+#define _GINPUT_H
+
+#include "gfx.h"
+
+#if GFX_USE_GINPUT || defined(__DOXYGEN__)
+
+/* How to use...
+
+ 1. Get source handles for all the inputs you are interested in.
+ - Attempting to get a handle for one instance of an input more than once will return the same handle
+ 2. Create a listener
+ 3. Assign inputs to your listener.
+ - Inputs can be assigned or released from a listener at any time.
+ - An input can be assigned to more than one listener.
+ 4. Loop on getting listener events
+ 5. When complete destroy the listener
+*/
+
+// Include various ginput types
+#include "ginput/mouse.h"
+#include "ginput/keyboard.h"
+#include "ginput/toggle.h"
+#include "ginput/dial.h"
+
+#endif /* GFX_USE_GINPUT */
+
+#endif /* _GINPUT_H */
+/** @} */
diff --git a/include/ginput/keyboard.h b/include/ginput/keyboard.h
new file mode 100644
index 00000000..9f5df32e
--- /dev/null
+++ b/include/ginput/keyboard.h
@@ -0,0 +1,140 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/keyboard.h
+ * @brief GINPUT GFX User Input subsystem header file.
+ *
+ * @defgroup Keyboard Keyboard
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_KEYBOARD_H
+#define _GINPUT_KEYBOARD_H
+
+#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+#define GINPUT_KEYBOARD_NUM_PORTS 1 // The total number of keyboard inputs
+
+// Event types for various ginput sources
+#define GEVENT_KEYBOARD (GEVENT_GINPUT_FIRST+2)
+
+typedef struct GEventKeyboard_t {
+ GEventType type; // The type of this event (GEVENT_KEYBOARD)
+ uint16_t instance; // The keyboard instance
+ char c; // The Ascii code for the current key press.
+ // The only possible values are 0(NUL), 8(BS), 9(TAB), 13(CR), 27(ESC), 32(SPACE) to 126(~), 127(DEL)
+ // 0 indicates an extended only key.
+ uint16_t code; // An extended keyboard code. Codes less than 128 match their ascii equivelent.
+ #define GKEY_NULL 0
+ #define GKEY_BACKSPACE 8
+ #define GKEY_TAB 9
+ #define GKEY_CR 13
+ #define GKEY_ESC 27
+ #define GKEY_SPACE 32
+ #define GKEY_DEL 127
+ #define GKEY_UP 0x0101
+ #define GKEY_DOWN 0x0102
+ #define GKEY_LEFT 0x0103
+ #define GKEY_RIGHT 0x0104
+ #define GKEY_HOME 0x0105
+ #define GKEY_END 0x0106
+ #define GKEY_PAGEUP 0x0107
+ #define GKEY_PAGEDOWN 0x0108
+ #define GKEY_INSERT 0x0109
+ #define GKEY_DELETE 0x010A
+ #define GKEY_SHIFT 0x0201
+ #define GKEY_CNTRL 0x0202
+ #define GKEY_ALT 0x0203
+ #define GKEY_WINKEY 0x0204
+ #define GKEY_RCLKEY 0x0205
+ #define GKEY_FNKEY 0x0206
+ #define GKEY_FN1 0x0301
+ #define GKEY_FN2 0x0302
+ #define GKEY_FN3 0x0303
+ #define GKEY_FN4 0x0304
+ #define GKEY_FN5 0x0305
+ #define GKEY_FN6 0x0306
+ #define GKEY_FN7 0x0307
+ #define GKEY_FN8 0x0308
+ #define GKEY_FN9 0x0309
+ #define GKEY_FN10 0x030A
+ #define GKEY_FN11 0x030B
+ #define GKEY_FN12 0x030C
+ uint16_t current_buttons; // A bit is set to indicate various meta status.
+ #define GMETA_KEY_DOWN 0x0001
+ #define GMETA_KEY_SHIFT 0x0002
+ #define GMETA_KEY_CNTRL 0x0004
+ #define GMETA_KEY_ALT 0x0008
+ #define GMETA_KEY_WINKEY 0x0010
+ #define GMETA_KEY_RCLKKEY 0x0020
+ #define GMETA_KEY_FN 0x0040
+ #define GMETA_KEY_MISSED_EVENT 0x8000
+ uint16_t last_buttons; // The value of current_buttons on the last event
+} GEventKeyboard;
+
+// Keyboard Listen Flags - passed to geventAddSourceToListener()
+#define GLISTEN_KEYREPEATS 0x0001 // Return key repeats (where the key is held down to get a repeat character)
+#define GLISTEN_KEYCODES 0x0002 // Return all key presses including extended code key presses (not just ascii codes)
+#define GLISTEN_KEYALL 0x0004 // Return keyup's, keydown's and everything in between (but not repeats unless GLISTEN_KEYREPEATS is set).
+#define GLISTEN_KEYSINGLE 0x8000 // Return only when one particular extended code key is pressed or released. The particular extended code is OR'd into this value
+ // eg. (GLISTEN_KEYSINGLE | GKEY_CR)
+ // No other flags may be set with this flag.
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * @brief Create a keyboard input instance
+ *
+ * @param[in] instance The ID of the keyboard input instance (from 0 to 9999)
+ *
+ * @return The source handle of the created input instance
+ */
+ GSourceHandle ginputGetKeyboard(uint16_t instance);
+
+ /**
+ * @brief Get the current keyboard status
+ *
+ * @param[in] instance The ID of the keyboard input instance
+ * @param[in] pkeyboard The keyboard event struct
+ *
+ * @return Returns FALSE on an error (eg invalid instance)
+ */
+ bool_t ginputGetKeyboardStatus(uint16_t instance, GEventKeyboard *pkeyboard);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GINPUT_NEED_KEYBOARD */
+
+#endif /* _GINPUT_KEYBOARD_H */
+/** @} */
+
diff --git a/include/ginput/lld/mouse.h b/include/ginput/lld/mouse.h
new file mode 100644
index 00000000..5f4ba52c
--- /dev/null
+++ b/include/ginput/lld/mouse.h
@@ -0,0 +1,121 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/lld/mouse.h
+ * @brief GINPUT LLD header file for mouse/touch drivers.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _LLD_GINPUT_MOUSE_H
+#define _LLD_GINPUT_MOUSE_H
+
+#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
+
+#include "ginput_lld_mouse_config.h"
+
+// GEVENT_MOUSE or GEVENT_TOUCH - What type of device is this.
+#ifndef GINPUT_MOUSE_EVENT_TYPE
+ #define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE
+#endif
+
+// TRUE/FALSE - Does the mouse/touch driver require calibration?
+#ifndef GINPUT_MOUSE_NEED_CALIBRATION
+ #define GINPUT_MOUSE_NEED_CALIBRATION FALSE
+#endif
+
+// TRUE/FALSE - Can the mouse/touch driver itself save calibration data?
+#ifndef GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+#endif
+
+// n or -1 - n means to test calibration result (+/- pixels), -1 means not to.
+#ifndef GINPUT_MOUSE_MAX_CALIBRATION_ERROR
+ #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1
+#endif
+
+// n - How many times to read (and average) per poll
+#ifndef GINPUT_MOUSE_READ_CYCLES
+ #define GINPUT_MOUSE_READ_CYCLES 1
+#endif
+
+// n - Millisecs between poll's
+#ifndef GINPUT_MOUSE_POLL_PERIOD
+ #define GINPUT_MOUSE_POLL_PERIOD 25
+#endif
+
+// n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels)
+#ifndef GINPUT_MOUSE_MAX_CLICK_JITTER
+ #define GINPUT_MOUSE_MAX_CLICK_JITTER 1
+#endif
+
+// n - Movement allowed without discarding the MOVE event (+/- pixels)
+#ifndef GINPUT_MOUSE_MAX_MOVE_JITTER
+ #define GINPUT_MOUSE_MAX_MOVE_JITTER 0
+#endif
+
+// ms - Millisecs seperating a CLICK from a CXTCLICK
+#ifndef GINPUT_MOUSE_CLICK_TIME
+ #define GINPUT_MOUSE_CLICK_TIME 700
+#endif
+
+
+typedef struct MouseReading_t {
+ coord_t x, y, z;
+ uint16_t buttons;
+ } MouseReading;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void ginput_lld_mouse_init(void);
+ void ginput_lld_mouse_get_reading(MouseReading *pt);
+
+ #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ const char *ginput_lld_mouse_calibration_load(uint16_t instance);
+ void ginput_lld_mouse_calibration_save(uint16_t instance, const uint8_t *calbuf, size_t sz);
+ #endif
+
+ /* This routine is provided to low level drivers to wakeup a value read from a thread context.
+ * Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
+ */
+ void ginputMouseWakeup(void);
+
+ /* This routine is provided to low level drivers to wakeup a value read from an ISR
+ * Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
+ */
+ void ginputMouseWakeupI(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH */
+
+#endif /* _LLD_GINPUT_MOUSE_H */
+/** @} */
+
diff --git a/include/ginput/lld/toggle.h b/include/ginput/lld/toggle.h
new file mode 100644
index 00000000..a75a670f
--- /dev/null
+++ b/include/ginput/lld/toggle.h
@@ -0,0 +1,73 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/lld/toggle.h
+ * @brief GINPUT header file for toggle drivers.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _LLD_GINPUT_TOGGLE_H
+#define _LLD_GINPUT_TOGGLE_H
+
+#if GINPUT_NEED_TOGGLE || defined(__DOXYGEN__)
+
+// Describes how the toggle bits are obtained
+typedef struct GToggleConfig_t {
+ void *id;
+ unsigned mask;
+ unsigned invert;
+ iomode_t mode;
+} GToggleConfig;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
+
+ void ginput_lld_toggle_init(const GToggleConfig *ptc);
+ unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc);
+
+ /* This routine is provided to low level drivers to wakeup a value read from a thread context.
+ * Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE
+ */
+ void ginputToggleWakeup(void);
+
+ /* This routine is provided to low level drivers to wakeup a value read from an ISR
+ * Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE
+ */
+ void ginputToggleWakeupI(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */
+
+#endif /* _LLD_GINPUT_TOGGLE_H */
+/** @} */
+
diff --git a/include/ginput/mouse.h b/include/ginput/mouse.h
new file mode 100644
index 00000000..5385ff17
--- /dev/null
+++ b/include/ginput/mouse.h
@@ -0,0 +1,171 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/mouse.h
+ * @brief GINPUT GFX User Input subsystem header file for mouse and touch.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ *
+ * @details GINPUT allows it to easily interface touchscreens and mices to
+ * your application.
+ *
+ * @pre GFX_USE_GINPUT must be set to TRUE in your gfxconf.h
+ * @pre GINPUT_NEED_MOUSE must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GINPUT_MOUSE_H
+#define _GINPUT_MOUSE_H
+
+#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/* This type definition is also used by touch */
+typedef struct GEventMouse_t {
+ GEventType type; // The type of this event (GEVENT_MOUSE or GEVENT_TOUCH)
+ uint16_t instance; // The mouse/touch instance
+ coord_t x, y, z; // The position of the mouse.
+ // - For touch devices, Z is the current pressure if supported (otherwise 0)
+ // - For mice, Z is the 3rd dimension if supported (otherwise 0)
+ uint16_t current_buttons; // A bit is set if the button is down.
+ // - For touch only bit 0 is relevant
+ // - For mice the order of the buttons is (from 0 to n) left, right, middle, any other buttons
+ // - Bit 15 being set indicates that an important mouse event has been missed.
+ #define GINPUT_MOUSE_BTN_LEFT 0x0001
+ #define GINPUT_MOUSE_BTN_RIGHT 0x0002
+ #define GINPUT_MOUSE_BTN_MIDDLE 0x0004
+ #define GINPUT_MOUSE_BTN_4 0x0008
+ #define GINPUT_MISSED_MOUSE_EVENT 0x8000
+ #define GINPUT_TOUCH_PRESSED GINPUT_MOUSE_BTN_LEFT
+ uint16_t last_buttons; // The value of current_buttons on the last event
+ enum GMouseMeta_e {
+ GMETA_NONE = 0, // There is no meta event currently happening
+ GMETA_MOUSE_DOWN = 1, // Button 0 has just gone down
+ GMETA_MOUSE_UP = 2, // Button 0 has just gone up
+ GMETA_MOUSE_CLICK = 4, // Button 0 has just gone through a short down - up cycle
+ GMETA_MOUSE_CXTCLICK = 8 // For mice - The right button has just been depressed
+ // For touch - a long press has just occurred
+ } meta;
+ } GEventMouse;
+
+// Mouse/Touch Listen Flags - passed to geventAddSourceToListener()
+#define GLISTEN_MOUSEMETA 0x0001 // Create events for meta events such as CLICK and CXTCLICK
+#define GLISTEN_MOUSEDOWNMOVES 0x0002 // Creates mouse move events when the primary mouse button is down (touch is on the surface)
+#define GLISTEN_MOUSEUPMOVES 0x0004 // Creates mouse move events when the primary mouse button is up (touch is off the surface - if the hardware allows).
+#define GLISTEN_MOUSENOFILTER 0x0008 // Don't filter out mouse moves where the position hasn't changed.
+#define GLISTEN_TOUCHMETA GLISTEN_MOUSEMETA
+#define GLISTEN_TOUCHDOWNMOVES GLISTEN_MOUSEDOWNMOVES
+#define GLISTEN_TOUCHUPMOVES GLISTEN_MOUSEUPMOVES
+#define GLISTEN_TOUCHNOFILTER GLISTEN_MOUSENOFILTER
+
+#define GINPUT_MOUSE_NUM_PORTS 1 // The total number of mouse/touch inputs supported
+
+// Event types for the mouse ginput source
+#define GEVENT_MOUSE (GEVENT_GINPUT_FIRST+0)
+#define GEVENT_TOUCH (GEVENT_GINPUT_FIRST+1)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * @brief Creates an instance of a mouse and returns the Source handler
+ * @note hack: if the instance is 9999, no calibration will be performed!
+ *
+ * @param[in] instance The ID of the mouse input instance (from 0 to 9999)
+ *
+ * @return The source handle of the created instance
+ */
+ GSourceHandle ginputGetMouse(uint16_t instance);
+
+ /**
+ * @brief Get the current mouse position and button status
+ * @note Unlinke a listener event, this status cannot record meta events such as
+ * "CLICK".
+ *
+ * @param[in] instance The ID of the mouse input instance
+ * @param[in] pmouse The mouse event
+ *
+ * @return FALSE on an error (eg. invalid instance)
+ */
+ bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pmouse);
+
+ /**
+ * @brief Performs a calibration
+ *
+ * @param[in] instance The ID of the mouse input instance
+ *
+ * @return FALSE if the driver dosen't support a calibration of if the handle is invalid
+ */
+ bool_t ginputCalibrateMouse(uint16_t instance);
+
+ /* Set the routines to save and fetch calibration data.
+ * This function should be called before first calling ginputGetMouse() for a particular instance
+ * as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it.
+ * If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.
+ * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
+ */
+ typedef void (*GMouseCalibrationSaveRoutine)(uint16_t instance, const uint8_t *calbuf, size_t sz); // Save calibration data
+ typedef const char * (*GMouseCalibrationLoadRoutine)(uint16_t instance); // Load calibration data (returns NULL if not data saved)
+
+ /**
+ * @brief Set the routines to store and restore calibration data
+ *
+ * @details This function should be called before first calling ginputGetMouse() for a particular instance
+ * as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it.
+ * If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the
+ * data is has already obtained.
+ * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
+ *
+ * @param[in] instance The ID of the mouse input instance
+ * @param[in] fnsave The routine to save the data
+ * @param[in] fnload The routine to restore the data
+ * @param[in] requireFree ToDo
+ */
+ void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree);
+
+ /**
+ * @brief Test if a particular mouse/touch instance requires routines to save it's alibration data
+ * @note Not implemented yet
+ *
+ * @param[in] instance The ID of the mouse input instance
+ *
+ * @return TRUE if needed
+ */
+ bool_t ginputRequireMouseCalibrationStorage(uint16_t instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GINPUT_NEED_MOUSE */
+
+#endif /* _GINPUT_MOUSE_H */
+/** @} */
+
diff --git a/include/ginput/options.h b/include/ginput/options.h
new file mode 100644
index 00000000..e7635fb5
--- /dev/null
+++ b/include/ginput/options.h
@@ -0,0 +1,127 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/ginput/options.h
+ * @brief GINPUT sub-system options header file.
+ *
+ * @addtogroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_OPTIONS_H
+#define _GINPUT_OPTIONS_H
+
+/**
+ * @name GINPUT Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Should mouse/touch functions be included.
+ * @details Defaults to FALSE
+ * @note Also add the a mouse/touch hardware driver to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk
+ */
+ #ifndef GINPUT_NEED_MOUSE
+ #define GINPUT_NEED_MOUSE FALSE
+ #endif
+ /**
+ * @brief Should keyboard functions be included.
+ * @details Defaults to FALSE
+ * @note Also add the a keyboard hardware driver to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/ginput/keyboard/XXXX/ginput_lld.mk
+ */
+ #ifndef GINPUT_NEED_KEYBOARD
+ #define GINPUT_NEED_KEYBOARD FALSE
+ #endif
+ /**
+ * @brief Should hardware toggle/switch/button functions be included.
+ * @details Defaults to FALSE
+ * @note Also add the a toggle hardware driver to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
+ */
+ #ifndef GINPUT_NEED_TOGGLE
+ #define GINPUT_NEED_TOGGLE FALSE
+ #endif
+ /**
+ * @brief Should analog dial functions be included.
+ * @details Defaults to FALSE
+ * @note Also add the a dial hardware driver to your makefile.
+ * Eg.
+ * include $(GFXLIB)/drivers/ginput/dial/analog/ginput_lld.mk
+ */
+ #ifndef GINPUT_NEED_DIAL
+ #define GINPUT_NEED_DIAL FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GINPUT Optional Sizing Parameters
+ * @{
+ */
+/**
+ * @}
+ *
+ * @name GINPUT Optional Low Level Driver Defines
+ * @{
+ */
+ /**
+ * @brief Use a custom board definition for the mouse/touch driver even if a board definition exists.
+ * @details Defaults to FALSE
+ * @details If TRUE, add ginput_lld_mouse_board.h to your project directory and customise it.
+ * @note Not all GINPUT mouse/touch low level drivers use board definition files.
+ */
+ #ifndef GINPUT_MOUSE_USE_CUSTOM_BOARD
+ #define GINPUT_MOUSE_USE_CUSTOM_BOARD FALSE
+ #endif
+ /**
+ * @brief Use a custom board definition for the keyboard driver even if a board definition exists.
+ * @details Defaults to FALSE
+ * @details If TRUE, add ginput_lld_keyboard_board.h to your project directory and customise it.
+ * @note Not all GINPUT keyboard low level drivers use board definition files.
+ */
+ #ifndef GINPUT_KEYBOARD_USE_CUSTOM_BOARD
+ #define GINPUT_KEYBOARD_USE_CUSTOM_BOARD FALSE
+ #endif
+ /**
+ * @brief Use a custom board definition for the toggle driver even if a board definition exists.
+ * @details Defaults to FALSE
+ * @details If TRUE, add ginput_lld_toggle_board.h to your project directory and customise it.
+ * @note Not all GINPUT toggle low level drivers use board definition files.
+ */
+ #ifndef GINPUT_TOGGLE_USE_CUSTOM_BOARD
+ #define GINPUT_TOGGLE_USE_CUSTOM_BOARD FALSE
+ #endif
+ /**
+ * @brief Use a custom board definition for the dial driver even if a board definition exists.
+ * @details Defaults to FALSE
+ * @details If TRUE, add ginput_lld_dial_board.h to your project directory and customise it.
+ * @note Not all GINPUT dial low level drivers use board definition files.
+ */
+ #ifndef GINPUT_DIAL_USE_CUSTOM_BOARD
+ #define GINPUT_DIAL_USE_CUSTOM_BOARD FALSE
+ #endif
+/** @} */
+
+#endif /* _GINPUT_OPTIONS_H */
+/** @} */
diff --git a/include/ginput/toggle.h b/include/ginput/toggle.h
new file mode 100644
index 00000000..bec4ed32
--- /dev/null
+++ b/include/ginput/toggle.h
@@ -0,0 +1,112 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/ginput/toggle.h
+ * @brief GINPUT GFX User Input subsystem header file.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ *
+ * @details GINPUT allows it to interface toggle buttons easily to your
+ * application.
+ *
+ * @pre GFX_USE_GINPUT must be set to TRUE in your gfxconf.h
+ * @pre GINPUT_NEED_TOGGLE must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GINPUT_TOGGLE_H
+#define _GINPUT_TOGGLE_H
+
+#if GINPUT_NEED_TOGGLE || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Low Level Driver details and error checks. */
+/*===========================================================================*/
+
+// Get the hardware definitions - Number of instances etc.
+#include "ginput_lld_toggle_config.h"
+
+#ifndef GINPUT_TOGGLE_POLL_PERIOD
+ #define GINPUT_TOGGLE_POLL_PERIOD 200
+#endif
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+// Event types for various ginput sources
+#define GEVENT_TOGGLE (GEVENT_GINPUT_FIRST+3)
+
+typedef struct GEventToggle_t {
+ GEventType type; // The type of this event (GEVENT_TOGGLE)
+ uint16_t instance; // The toggle instance
+ bool_t on; // True if the toggle/button is on
+ } GEventToggle;
+
+// Toggle Listen Flags - passed to geventAddSourceToListener()
+#define GLISTEN_TOGGLE_ON 0x0001 // Return an event when the toggle turns on
+#define GLISTEN_TOGGLE_OFF 0x0002 // Return an event when the toggle turns off
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * @brief Create a toggle input instance
+ *
+ * @param[in] instance The ID of the toggle input instance (from 0 to 9999)
+ *
+ * @return The source handle of the created instance
+ */
+ GSourceHandle ginputGetToggle(uint16_t instance);
+
+ /**
+ * @brief Can be used to invert the sense of a toggle
+ *
+ * @param[in] instance The ID of the toggle input instance
+ * @param[in] invert If TRUE, will be inverted
+ */
+ void ginputInvertToggle(uint16_t instance, bool_t invert);
+
+ /**
+ * @brief Get the current toggle status
+ *
+ * @param[in] instance The ID of the toggle input instance
+ * @param[in] ptoggle The toggle event struct
+ *
+ * @return Returns FALSE on an error (eg invalid instance)
+ */
+ bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GINPUT_NEED_TOGGLE */
+
+#endif /* _GINPUT_TOGGLE_H */
+/** @} */
+
diff --git a/include/gmisc/gmisc.h b/include/gmisc/gmisc.h
new file mode 100644
index 00000000..c68e5ca2
--- /dev/null
+++ b/include/gmisc/gmisc.h
@@ -0,0 +1,106 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @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 */
+/** @} */
+
diff --git a/include/gmisc/options.h b/include/gmisc/options.h
new file mode 100644
index 00000000..d526ff84
--- /dev/null
+++ b/include/gmisc/options.h
@@ -0,0 +1,52 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gmisc/options.h
+ * @brief GMISC - Miscellaneous Routines options header file.
+ *
+ * @addtogroup GMISC
+ * @{
+ */
+
+#ifndef _GMISC_OPTIONS_H
+#define _GMISC_OPTIONS_H
+
+/**
+ * @name GMISC Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Include array operation functions
+ * @details Defaults to FALSE
+ */
+ #ifndef GMISC_NEED_ARRAYOPS
+ #define GMISC_NEED_ARRAYOPS FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GMISC Optional Sizing Parameters
+ * @{
+ */
+/** @} */
+
+#endif /* _GMISC_OPTIONS_H */
+/** @} */
diff --git a/include/gtimer/gtimer.h b/include/gtimer/gtimer.h
new file mode 100644
index 00000000..95ab6ba7
--- /dev/null
+++ b/include/gtimer/gtimer.h
@@ -0,0 +1,182 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gtimer/gtimer.h
+ * @brief GTIMER GFX User Timer subsystem header file.
+ *
+ * @addtogroup GTIMER
+ *
+ * @details The reason why ChibiOS/GFX has it's own timer abstraction is because
+ * virtual timers provided by ChibiOS/RT are interrupt context only.
+ * While great for what they are designed for, they make coding of the input
+ * drivers much more complex.
+ * For non-performance critical drivers like these input drivers, it would also
+ * hog an in-ordinate amount of critical (interrupt locked) system time.
+ * This contrary to the goals of a real-time operating system. So a user-land
+ * (thread based) timer mechanism is also required.
+ *
+ * @pre GFX_USE_GTIMER must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GTIMER_H
+#define _GTIMER_H
+
+#include "gfx.h"
+
+#if GFX_USE_GTIMER || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/* Data part of a static GTimer initialiser */
+#define _GTIMER_DATA() {0,0,0,0,0,0,0}
+
+/* Static GTimer initialiser */
+#define GTIMER_DECL(name) GTimer name = _GTIMER_DATA()
+
+/* A callback function (executed in a thread context) */
+typedef void (*GTimerFunction)(void *param);
+
+/**
+ * @brief A GTimer structure
+ */
+typedef struct GTimer_t {
+ GTimerFunction fn;
+ void *param;
+ systime_t when;
+ systime_t period;
+ uint16_t flags;
+ struct GTimer_t *next;
+ struct GTimer_t *prev;
+} GTimer;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise a timer.
+ *
+ * @param[in] pt pointer to a GTimer structure
+ *
+ * @api
+ */
+void gtimerInit(GTimer *pt);
+
+/**
+ * @brief Set a timer going or alter its properties if it is already going.
+ *
+ * @param[in] pt Pointer to a GTimer structure
+ * @param[in] fn The callback function
+ * @param[in] param The parameter to pass to the callback function
+ * @param[in] periodic Is the timer a periodic timer? FALSE is a once-only timer.
+ * @param[in] millisec The timer period. The following special values are allowed:
+ * TIME_IMMEDIATE causes the callback function to be called asap.
+ * A periodic timer with this value will fire once only.
+ * TIME_INFINITE never timeout (unless triggered by gtimerJab or gtimerJabI)
+ *
+ * @note If the timer is already active its properties are updated with the new parameters.
+ * The current period will be immediately canceled (without the callback function being
+ * called) and the timer will be restart with the new timer properties.
+ * @note The callback function should be careful not to over-run the thread stack.
+ * Define a new value for the macro GTIME_THREAD_STACK_SIZE if you want to
+ * change the default size.
+ * @note The callback function should return as quickly as possible as all
+ * timer callbacks are performed by a single thread. If a callback function
+ * takes too long it could affect the timer response for other timers.
+ * @note A timer callback function is not a replacement for a dedicated thread if the
+ * function wants to perform computationally expensive stuff.
+ * @note As the callback function is called on GTIMER's thread, the function must make sure it uses
+ * appropriate synchronisation controls such as semaphores or mutexes around any data
+ * structures it shares with other threads such as the main application thread.
+ *
+ * @api
+ */
+void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, systime_t millisec);
+
+/**
+ * @brief Stop a timer (periodic or otherwise)
+ *
+ * @param[in] pt Pointer to a GTimer structure
+ *
+ * @note If the timer is not active this does nothing.
+ *
+ * @api
+ */
+void gtimerStop(GTimer *pt);
+
+/**
+ * @brief Test if a timer is currently active
+ *
+ * @param[in] pt Pointer to a GTimer structure
+ *
+ * @return TRUE if active, FALSE otherwise
+ *
+ * @api
+ */
+bool_t gtimerIsActive(GTimer *pt);
+
+/**
+ * @brief Jab a timer causing the current period to immediate expire
+ * @details The callback function will be called as soon as possible.
+ *
+ * @pre Use from a normal thread context.
+ *
+ * @param[in] pt Pointer to a GTimer structure
+ *
+ * @note If the timer is not active this does nothing.
+ * @note Repeated Jabs before the callback function actually happens are ignored.
+ *
+ * @api
+ */
+void gtimerJab(GTimer *pt);
+
+/**
+ * @brief Jab a timer causing the current period to immediate expire
+ * @details The callback function will be called as soon as possible.
+ *
+ * @pre Use from an interrupt routine context.
+ *
+ * @param[in] pt Pointer to a GTimer structure
+ *
+ * @note If the timer is not active this does nothing.
+ * @note Repeated Jabs before the callback function actually happens are ignored.
+ *
+ * @iclass
+ * @api
+ */
+void gtimerJabI(GTimer *pt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GTIMER */
+
+#endif /* _GTIMER_H */
+/** @} */
+
diff --git a/include/gtimer/options.h b/include/gtimer/options.h
new file mode 100644
index 00000000..e0770627
--- /dev/null
+++ b/include/gtimer/options.h
@@ -0,0 +1,52 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gtimer/options.h
+ * @brief GTIMER sub-system options header file.
+ *
+ * @addtogroup GTIMER
+ * @{
+ */
+
+#ifndef _GTIMER_OPTIONS_H
+#define _GTIMER_OPTIONS_H
+
+/**
+ * @name GTIMER Functionality to be included
+ * @{
+ */
+/**
+ * @}
+ *
+ * @name GTIMER Optional Sizing Parameters
+ * @{
+ */
+ /**
+ * @brief Defines the size of the timer threads work area (stack+structures).
+ * @details Defaults to 512 bytes
+ */
+ #ifndef GTIMER_THREAD_WORKAREA_SIZE
+ #define GTIMER_THREAD_WORKAREA_SIZE 512
+ #endif
+/** @} */
+
+#endif /* _GTIMER_OPTIONS_H */
+/** @} */
diff --git a/include/gwin/button.h b/include/gwin/button.h
new file mode 100644
index 00000000..ffec858b
--- /dev/null
+++ b/include/gwin/button.h
@@ -0,0 +1,194 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gwin/button.h
+ * @brief GWIN Graphic window subsystem header file.
+ *
+ * @defgroup Button Button
+ * @ingroup GWIN
+ *
+ * @details GWIN allows it to easily create buttons with different styles
+ * and check for different meta states such as: PRESSED, CLICKED,
+ * RELEASED etc.
+ *
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ * @pre GWIN_NEED_BUTTON must be set to TRUE in your gfxconf.h
+ * @{
+ */
+
+#ifndef _GWIN_BUTTON_H
+#define _GWIN_BUTTON_H
+
+#if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define GW_BUTTON 0x0002
+#define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+typedef struct GEventGWinButton_t {
+ GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
+ GHandle button; // The button that has been depressed (actually triggered on release)
+} GEventGWinButton;
+
+// There are currently no GEventGWinButton listening flags - use 0
+
+typedef enum GButtonShape_e {
+ GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE
+} GButtonShape;
+
+typedef struct GButtonStyle_t {
+ GButtonShape shape;
+ color_t color_up_edge;
+ color_t color_up_fill;
+ color_t color_up_txt;
+ color_t color_dn_edge;
+ color_t color_dn_fill;
+ color_t color_dn_txt;
+} GButtonStyle;
+
+typedef enum GButtonType_e {
+ GBTN_NORMAL, GBTN_TOGGLE
+} GButtonType;
+
+typedef enum GButtonState_e {
+ GBTN_UP, GBTN_DOWN
+} GButtonState;
+
+// A button window
+typedef struct GButtonObject_t {
+ GWindowObject gwin;
+
+ GButtonStyle style;
+ GButtonState state;
+ GButtonType type;
+ const char * txt;
+ GListener listener;
+} GButtonObject;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a button window.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] gb The GButtonObject 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
+ * @param[in] font The font to use
+ * @param[in] type The type of button
+ * @note The drawing color gets set to White and the background drawing color to Black.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ * @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text.
+ *
+ * @api
+ */
+GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type);
+
+/**
+ * @brief Set the style of a button.
+ * @details The button style is defined by its shape and colours.
+ *
+ * @param[in] gh The window handle (must be a button window)
+ * @param[in] style The button style to set.
+ * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style
+ *
+ * @api
+ */
+void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style);
+
+/**
+ * @brief Set the text of a button.
+ *
+ * @param[in] gh The window handle (must be a button window)
+ * @param[in] txt The button text to set. This must be a constant string unless useAlloc is set.
+ * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
+ * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text.
+ *
+ * @api
+ */
+void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
+
+/**
+ * @brief Redraw the button.
+ *
+ * @param[in] gh The window handle (must be a button window)
+ *
+ * @api
+ */
+void gwinButtonDraw(GHandle gh);
+
+#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
+
+/**
+ * @brief Get the source handle of a button
+ * @details Get the source handle of a button so the application can listen for events
+ *
+ * @param[in] gh The Hanlde
+ */
+#define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
+
+#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
+ /**
+ * @brief Attach a mouse source
+ * @details Attach a mouse source to a given button
+ *
+ * @param[in] gh The button handle
+ * @param[in] gsh The source handle
+ *
+ * @return
+ */
+ bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh);
+#endif
+
+#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
+ /**
+ * @brief Attach a toggle source
+ * @details Attach a toggle source to this button
+ *
+ * @gh The button handle
+ * @gsh The source handle
+ *
+ * @return
+ */
+ bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GWIN_NEED_BUTTON */
+
+#endif /* _GWIN_BUTTON_H */
+/** @} */
diff --git a/include/gwin/console.h b/include/gwin/console.h
new file mode 100644
index 00000000..30058b2b
--- /dev/null
+++ b/include/gwin/console.h
@@ -0,0 +1,144 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gwin/console.h
+ * @brief GWIN Graphic window subsystem header file.
+ *
+ * @defgroup Console Console
+ * @ingroup GWIN
+ *
+ * @details GWIN allows it to create a console/terminal like window.
+ * You can simply use chprintf() to print to the terminal.
+ *
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ * @pre GWIN_NEED_CONSOLE must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GWIN_CONSOLE_H
+#define _GWIN_CONSOLE_H
+
+#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define GW_CONSOLE 0x0001
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+// A console window. Supports wrapped text writing and a cursor.
+typedef struct GConsoleObject_t {
+ GWindowObject gwin;
+
+ struct GConsoleWindowStream_t {
+ const struct GConsoleWindowVMT_t *vmt;
+ _base_asynchronous_channel_data
+ } stream;
+
+ coord_t cx,cy; // Cursor position
+ uint8_t fy; // Current font height
+ uint8_t fp; // Current font inter-character spacing
+ } GConsoleObject;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a console window.
+ * @details A console window allows text to be written using chprintf() (and the console functions defined here).
+ * @brief Text in a console window supports newlines and will wrap text as required.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] gc The GConsoleObject 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
+ * @param[in] font The font to use
+ * @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
+ * @note If the dispay does not support scrolling, the window will be cleared when the bottom line is reached.
+ * @note The default drawing color gets set to White and the background drawing color to Black.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ *
+ * @api
+ */
+GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font);
+
+/**
+ * @brief Get a stream from a console window suitable for use with chprintf().
+ * @return The stream handle or NULL if this is not a console window.
+ *
+ * @param[in] gh The window handle (must be a console window)
+ *
+ * @api
+ */
+BaseSequentialStream *gwinGetConsoleStream(GHandle gh);
+
+/**
+ * @brief Put a character at the cursor position in the window.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ *
+ * @param[in] gh The window handle (must be a console window)
+ * @param[in] c The character to draw
+ *
+ * @api
+ */
+void gwinPutChar(GHandle gh, char c);
+
+/**
+ * @brief Put a string at the cursor position in the window. It will wrap lines as required.
+ * @note Uses the current foreground color to draw the string and fills the background using the background drawing color
+ *
+ * @param[in] gh The window handle (must be a console window)
+ * @param[in] str The string to draw
+ *
+ * @api
+ */
+void gwinPutString(GHandle gh, const char *str);
+
+/**
+ * @brief Put the character array at the cursor position in the window. It will wrap lines as required.
+ * @note Uses the current foreground color to draw the string and fills the background using the background drawing color
+ *
+ * @param[in] gh The window handle (must be a console window)
+ * @param[in] str The string to draw
+ * @param[in] n The number of characters to draw
+ *
+ * @api
+ */
+void gwinPutCharArray(GHandle gh, const char *str, size_t n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GWIN_NEED_CONSOLE */
+
+#endif /* _GWIN_CONSOLE_H */
+/** @} */
diff --git a/include/gwin/graph.h b/include/gwin/graph.h
new file mode 100644
index 00000000..9267813b
--- /dev/null
+++ b/include/gwin/graph.h
@@ -0,0 +1,208 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gwin/graph.h
+ * @brief GWIN GRAPH module header file.
+ *
+ * @defgroup Graph Graph
+ * @ingroup GWIN
+ *
+ * @details GWIN allows it to easily draw graphs.
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ * @pre GWIN_NEED_GRAPH must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GWIN_GRAPH_H
+#define _GWIN_GRAPH_H
+
+#if GWIN_NEED_GRAPH || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define GW_GRAPH 0x0003
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+typedef struct GGraphPoint_t {
+ coord_t x, y;
+ } GGraphPoint;
+
+typedef enum GGraphPointType_e {
+ GGRAPH_POINT_NONE, GGRAPH_POINT_DOT, GGRAPH_POINT_SQUARE, GGRAPH_POINT_CIRCLE
+ } GGraphPointType;
+
+typedef struct GGraphPointStyle_t {
+ GGraphPointType type;
+ coord_t size;
+ color_t color;
+ } GGraphPointStyle;
+
+typedef enum GGraphLineType_e {
+ GGRAPH_LINE_NONE, GGRAPH_LINE_SOLID, GGRAPH_LINE_DOT, GGRAPH_LINE_DASH
+ } GGraphLineType;
+
+typedef struct GGraphLineStyle_t {
+ GGraphLineType type;
+ coord_t size;
+ color_t color;
+ } GGraphLineStyle;
+
+typedef struct GGraphGridStyle_t {
+ GGraphLineType type;
+ coord_t size;
+ color_t color;
+ coord_t spacing;
+ } GGraphGridStyle;
+
+typedef struct GGraphStyle_t {
+ GGraphPointStyle point;
+ GGraphLineStyle line;
+ GGraphLineStyle xaxis;
+ GGraphLineStyle yaxis;
+ GGraphGridStyle xgrid;
+ GGraphGridStyle ygrid;
+ uint16_t flags;
+ #define GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS 0x0001
+ #define GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS 0x0002
+ #define GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS 0x0004
+ #define GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS 0x0008
+ #define GWIN_GRAPH_STYLE_POSITIVE_AXIS_ARROWS (GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS|GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS)
+ #define GWIN_GRAPH_STYLE_NEGATIVE_AXIS_ARROWS (GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS|GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS)
+ #define GWIN_GRAPH_STYLE_XAXIS_ARROWS (GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS|GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS)
+ #define GWIN_GRAPH_STYLE_YAXIS_ARROWS (GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS|GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS)
+ #define GWIN_GRAPH_STYLE_ALL_AXIS_ARROWS (GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS)
+} GGraphStyle;
+
+// A graph window
+typedef struct GGraphObject_t {
+ GWindowObject gwin;
+ GGraphStyle style;
+ coord_t xorigin, yorigin;
+ coord_t lastx, lasty;
+ } GGraphObject;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a graph window.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] gg The GGraphObject 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 console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
+ * @note The coordinate system within the window for graphing operations (but not for any other drawing
+ * operation) is relative to the bottom left corner and then shifted right and up by the specified
+ * graphing x and y origin. Note that this system is inverted in the y direction relative to the display.
+ * This gives the best graphing arrangement ie. increasing y values are closer to the top of the display.
+ *
+ * @api
+ */
+GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height);
+
+/**
+ * @brief Set the style of the graphing operations.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ * @param[in] pstyle The graph style to set.
+ * @note The graph is not automatically redrawn. The new style will apply to any new drawing operations.
+ *
+ * @api
+ */
+void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle);
+
+/**
+ * @brief Set the origin for graphing operations.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ * @param[in] x, y The new origin for the graph (in graph coordinates relative to the bottom left corner).
+ * @note The graph is not automatically redrawn. The new origin will apply to any new drawing operations.
+ *
+ * @api
+ */
+void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y);
+
+/**
+ * @brief Draw the axis and the background grid.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ * @note The graph is not automatically cleared. You must do that first by calling gwinClear().
+ *
+ * @api
+ */
+void gwinGraphDrawAxis(GHandle gh);
+
+/**
+ * @brief Start a new set of graphing data.
+ * @details This prevents a line being drawn from the last data point to the next point to be drawn.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ *
+ * @api
+ */
+void gwinGraphStartSet(GHandle gh);
+
+/**
+ * @brief Draw a graph point.
+ * @details A graph point and a line connecting to the previous point will be drawn.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ * @param[in] x, y The new point for the graph.
+ *
+ * @api
+ */
+void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y);
+
+/**
+ * @brief Draw multiple graph points.
+ * @details A graph point and a line connecting to each previous point will be drawn.
+ *
+ * @param[in] gh The window handle (must be a graph window)
+ * @param[in] points The array of points for the graph.
+ * @param[in] count The number of points in the array.
+ * @note This is slightly more efficient than calling gwinGraphDrawPoint() repeatedly.
+ *
+ * @api
+ */
+void gwinGraphDrawPoints(GHandle gh, const GGraphPoint *points, unsigned count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GWIN_NEED_GRAPH */
+
+#endif /* _GWIN_GRAPH_H */
+/** @} */
+
diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h
new file mode 100644
index 00000000..e109dd83
--- /dev/null
+++ b/include/gwin/gwin.h
@@ -0,0 +1,186 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gwin/gwin.h
+ * @brief GWIN Graphic window subsystem header file.
+ *
+ * @defgroup Window Window
+ * @ingroup GWIN
+ *
+ * @details GWIN provides a basic window manager which allows it to easily
+ * create and destroy different windows on runtime. Each window
+ * will have it's own properties such as colors, brushes as well as
+ * it's own drawing origin.
+ * Moving the windows around is not supported yet.
+ *
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _GWIN_H
+#define _GWIN_H
+
+#include "gfx.h"
+
+#if GFX_USE_GWIN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+typedef uint16_t GWindowType;
+#define GW_WINDOW 0x0000
+#define GW_FIRST_USER_WINDOW 0x8000
+
+// A basic window
+typedef struct GWindowObject_t {
+ GWindowType type; // What type of window is this
+ uint16_t flags; // Internal flags
+ coord_t x, y; // Screen relative position
+ coord_t width, height; // Dimensions of this window
+ color_t color, bgcolor; // Current drawing colors
+#if GDISP_NEED_TEXT
+ font_t font; // Current font
+#endif
+} GWindowObject, * GHandle;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Base Functions */
+GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height);
+void gwinDestroyWindow(GHandle gh);
+
+/**
+ * @brief Get the X coordinate of the window
+ * @details Returns the X coordinate of the origin of the window.
+ * The coordinate is relative to the physical screen zero point.
+ *
+ * @param[in] gh The window
+ */
+#define gwinGetScreenX(gh) ((gh)->x)
+
+/**
+ * @brief Get the Y coordinate of the window
+ * @details Returns the Y coordinate of the origin of the window.
+ * The coordinate is relative to the physical screen zero point.
+ *
+ * @param[in] gh The window
+ */
+#define gwinGetScreenY(gh) ((gh)->y)
+
+/**
+ * @brief Get the width of the window
+ *
+ * @param[in] gh The window
+ */
+#define gwinGetWidth(gh) ((gh)->width)
+
+/**
+ * @brief Get the height of the window
+ *
+ * @param[in] gh The window
+ */
+#define gwinGetHeight(gh) ((gh)->height)
+
+/**
+ * @brief Set foreground color
+ * @details Set the color which will be used to draw
+ *
+ * @param[in] gh The window
+ * @param[in] clr The color to be set
+ */
+#define gwinSetColor(gh, clr) (gh)->color = (clr)
+
+/**
+ * @brief Set background color
+ * @details Set the color which will be used as background
+ * @note gwinClear() must be called to set the background color
+ *
+ * @param[in] gh The window
+ * @param[in] bgclr The background color
+ */
+#define gwinSetBgColor(gh, bgclr) (gh)->bgcolor = (bgclr)
+
+/* Set up for text */
+#if GDISP_NEED_TEXT
+ void gwinSetFont(GHandle gh, font_t font);
+#endif
+
+/* Drawing Functions */
+void gwinClear(GHandle gh);
+void gwinDrawPixel(GHandle gh, coord_t x, coord_t y);
+void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1);
+void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
+void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
+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);
+
+/* Circle Functions */
+#if GDISP_NEED_CIRCLE
+ void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
+ void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
+#endif
+
+/* Ellipse Functions */
+#if GDISP_NEED_ELLIPSE
+ void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
+ void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
+#endif
+
+/* Arc Functions */
+#if GDISP_NEED_ARC
+ void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+ void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+#endif
+
+/* Read a pixel Function */
+#if GDISP_NEED_PIXELREAD
+ color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y);
+#endif
+
+/* Extra Text Functions */
+#if GDISP_NEED_TEXT
+ void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c);
+ void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c);
+ void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str);
+ void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str);
+ void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
+ void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Include extra window types */
+#include "gwin/console.h"
+#include "gwin/button.h"
+#include "gwin/graph.h"
+
+#endif /* GFX_USE_GWIN */
+
+#endif /* _GWIN_H */
+/** @} */
diff --git a/include/gwin/internal.h b/include/gwin/internal.h
new file mode 100644
index 00000000..b47a2229
--- /dev/null
+++ b/include/gwin/internal.h
@@ -0,0 +1,53 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file include/gwin/internal.h
+ * @brief GWIN Graphic window subsystem header file.
+ *
+ * @addtogroup GWIN
+ * @{
+ */
+#ifndef _GWIN_INTERNAL_H
+#define _GWIN_INTERNAL_H
+
+#if GFX_USE_GWIN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Sub-system constants. */
+/*===========================================================================*/
+
+#define GWIN_FLG_DYNAMIC 0x0001
+#define GBTN_FLG_ALLOCTXT 0x0002
+#define GWIN_FIRST_CONTROL_FLAG 0x0004
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GWIN */
+
+#endif /* _GWIN_INTERNAL_H */
+/** @} */
diff --git a/include/gwin/options.h b/include/gwin/options.h
new file mode 100644
index 00000000..6e17e61f
--- /dev/null
+++ b/include/gwin/options.h
@@ -0,0 +1,71 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/gwin/options.h
+ * @brief GWIN sub-system options header file.
+ *
+ * @addtogroup GWIN
+ * @{
+ */
+
+#ifndef _GWIN_OPTIONS_H
+#define _GWIN_OPTIONS_H
+
+/**
+ * @name GWIN Functionality to be included
+ * @{
+ */
+ /**
+ * @brief Should button functions be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_BUTTON
+ #define GWIN_NEED_BUTTON FALSE
+ #endif
+ /**
+ * @brief Should console functions be included.
+ * @details Defaults to FALSE
+ * @note To use chprintf() for printing in a console window you need to
+ * include in your application source file...
+ * \#include "chprintf.h"
+ * Also in your makefile, as part of your list of C source files, include
+ * ${CHIBIOS}/os/various/chprintf.c
+ */
+ #ifndef GWIN_NEED_CONSOLE
+ #define GWIN_NEED_CONSOLE FALSE
+ #endif
+ /**
+ * @brief Should graph functions be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_GRAPH
+ #define GWIN_NEED_GRAPH FALSE
+ #endif
+/**
+ * @}
+ *
+ * @name GWIN Optional Sizing Parameters
+ * @{
+ */
+/** @} */
+
+#endif /* _GWIN_OPTIONS_H */
+/** @} */
diff --git a/include/tdisp/lld/tdisp_lld.h b/include/tdisp/lld/tdisp_lld.h
new file mode 100644
index 00000000..de6266f3
--- /dev/null
+++ b/include/tdisp/lld/tdisp_lld.h
@@ -0,0 +1,57 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/tdisp/lld/tdisp_lld.h
+ * @brief TDISP driver subsystem low level driver header.
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_LLD_H
+#define _TDISP_LLD_H
+
+#if GFX_USE_TDISP || defined(__DOXYGEN__)
+
+#include "tdisp_lld_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void tdisp_lld_write_cmd(uint8_t data);
+extern void tdisp_lld_write_data(uint8_t data);
+extern bool_t tdisp_lld_init(void);
+extern void tdisp_lld_set_cursor(coord_t col, coord_t row);
+extern void tdisp_lld_create_char(uint8_t address, char *charmap);
+extern void tdisp_lld_clear(void);
+extern void tdisp_lld_home(void);
+extern void tdisp_lld_control(uint16_t what, void *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_TDISP */
+
+#endif /* _TDISP_LLD_H */
+/** @} */
+
diff --git a/include/tdisp/options.h b/include/tdisp/options.h
new file mode 100644
index 00000000..69d24b64
--- /dev/null
+++ b/include/tdisp/options.h
@@ -0,0 +1,87 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/tdisp/options.h
+ * @brief TDISP sub-system options header file.
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_OPTIONS_H
+#define _TDISP_OPTIONS_H
+
+#if GFX_USE_TDISP
+/**
+ * @name TDISP configuration
+ * @{
+ */
+
+ /**
+ * @brief How many rows of characters the TDISP provides
+ */
+ #ifndef TDISP_ROWS
+ #define TDISP_ROWS 2
+ #endif
+
+ /**
+ * @brief How many columns of characters the TDISP provides
+ */
+ #ifndef TDISP_COLUMNS
+ #define TDISP_COLUMNS 16
+ #endif
+
+/** @} */
+
+/**
+ * @name TDISP interface configuration
+ * @note Only one of these interfaces can be selected at a time!
+ * @{
+ */
+ /**
+ * @brief Use the 4-bit paralle interface
+ */
+ #ifndef TDISP_NEED_4BIT_MODE
+ #define TDISP_NEED_4BIT_MODE FALSE
+ #endif
+
+ /**
+ * @brief Use the 8-bit parallel interface
+ */
+ #ifndef TDISP_NEED_8BIT_MODE
+ #define TDISP_NEED_8BIT_MODE FALSE
+ #endif
+
+ #if (!TDISP_NEED_4BIT_MODE && !TDISP_NEED_8BIT_MODE)
+ #error "Either TDISP_NEED_4BIT_MODE or TDISP_NEED_8BIT_MODE needs to be set to TRUE in your gfxconf.h!"
+ #endif
+
+ #if (TDISP_NEED_4BIT_MODE && TDISP_NEED_8BIT_MODE)
+ #error "Only TDISP_NEED_4BIT_MODE or TDISP_NEED_8BIT_MODE can be set to TRUE, not both at one!"
+ #endif
+
+/** @} */
+
+#endif /* GFX_USE_TDISP */
+
+#endif /* _TDISP_OPTIONS_H */
+/** @} */
+
diff --git a/include/tdisp/tdisp.h b/include/tdisp/tdisp.h
new file mode 100644
index 00000000..01cb76a0
--- /dev/null
+++ b/include/tdisp/tdisp.h
@@ -0,0 +1,147 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file include/tdisp/tdisp.h
+ * @brief TDISP Graphic Driver subsystem header file.
+ *
+ * @addtogroup TDISP
+ *
+ * @details The TDISP module provides high level abstraction to interface pixel oriented graphic displays.
+ * Due the TDISP module is completely encapsulated from the other modules, it's very fast and lightweight.
+ *
+ * @pre GFX_USE_TDISP must be set to TRUE in gfxconf.h
+ *
+ * @{
+ */
+
+#ifndef _TDISP_H
+#define _TDISP_H
+
+#include "gfx.h"
+
+#if GFX_USE_TDISP || defined(__DOXYGEN__)
+
+/* Include the low level driver information */
+#include "tdisp/lld/tdisp_lld.h"
+
+/**
+ * @name TDISP display attributes
+ * @{
+ */
+#define TDISP_ON 0x01
+#define TDISP_OFF 0x02
+#define TDISP_CURSOR_ON 0x03
+#define TDISP_CURSOR_OFF 0x04
+#define TDISP_CURSOR_BLINK_ON 0x05
+#define TDISP_CURSOR_BLINK_OFF 0x06
+/** @} */
+
+/**
+ * @brief TDISP driver initialisation
+ * @note This function is not implicitly invoked by @p halInit().
+ * It must be called manually.
+ *
+ * @return TRUE if success, FALSE otherwise
+ *
+ * @init
+ */
+bool_t tdispInit(void);
+
+/**
+ * @brief Control different display properties
+ * @note A wrapper macro exists for each option, please use them
+ * instead of this function manually.
+ *
+ * @param[in] what What you want to control
+ * @param[in] value The value to be assigned
+ */
+void tdispControl(uint16_t what, void *value);
+
+/**
+ * @brief Clears the display
+ */
+void tdispClear(void);
+
+/**
+ * @brief Sets the cursor to it's home position ( 0/0 )
+ */
+void tdispHome(void);
+
+/**
+ * @brief Set cursor to a certain position
+ *
+ * @param[in] col The column
+ * @param[in] row The row
+ */
+void tdispSetCursor(coord_t col, coord_t row);
+
+/**
+ * @brief Store a custom character in RAM
+ *
+ * @note This usually must be done after each power-up since most
+ * LCDs lose their RAM content.
+ *
+ * @param[in] address On which address to store the character (from 0 up to max)
+ * @param[in] charmap The character to be stored.
+ */
+void tdispCreateChar(uint8_t address, char *charmap);
+
+/**
+ * @brief Draws a single character at the current cursor position
+ *
+ * @param[in] c The character to be drawn
+ */
+void tdispDrawChar(char c);
+
+/**
+ * @brief Draws a string at the current cursor position
+ *
+ * @param[in] s The string to be drawn
+ */
+void tdispDrawString(char *s);
+
+/**
+ * @brief Draws a single character at a given position
+ * @note This function manipulates the cursor position and it will not be
+ * reset to it's original state
+ *
+ * @param[in] col The column
+ * @param[in] row The row
+ * @param[in] c The character to be drawn
+ */
+void tdispDrawCharLocation(coord_t col, coord_t row, char c);
+
+/**
+ * @brief Draws a string at a given position
+ * @note This function manipulates the cursor position and it will not be
+ * reset to it's original state
+ *
+ * @param[in] col The column
+ * @param[in] row The row
+ * @param[in] s The string to be drawn
+ */
+void tdispDrawStringLocation(coord_t col, coord_t row, char *s);
+
+#endif /* GFX_USE_TDISP */
+
+#endif /* _TDISP_H */
+/** @} */
+
diff --git a/license.txt b/license.txt
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program 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.
+
+ This program 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 .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 00000000..cb534a3c
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,2 @@
+please visit http://chibios-gfx.com
+
diff --git a/releases.txt b/releases.txt
new file mode 100644
index 00000000..400d2d37
--- /dev/null
+++ b/releases.txt
@@ -0,0 +1,74 @@
+*****************************************************************************
+*** Releases ***
+*****************************************************************************
+
+current release: 1.5
+FEATURE: Added ILI9325 driver - Thanks to Chris van Dongen aka _Sjaak
+FEATURE: Added TDISP module
+FIX: tdispGotoXY() renamed to tdispSetCursor()
+FEATURE: Addition of GADC, GMISC, GAUDIN, GAUDOUT subsystems
+
+
+*** changes after 1.4 ***
+FEATURE: GEVENT - for passing event structures from Sources to Listeners
+FEATURE: GTIMER - thread context based once-off and periodic timers.
+FEATURE: GINPUT - extensible, multiple device-type, input sub-system.
+FEATURE: GWIN - full button, console and graph support
+FEATURE: Numerous touch calibration improvements
+FEATURE: Win32 driver - now support gdisp & ginput mouse/touch/toggle
+FEATURE: Win32 driver - full gdisp orientation support
+FEATURE: ILI9320 GDISP driver
+FEATURE: Nokia6610 GDISP driver split in to GE8 and GE12 variants
+FEATURE: Many GDISP drivers changed to use a board interface definition
+FEATURE: GFX source restructure with new gfx.h include file.
+DEPRECATE: console deprecated - replaced with gwin functionality
+DEPRECATE: graph deprecated - replaced with gwin functionality
+DEPRECATE: touchscreen deprecated - replaced with ginput functionality
+FEATURE: Numerous documentation improvements
+FEATURE: Added a number of module demo and test programs
+DEPRECATE: Remove of XPT2046 since full compatibility with ADS7843
+
+
+*** changes after 1.3 ***
+FIX: Nokia 6610 fix
+FEATURE: New driver: Win32
+FEATURE: implementation of gdispFillArc()
+FIX: Hardware accelerate Arc routines
+FIX: Fix axis orientation for Arc routines
+FEATURE: new gdisp rounded box routines
+FEATURE: new gdispDrawStringBox()
+FEATURE: GWIN infrastructure
+FEATURE: now we fully support doxygen
+
+
+*** changes after 1.2 ***
+FEATURE: added FSMC for SSD1289 / F4
+FEATURE: added calibration storage interface
+FIX: bugfix in filling functions for SSD1289
+FEATURE: added point_t struct in gdisp.h
+FEATURE: added graph module
+
+
+*** changer after 1.1 ***
+FIX: orientation macros changed
+FIX: huge internal bugfix in orientation stuff (big thanks to Abhishek)
+FEATURE: added TOUCHPAD_XY_INVERTED macro
+FIX: struct cal renamed to struct cal_t
+FIX: SCREEN_WIDTH and SCREEN_HEIGHT renamed to GDISP_SCREEN_WIDTH and GDISP_SCREEN_HEIGHT
+FIX: struct TOUCHPAD_t renamed to struct TOUCHPADDriver_t
+FIX: struct GConsole renamed to struct GConsole_t
+FIX: lcdConsoleXXX() functions have been renamed to gfxConsoleXXX()
+FEATURE: FSMC for SSD1289 F2/F4
+
+
+*** changes after 1.0 ***
+FIX: removed gdisp and touchpad prefix of driver directories
+UPDATE: added SSD1963 driver
+FIX: fixed Validation, VMT driver, console and BitBlit
+FEATURE: added clipping support
+FEATURE: addad gdispDrawArc()
+FEATURE: added SSD1963 DMA support
+FEATURE: added touchpad interface for storing calibration values (#define TOUCHPAD_STORE_CALIBRATION)
+CHANGE: replaced every GDISP_XXX macro with GDISP_XXX
+CHANGE: removed last digit of version number
+
diff --git a/src/gadc/gadc.c b/src/gadc/gadc.c
new file mode 100644
index 00000000..5533bb49
--- /dev/null
+++ b/src/gadc/gadc.c
@@ -0,0 +1,38 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gadc/gadc.c
+ * @brief GADC sub-system code.
+ *
+ * @addtogroup GADC
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GADC || defined(__DOXYGEN__)
+
+ #error "GADC: Not implemented yet"
+
+#endif /* GFX_USE_GADC */
+/** @} */
+
diff --git a/src/gadc/gadc.mk b/src/gadc/gadc.mk
new file mode 100644
index 00000000..cfe04177
--- /dev/null
+++ b/src/gadc/gadc.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gadc/gadc.c
diff --git a/src/gaudin/gaudin.c b/src/gaudin/gaudin.c
new file mode 100644
index 00000000..120d7d81
--- /dev/null
+++ b/src/gaudin/gaudin.c
@@ -0,0 +1,38 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @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 */
+/** @} */
+
diff --git a/src/gaudin/gaudin.mk b/src/gaudin/gaudin.mk
new file mode 100644
index 00000000..f134d264
--- /dev/null
+++ b/src/gaudin/gaudin.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gaudin/gaudin.c
diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c
new file mode 100644
index 00000000..af8499dc
--- /dev/null
+++ b/src/gaudout/gaudout.c
@@ -0,0 +1,38 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gaudout/gaudout.c
+ * @brief GAUDOUT sub-system code.
+ *
+ * @addtogroup GAUDOUT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
+
+ #error "GAUDOUT: Not implemented yet"
+
+#endif /* GFX_USE_GAUDOUT */
+/** @} */
+
diff --git a/src/gaudout/gaudout.mk b/src/gaudout/gaudout.mk
new file mode 100644
index 00000000..004306bc
--- /dev/null
+++ b/src/gaudout/gaudout.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gaudout/gaudout.c
diff --git a/src/gdisp/fonts.c b/src/gdisp/fonts.c
new file mode 100644
index 00000000..59293359
--- /dev/null
+++ b/src/gdisp/fonts.c
@@ -0,0 +1,780 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gdisp/fonts.c
+ * @brief GDISP Font Handling.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GDISP && GDISP_NEED_TEXT) || defined(__DOXYGEN__)
+
+#include "gdisp/fonts.h"
+
+#if GDISP_OLD_FONT_DEFINITIONS
+ #define FONT_DECL
+#else
+ #define FONT_DECL static
+#endif
+
+/* fontSmall - for side buttons */
+#if GDISP_INCLUDE_FONT_SMALL
+ /* Forward Declarations of internal arrays */
+ static const uint8_t fontSmall_Widths[];
+ static const uint16_t fontSmall_Offsets[];
+ static const fontcolumn_t fontSmall_Data[];
+
+ FONT_DECL const struct font fontSmall = {
+ "Small",
+ 11, 0, 14, 2, 2, 12, ' ', '~', 1, 1,
+ fontSmall_Widths,
+ fontSmall_Offsets,
+ fontSmall_Data};
+ FONT_DECL const struct font fontSmallDouble = {
+ "Small Double",
+ 11, 0, 14, 2, 2, 12, ' ', '~', 2, 2,
+ fontSmall_Widths,
+ fontSmall_Offsets,
+ fontSmall_Data};
+ FONT_DECL const struct font fontSmallNarrow = {
+ "Small Narrow",
+ 11, 0, 14, 2, 2, 12, ' ', '~', 1, 2,
+ fontSmall_Widths,
+ fontSmall_Offsets,
+ fontSmall_Data};
+
+ static const uint8_t fontSmall_Widths[] = {
+ 2, 3, 6, 8, 7, 9, 7, 3, 4, 4, 5, 7, 4, 4, 3, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 4, 6, 7, 6, 7,
+ 12, 8, 7, 8, 8, 7, 7, 8, 8, 3, 5, 8, 7, 9, 8, 8,
+ 8, 8, 8, 7, 7, 8, 8, 12, 8, 8, 8, 4, 6, 4, 7, 7,
+ 4, 7, 7, 7, 7, 7, 4, 7, 7, 3, 3, 7, 3, 9, 7, 7,
+ 7, 7, 4, 6, 4, 7, 7, 9, 6, 6, 6, 5, 3, 5, 8, 0
+ };
+ static const uint16_t fontSmall_Offsets[] = {
+ 0, 2, 5, 11, 19, 26, 35, 42,
+ 45, 49, 53, 58, 65, 69, 73, 76,
+ 82, 89, 96, 103, 110, 117, 124, 131,
+ 138, 145, 152, 155, 159, 165, 172, 178,
+ 185, 197, 205, 212, 220, 228, 235, 242,
+ 250, 258, 261, 266, 274, 281, 290, 298,
+ 306, 314, 322, 330, 337, 344, 352, 360,
+ 372, 380, 388, 396, 400, 406, 410, 417,
+ 424, 428, 435, 442, 449, 456, 463, 467,
+ 474, 481, 484, 487, 494, 497, 506, 513,
+ 520, 527, 534, 538, 544, 548, 555, 562,
+ 571, 577, 583, 589, 594, 597, 602, 0
+ };
+ static const fontcolumn_t fontSmall_Data[] = {
+ /* */ 0x0000, 0x0000,
+ /* ! */ 0x0000, 0x017F, 0x017F,
+ /* " */ 0x0000, 0x0007, 0x0007, 0x0000, 0x0007, 0x0007,
+ /* # */ 0x0000, 0x0044, 0x01FF, 0x01FF, 0x0044, 0x01FF, 0x01FF, 0x0044,
+ /* $ */ 0x0000, 0x008C, 0x019E, 0x03FF, 0x03FF, 0x01E6, 0x00C4,
+ /* % */ 0x0000, 0x0082, 0x00C7, 0x0065, 0x00B7, 0x01DA, 0x014C, 0x01C6, 0x0082,
+ /* & */ 0x0000, 0x00E6, 0x01FF, 0x013F, 0x01E6, 0x01E0, 0x0120,
+ /* ' */ 0x0000, 0x0007, 0x0007,
+ /* ( */ 0x0000, 0x03FE, 0x07FF, 0x0401,
+ /* ) */ 0x0000, 0x0401, 0x07FF, 0x03FE,
+ /* * */ 0x0000, 0x000A, 0x000E, 0x000E, 0x000A,
+ /* + */ 0x0000, 0x0020, 0x0020, 0x00F8, 0x00F8, 0x0020, 0x0020,
+ /* , */ 0x0000, 0x0200, 0x0300, 0x0100,
+ /* - */ 0x0000, 0x0020, 0x0020, 0x0020,
+ /* . */ 0x0000, 0x0100, 0x0100,
+ /* / */ 0x0000, 0x0180, 0x01E0, 0x0078, 0x001F, 0x0007,
+ /* 0 */ 0x0000, 0x00FE, 0x01FF, 0x0101, 0x0101, 0x01FF, 0x00FE,
+ /* 1 */ 0x0000, 0x0002, 0x0002, 0x01FF, 0x01FF, 0x0000, 0x0000,
+ /* 2 */ 0x0000, 0x0182, 0x01C3, 0x0161, 0x0131, 0x011F, 0x010E,
+ /* 3 */ 0x0000, 0x0082, 0x0183, 0x0111, 0x0111, 0x01FF, 0x00EE,
+ /* 4 */ 0x0000, 0x0060, 0x0078, 0x005E, 0x01FF, 0x01FF, 0x0040,
+ /* 5 */ 0x0000, 0x009F, 0x019F, 0x0109, 0x0109, 0x01F9, 0x00F1,
+ /* 6 */ 0x0000, 0x00FE, 0x01FF, 0x0111, 0x0111, 0x01F3, 0x00E2,
+ /* 7 */ 0x0000, 0x0001, 0x01C1, 0x01F1, 0x003D, 0x000F, 0x0003,
+ /* 8 */ 0x0000, 0x00EE, 0x01FF, 0x0111, 0x0111, 0x01FF, 0x00EE,
+ /* 9 */ 0x0000, 0x008E, 0x019F, 0x0111, 0x0111, 0x01FF, 0x00FE,
+ /* : */ 0x0000, 0x0108, 0x0108,
+ /* ; */ 0x0000, 0x0200, 0x0308, 0x0108,
+ /* < */ 0x0000, 0x0020, 0x0070, 0x00D8, 0x018C, 0x0104,
+ /* = */ 0x0000, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050,
+ /* > */ 0x0000, 0x0104, 0x018C, 0x00D8, 0x0070, 0x0020,
+ /* ? */ 0x0000, 0x0002, 0x0003, 0x0161, 0x0171, 0x001F, 0x000E,
+ /* @ */ 0x0000, 0x0078, 0x01FE, 0x0186, 0x0333, 0x0279, 0x0249, 0x0279, 0x027B, 0x0246, 0x007E, 0x0078,
+ /* A */ 0x0180, 0x01F0, 0x007C, 0x004F, 0x004F, 0x007C, 0x01F0, 0x0180,
+ /* B */ 0x0000, 0x01FF, 0x01FF, 0x0111, 0x0111, 0x01FF, 0x00EE,
+ /* C */ 0x0000, 0x00FE, 0x01FF, 0x0101, 0x0101, 0x0101, 0x0183, 0x0082,
+ /* D */ 0x0000, 0x01FF, 0x01FF, 0x0101, 0x0101, 0x0183, 0x00FE, 0x007C,
+ /* E */ 0x0000, 0x01FF, 0x01FF, 0x0111, 0x0111, 0x0111, 0x0101,
+ /* F */ 0x0000, 0x01FF, 0x01FF, 0x0011, 0x0011, 0x0011, 0x0001,
+ /* G */ 0x0000, 0x00FE, 0x01FF, 0x0101, 0x0111, 0x0191, 0x01F3, 0x01F2,
+ /* H */ 0x0000, 0x01FF, 0x01FF, 0x0010, 0x0010, 0x0010, 0x01FF, 0x01FF,
+ /* I */ 0x0000, 0x01FF, 0x01FF,
+ /* J */ 0x00C0, 0x01C0, 0x0100, 0x01FF, 0x00FF,
+ /* K */ 0x0000, 0x01FF, 0x01FF, 0x003C, 0x0066, 0x00C3, 0x0181, 0x0100,
+ /* L */ 0x0000, 0x01FF, 0x01FF, 0x0100, 0x0100, 0x0100, 0x0100,
+ /* M */ 0x0000, 0x01FF, 0x01FF, 0x003C, 0x00F0, 0x00F0, 0x003C, 0x01FF, 0x01FF,
+ /* N */ 0x0000, 0x01FF, 0x01FF, 0x001E, 0x0038, 0x00E0, 0x01FF, 0x01FF,
+ /* O */ 0x0000, 0x00FE, 0x01FF, 0x0101, 0x0101, 0x0101, 0x01FF, 0x00FE,
+ /* P */ 0x0000, 0x01FF, 0x01FF, 0x0011, 0x0011, 0x0011, 0x001F, 0x000E,
+ /* Q */ 0x0000, 0x00FE, 0x01FF, 0x0101, 0x0141, 0x01C1, 0x03FF, 0x02FE,
+ /* R */ 0x0000, 0x01FF, 0x01FF, 0x0011, 0x0011, 0x0011, 0x01FF, 0x01EE,
+ /* S */ 0x0000, 0x008E, 0x019F, 0x0111, 0x0111, 0x01F3, 0x00E2,
+ /* T */ 0x0000, 0x0001, 0x0001, 0x01FF, 0x01FF, 0x0001, 0x0001,
+ /* U */ 0x0000, 0x00FF, 0x01FF, 0x0100, 0x0100, 0x0100, 0x01FF, 0x00FF,
+ /* V */ 0x0003, 0x001F, 0x007C, 0x01E0, 0x01E0, 0x007C, 0x001F, 0x0003,
+ /* W */ 0x0003, 0x001F, 0x007C, 0x01E0, 0x01E0, 0x007C, 0x007C, 0x01E0, 0x01E0, 0x007C, 0x001F, 0x0003,
+ /* X */ 0x0183, 0x01C7, 0x006C, 0x0038, 0x0038, 0x006C, 0x01C7, 0x0183,
+ /* Y */ 0x0003, 0x0007, 0x000C, 0x01F8, 0x01F8, 0x000C, 0x0007, 0x0003,
+ /* Z */ 0x0181, 0x01C1, 0x0161, 0x0131, 0x0119, 0x010D, 0x0107, 0x0103,
+ /* [ */ 0x0000, 0x07FF, 0x07FF, 0x0401,
+ /* \ */ 0x0000, 0x0007, 0x001F, 0x0078, 0x01E0, 0x0180,
+ /* ] */ 0x0000, 0x0401, 0x07FF, 0x07FF,
+ /* ^ */ 0x0000, 0x0002, 0x0003, 0x0001, 0x0001, 0x0003, 0x0002,
+ /* _ */ 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
+ /* ` */ 0x0000, 0x0001, 0x0003, 0x0002,
+ /* a */ 0x0000, 0x00C0, 0x01E8, 0x0128, 0x0128, 0x01F8, 0x01F0,
+ /* b */ 0x0000, 0x01FF, 0x01FF, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* c */ 0x0000, 0x00F0, 0x01F8, 0x0108, 0x0108, 0x0198, 0x0090,
+ /* d */ 0x0000, 0x00F0, 0x01F8, 0x0108, 0x0108, 0x01FF, 0x01FF,
+ /* e */ 0x0000, 0x00F0, 0x01F8, 0x0128, 0x0128, 0x01B8, 0x00B0,
+ /* f */ 0x0000, 0x01FE, 0x01FF, 0x0009,
+ /* g */ 0x0000, 0x04F0, 0x05F8, 0x0508, 0x0508, 0x07F8, 0x03F8,
+ /* h */ 0x0000, 0x01FF, 0x01FF, 0x0018, 0x0008, 0x01F8, 0x01F0,
+ /* i */ 0x0000, 0x01F9, 0x01F9,
+ /* j */ 0x0000, 0x07F9, 0x07F9,
+ /* k */ 0x0000, 0x01FF, 0x01FF, 0x0070, 0x00D8, 0x0188, 0x0100,
+ /* l */ 0x0000, 0x01FF, 0x01FF,
+ /* m */ 0x0000, 0x01F8, 0x01F8, 0x0008, 0x01F8, 0x01F8, 0x0008, 0x01F8, 0x01F0,
+ /* n */ 0x0000, 0x01F8, 0x01F8, 0x0018, 0x0008, 0x01F8, 0x01F0,
+ /* o */ 0x0000, 0x00F0, 0x01F8, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* p */ 0x0000, 0x07F8, 0x07F8, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* q */ 0x0000, 0x00F0, 0x01F8, 0x0108, 0x0108, 0x07F8, 0x07F8,
+ /* r */ 0x0000, 0x01F8, 0x01F8, 0x0008,
+ /* s */ 0x0000, 0x0090, 0x01B8, 0x0168, 0x01D8, 0x0090,
+ /* t */ 0x0000, 0x00FE, 0x01FE, 0x0108,
+ /* u */ 0x0000, 0x00F8, 0x01F8, 0x0100, 0x0180, 0x01F8, 0x01F8,
+ /* v */ 0x0000, 0x0018, 0x0078, 0x01E0, 0x01E0, 0x0078, 0x0018,
+ /* w */ 0x0000, 0x0078, 0x01F8, 0x01E0, 0x0078, 0x0078, 0x01E0, 0x01F8, 0x0078,
+ /* x */ 0x0000, 0x0198, 0x01F8, 0x0060, 0x01F8, 0x0198,
+ /* y */ 0x0400, 0x0478, 0x07F8, 0x0380, 0x00F8, 0x0078,
+ /* z */ 0x0000, 0x0188, 0x01C8, 0x0168, 0x0138, 0x0118,
+ /* { */ 0x0000, 0x0010, 0x01FF, 0x03EF, 0x0200,
+ /* | */ 0x0000, 0x03FF, 0x03FF,
+ /* } */ 0x0000, 0x0200, 0x03EF, 0x01FF, 0x0010,
+ /* ~ */ 0x0000, 0x0004, 0x0006, 0x0002, 0x0006, 0x0004, 0x0006, 0x0002
+ };
+#endif
+
+/* fontLarger - Tahoma, 11, Bold */
+#if GDISP_INCLUDE_FONT_LARGER
+ /* Forward Declarations of internal arrays */
+ static const uint8_t fontLarger_Widths[];
+ static const uint16_t fontLarger_Offsets[];
+ static const fontcolumn_t fontLarger_Data[];
+
+ FONT_DECL const struct font fontLarger = {
+ "Larger",
+ 12, 1, 13, 2, 2, 13, ' ', '~', 1, 1,
+ fontLarger_Widths,
+ fontLarger_Offsets,
+ fontLarger_Data};
+ FONT_DECL const struct font fontLargerDouble = {
+ "Larger Double",
+ 12, 1, 13, 2, 2, 13, ' ', '~', 2, 2,
+ fontLarger_Widths,
+ fontLarger_Offsets,
+ fontLarger_Data};
+ FONT_DECL const struct font fontLargerNarrow = {
+ "Larger Narrow",
+ 12, 1, 13, 2, 2, 13, ' ', '~', 1, 2,
+ fontLarger_Widths,
+ fontLarger_Offsets,
+ fontLarger_Data};
+ static const uint8_t fontLarger_Widths[] = {
+ 2, 3, 5, 8, 7, 13, 8, 2, 4, 4, 7, 8, 3, 4, 3, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 9, 8, 9, 6,
+ 9, 8, 7, 7, 8, 6, 5, 7, 8, 4, 5, 7, 6, 10, 7, 8,
+ 7, 8, 8, 7, 6, 7, 7, 11, 7, 6, 6, 4, 5, 4, 9, 8,
+ 5, 6, 7, 5, 7, 6, 5, 7, 7, 2, 3, 6, 2, 10, 7, 7,
+ 7, 7, 4, 5, 5, 7, 6, 10, 6, 6, 5, 6, 4, 6, 9, 0
+ };
+ static const uint16_t fontLarger_Offsets[] = {
+ 0, 2, 5, 10, 18, 25, 38, 46,
+ 48, 52, 56, 63, 71, 74, 78, 81,
+ 86, 93, 100, 107, 114, 121, 128, 135,
+ 142, 149, 156, 159, 162, 171, 179, 188,
+ 194, 203, 211, 218, 225, 233, 239, 244,
+ 251, 259, 263, 268, 275, 281, 291, 298,
+ 306, 313, 321, 329, 336, 342, 349, 356,
+ 367, 374, 380, 386, 390, 395, 399, 408,
+ 416, 421, 427, 434, 439, 446, 452, 457,
+ 464, 471, 473, 476, 482, 484, 494, 501,
+ 508, 515, 522, 526, 531, 536, 543, 549,
+ 559, 565, 571, 576, 582, 586, 592, 0
+ };
+ static const fontcolumn_t fontLarger_Data[] = {
+ /* */ 0x0000, 0x0000,
+ /* ! */ 0x0000, 0x037E, 0x037E,
+ /* " */ 0x0007, 0x0007, 0x0000, 0x0007, 0x0007,
+ /* # */ 0x00C0, 0x03D8, 0x00F8, 0x00DE, 0x03D8, 0x00F8, 0x00DE, 0x0018,
+ /* $ */ 0x0118, 0x023C, 0x0264, 0x0FFF, 0x0264, 0x03C4, 0x0188,
+ /* % */ 0x001C, 0x003E, 0x0022, 0x023E, 0x011C, 0x00C0, 0x0020, 0x0018, 0x01C4, 0x03E2, 0x0220, 0x03E0,
+ 0x01C0,
+ /* & */ 0x01CC, 0x03FE, 0x0232, 0x0272, 0x03DE, 0x018C, 0x03E0, 0x0260,
+ /* ' */ 0x0007, 0x0007,
+ /* ( */ 0x01F8, 0x07FE, 0x0E07, 0x0801,
+ /* ) */ 0x0801, 0x0E07, 0x07FE, 0x01F8,
+ /* * */ 0x0000, 0x000A, 0x0004, 0x001F, 0x001F, 0x0004, 0x000A,
+ /* + */ 0x0000, 0x0020, 0x0020, 0x0020, 0x01FC, 0x0020, 0x0020, 0x0020,
+ /* , */ 0x0000, 0x0F00, 0x0700,
+ /* - */ 0x0020, 0x0020, 0x0020, 0x0020,
+ /* . */ 0x0000, 0x0300, 0x0300,
+ /* / */ 0x0C00, 0x0380, 0x0060, 0x001C, 0x0003,
+ /* 0 */ 0x01FC, 0x03FE, 0x0202, 0x0202, 0x0202, 0x03FE, 0x01FC,
+ /* 1 */ 0x0000, 0x0204, 0x0204, 0x03FE, 0x03FE, 0x0200, 0x0200,
+ /* 2 */ 0x0204, 0x0302, 0x0382, 0x02C2, 0x0262, 0x023E, 0x021C,
+ /* 3 */ 0x0104, 0x0202, 0x0222, 0x0222, 0x0222, 0x03FE, 0x01DC,
+ /* 4 */ 0x0060, 0x0050, 0x0048, 0x0044, 0x03FE, 0x03FE, 0x0040,
+ /* 5 */ 0x0100, 0x021E, 0x021E, 0x0212, 0x0212, 0x03F2, 0x01E2,
+ /* 6 */ 0x01F8, 0x03FC, 0x0216, 0x0212, 0x0212, 0x03F2, 0x01E0,
+ /* 7 */ 0x0002, 0x0002, 0x0382, 0x03E2, 0x007A, 0x001E, 0x0006,
+ /* 8 */ 0x01DC, 0x03FE, 0x0222, 0x0222, 0x0222, 0x03FE, 0x01DC,
+ /* 9 */ 0x003C, 0x027E, 0x0242, 0x0242, 0x0342, 0x01FE, 0x00FC,
+ /* : */ 0x0000, 0x0318, 0x0318,
+ /* ; */ 0x0000, 0x0F18, 0x0718,
+ /* < */ 0x0000, 0x0060, 0x0060, 0x0090, 0x0090, 0x0108, 0x0108, 0x0204, 0x0204,
+ /* = */ 0x0000, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090,
+ /* > */ 0x0000, 0x0204, 0x0204, 0x0108, 0x0108, 0x0090, 0x0090, 0x0060, 0x0060,
+ /* ? */ 0x0004, 0x0002, 0x0362, 0x0372, 0x001E, 0x000C,
+ /* @ */ 0x01F8, 0x0204, 0x04F2, 0x05FA, 0x050A, 0x04FA, 0x05FA, 0x0104, 0x00F8,
+ /* A */ 0x0380, 0x03F0, 0x00FC, 0x008E, 0x008E, 0x00FC, 0x03F0, 0x0380,
+ /* B */ 0x03FE, 0x03FE, 0x0222, 0x0222, 0x0222, 0x03FE, 0x01DC,
+ /* C */ 0x01FC, 0x03FE, 0x0202, 0x0202, 0x0202, 0x0202, 0x018C,
+ /* D */ 0x03FE, 0x03FE, 0x0202, 0x0202, 0x0202, 0x0306, 0x01FC, 0x00F8,
+ /* E */ 0x03FE, 0x03FE, 0x0222, 0x0222, 0x0222, 0x0222,
+ /* F */ 0x03FE, 0x03FE, 0x0022, 0x0022, 0x0022,
+ /* G */ 0x01FC, 0x03FE, 0x0202, 0x0202, 0x0222, 0x03E2, 0x03EC,
+ /* H */ 0x03FE, 0x03FE, 0x0020, 0x0020, 0x0020, 0x0020, 0x03FE, 0x03FE,
+ /* I */ 0x0202, 0x03FE, 0x03FE, 0x0202,
+ /* J */ 0x0200, 0x0202, 0x0202, 0x03FE, 0x01FE,
+ /* K */ 0x03FE, 0x03FE, 0x0070, 0x00D8, 0x018C, 0x0306, 0x0202,
+ /* L */ 0x03FE, 0x03FE, 0x0200, 0x0200, 0x0200, 0x0200,
+ /* M */ 0x03FE, 0x000E, 0x001C, 0x0038, 0x0070, 0x0030, 0x0018, 0x000C, 0x03FE, 0x03FE,
+ /* N */ 0x03FE, 0x000E, 0x001C, 0x0070, 0x01E0, 0x0380, 0x03FE,
+ /* O */ 0x01FC, 0x03FE, 0x0202, 0x0202, 0x0202, 0x0202, 0x03FE, 0x01FC,
+ /* P */ 0x03FE, 0x03FE, 0x0042, 0x0042, 0x0042, 0x007E, 0x003C,
+ /* Q */ 0x01FC, 0x03FE, 0x0202, 0x0202, 0x0602, 0x0E02, 0x0BFE, 0x09FC,
+ /* R */ 0x03FE, 0x03FE, 0x0022, 0x0062, 0x00E2, 0x01BE, 0x031C, 0x0200,
+ /* S */ 0x019C, 0x023E, 0x0222, 0x0222, 0x0222, 0x03E2, 0x01CC,
+ /* T */ 0x0002, 0x0002, 0x03FE, 0x03FE, 0x0002, 0x0002,
+ /* U */ 0x01FE, 0x03FE, 0x0200, 0x0200, 0x0200, 0x03FE, 0x01FE,
+ /* V */ 0x000E, 0x007E, 0x03F0, 0x0380, 0x03F0, 0x007E, 0x000E,
+ /* W */ 0x001E, 0x00FE, 0x03E0, 0x03E0, 0x00FC, 0x000E, 0x00FC, 0x03E0, 0x03E0, 0x00FE, 0x001E,
+ /* X */ 0x0306, 0x038E, 0x00F8, 0x0070, 0x00F8, 0x038E, 0x0306,
+ /* Y */ 0x000E, 0x003E, 0x03F0, 0x03F0, 0x003E, 0x000E,
+ /* Z */ 0x0382, 0x03C2, 0x0262, 0x0232, 0x021E, 0x020E,
+ /* [ */ 0x0FFF, 0x0FFF, 0x0801, 0x0801,
+ /* \ */ 0x0003, 0x001C, 0x0060, 0x0380, 0x0C00,
+ /* ] */ 0x0801, 0x0801, 0x0FFF, 0x0FFF,
+ /* ^ */ 0x0000, 0x0010, 0x0008, 0x0004, 0x0002, 0x0002, 0x0004, 0x0008, 0x0010,
+ /* _ */ 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800,
+ /* ` */ 0x0000, 0x0000, 0x0001, 0x0003, 0x0002,
+ /* a */ 0x0180, 0x03D0, 0x0248, 0x0248, 0x03F8, 0x03F0,
+ /* b */ 0x03FF, 0x03FF, 0x0210, 0x0208, 0x0208, 0x03F8, 0x01F0,
+ /* c */ 0x01F0, 0x03F8, 0x0208, 0x0208, 0x0208,
+ /* d */ 0x01F0, 0x03F8, 0x0208, 0x0208, 0x0108, 0x03FF, 0x03FF,
+ /* e */ 0x01F0, 0x03F8, 0x0248, 0x0248, 0x0278, 0x0170,
+ /* f */ 0x0008, 0x03FE, 0x03FF, 0x0009, 0x0001,
+ /* g */ 0x01F0, 0x0BF8, 0x0A08, 0x0A08, 0x0908, 0x0FF8, 0x07F8,
+ /* h */ 0x03FF, 0x03FF, 0x0010, 0x0008, 0x0008, 0x03F8, 0x03F0,
+ /* i */ 0x03FA, 0x03FA,
+ /* j */ 0x0808, 0x0FFA, 0x07FA,
+ /* k */ 0x03FF, 0x03FF, 0x00E0, 0x01B0, 0x0318, 0x0208,
+ /* l */ 0x03FF, 0x03FF,
+ /* m */ 0x03F8, 0x03F8, 0x0008, 0x0008, 0x03F8, 0x03F0, 0x0008, 0x0008, 0x03F8, 0x03F0,
+ /* n */ 0x03F8, 0x03F8, 0x0010, 0x0008, 0x0008, 0x03F8, 0x03F0,
+ /* o */ 0x01F0, 0x03F8, 0x0208, 0x0208, 0x0208, 0x03F8, 0x01F0,
+ /* p */ 0x0FF8, 0x0FF8, 0x0210, 0x0208, 0x0208, 0x03F8, 0x01F0,
+ /* q */ 0x01F0, 0x03F8, 0x0208, 0x0208, 0x0108, 0x0FF8, 0x0FF8,
+ /* r */ 0x03F8, 0x03F8, 0x0010, 0x0018,
+ /* s */ 0x0130, 0x0278, 0x0248, 0x03C8, 0x0190,
+ /* t */ 0x0008, 0x01FE, 0x03FE, 0x0208, 0x0208,
+ /* u */ 0x01F8, 0x03F8, 0x0200, 0x0200, 0x0100, 0x03F8, 0x03F8,
+ /* v */ 0x0038, 0x00F8, 0x03C0, 0x03C0, 0x00F8, 0x0038,
+ /* w */ 0x0018, 0x00F8, 0x03E0, 0x0380, 0x00F8, 0x00F8, 0x0380, 0x03E0, 0x00F8, 0x0018,
+ /* x */ 0x0318, 0x03B8, 0x00E0, 0x00E0, 0x03B8, 0x0318,
+ /* y */ 0x0038, 0x0CF8, 0x0FC0, 0x03C0, 0x00F8, 0x0038,
+ /* z */ 0x0388, 0x03C8, 0x0268, 0x0238, 0x0218,
+ /* { */ 0x0020, 0x0020, 0x07FE, 0x0FDF, 0x0801, 0x0801,
+ /* | */ 0x0000, 0x0000, 0x0FFF, 0x0FFF,
+ /* } */ 0x0801, 0x0801, 0x0FDF, 0x07FE, 0x0020, 0x0020,
+ /* ~ */ 0x00E0, 0x0030, 0x0030, 0x0030, 0x0060, 0x00C0, 0x00C0, 0x00C0, 0x0070
+ };
+#endif
+
+/* fontUI1 - UI Font 1 Medium Bold */
+#if GDISP_INCLUDE_FONT_UI1
+ /* Forward Declarations of internal arrays */
+ static const uint8_t fontUI1_Widths[];
+ static const uint16_t fontUI1_Offsets[];
+ static const fontcolumn_t fontUI1_Data[];
+
+ FONT_DECL const struct font fontUI1 = {
+ "UI1",
+ 13, 0, 15, 2, 3, 13, ' ', '~', 1, 1,
+ fontUI1_Widths,
+ fontUI1_Offsets,
+ fontUI1_Data};
+ FONT_DECL const struct font fontUI1Double = {
+ "UI1 Double",
+ 13, 0, 15, 2, 3, 13, ' ', '~', 2, 2,
+ fontUI1_Widths,
+ fontUI1_Offsets,
+ fontUI1_Data};
+ FONT_DECL const struct font fontUI1Narrow = {
+ "UI1 Narrow",
+ 13, 0, 15, 2, 3, 13, ' ', '~', 1, 2,
+ fontUI1_Widths,
+ fontUI1_Offsets,
+ fontUI1_Data};
+
+ static const uint8_t fontUI1_Widths[] = {
+ 3, 3, 6, 8, 7, 13, 9, 3, 5, 5, 6, 8, 3, 5, 3, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 8, 8, 8, 6,
+ 10, 8, 7, 7, 8, 7, 7, 8, 8, 5, 5, 7, 7, 9, 8, 8,
+ 7, 8, 8, 7, 8, 8, 7, 11, 7, 7, 7, 5, 7, 5, 9, 8,
+ 5, 7, 7, 6, 7, 7, 5, 7, 7, 3, 4, 7, 3, 11, 7, 7,
+ 7, 7, 6, 6, 5, 7, 7, 9, 7, 7, 6, 7, 4, 7, 8, 0
+ };
+ static const uint16_t fontUI1_Offsets[] = {
+ 0, 3, 6, 12, 20, 27, 40, 49,
+ 52, 57, 62, 68, 76, 79, 84, 87,
+ 94, 101, 108, 115, 122, 129, 136, 143,
+ 150, 157, 164, 167, 170, 178, 186, 194,
+ 200, 210, 218, 225, 232, 240, 247, 254,
+ 262, 270, 275, 280, 287, 294, 303, 311,
+ 319, 326, 334, 342, 349, 357, 365, 372,
+ 383, 390, 397, 404, 409, 416, 421, 430,
+ 438, 443, 450, 457, 463, 470, 477, 482,
+ 489, 496, 499, 503, 510, 513, 524, 531,
+ 538, 545, 552, 558, 564, 569, 576, 583,
+ 592, 599, 606, 612, 619, 623, 630, 0
+ };
+ static const fontcolumn_t fontUI1_Data[] = {
+ /* */ 0x0000, 0x0000, 0x0000,
+ /* ! */ 0x0000, 0x02FC, 0x02FC,
+ /* " */ 0x0000, 0x000E, 0x000E, 0x0000, 0x000E, 0x000E,
+ /* # */ 0x0000, 0x0080, 0x0390, 0x00F0, 0x039C, 0x00F0, 0x009C, 0x0010,
+ /* $ */ 0x0000, 0x0130, 0x0278, 0x0FC8, 0x027E, 0x03C8, 0x0190,
+ /* % */ 0x0000, 0x0038, 0x007C, 0x0044, 0x007C, 0x0338, 0x00C0, 0x0030, 0x01CC, 0x03E0, 0x0220, 0x03E0,
+ 0x01C0,
+ /* & */ 0x0000, 0x01D8, 0x03FC, 0x0224, 0x027C, 0x02D8, 0x0180, 0x0360, 0x0220,
+ /* ' */ 0x0000, 0x000E, 0x000E,
+ /* ( */ 0x0000, 0x01F0, 0x07FC, 0x0E0E, 0x0802,
+ /* ) */ 0x0000, 0x0802, 0x0E0E, 0x07FC, 0x01F0,
+ /* * */ 0x0000, 0x0014, 0x0008, 0x003E, 0x0008, 0x0014,
+ /* + */ 0x0000, 0x0040, 0x0040, 0x0040, 0x03F8, 0x0040, 0x0040, 0x0040,
+ /* , */ 0x0000, 0x0F00, 0x0700,
+ /* - */ 0x0000, 0x0040, 0x0040, 0x0040, 0x0040,
+ /* . */ 0x0000, 0x0300, 0x0300,
+ /* / */ 0x0000, 0x0C00, 0x0F00, 0x03E0, 0x00F8, 0x001E, 0x0006,
+ /* 0 */ 0x0000, 0x01F8, 0x03FC, 0x0204, 0x0204, 0x03FC, 0x01F8,
+ /* 1 */ 0x0000, 0x0000, 0x0208, 0x03FC, 0x03FC, 0x0200, 0x0000,
+ /* 2 */ 0x0000, 0x0308, 0x038C, 0x02C4, 0x0264, 0x023C, 0x0218,
+ /* 3 */ 0x0000, 0x0108, 0x030C, 0x0224, 0x0224, 0x03FC, 0x01D8,
+ /* 4 */ 0x0000, 0x00C0, 0x00A0, 0x0090, 0x03F8, 0x03FC, 0x0080,
+ /* 5 */ 0x0000, 0x0100, 0x033C, 0x023C, 0x0224, 0x03E4, 0x01C4,
+ /* 6 */ 0x0000, 0x01F0, 0x03F8, 0x022C, 0x0224, 0x03E4, 0x01C0,
+ /* 7 */ 0x0000, 0x0004, 0x0304, 0x03C4, 0x00F4, 0x003C, 0x000C,
+ /* 8 */ 0x0000, 0x01D8, 0x03FC, 0x0224, 0x0224, 0x03FC, 0x01D8,
+ /* 9 */ 0x0000, 0x0038, 0x027C, 0x0244, 0x0344, 0x01FC, 0x00F8,
+ /* : */ 0x0000, 0x0330, 0x0330,
+ /* ; */ 0x0000, 0x0F30, 0x0730,
+ /* < */ 0x0000, 0x0040, 0x00A0, 0x00A0, 0x0110, 0x0110, 0x0208, 0x0208,
+ /* = */ 0x0000, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090, 0x0090,
+ /* > */ 0x0000, 0x0208, 0x0208, 0x0110, 0x0110, 0x00A0, 0x00A0, 0x0040,
+ /* ? */ 0x0000, 0x0008, 0x02C4, 0x02E4, 0x003C, 0x0018,
+ /* @ */ 0x0000, 0x01F0, 0x0208, 0x04E4, 0x05F4, 0x0514, 0x05F4, 0x05F4, 0x0104, 0x00F8,
+ /* A */ 0x0000, 0x0380, 0x03F0, 0x00FC, 0x008C, 0x00FC, 0x03F0, 0x0380,
+ /* B */ 0x0000, 0x03FC, 0x03FC, 0x0224, 0x0224, 0x03FC, 0x01D8,
+ /* C */ 0x0000, 0x01F8, 0x03FC, 0x0204, 0x0204, 0x0204, 0x0108,
+ /* D */ 0x0000, 0x03FC, 0x03FC, 0x0204, 0x0204, 0x030C, 0x01F8, 0x00F0,
+ /* E */ 0x0000, 0x03FC, 0x03FC, 0x0224, 0x0224, 0x0224, 0x0224,
+ /* F */ 0x0000, 0x03FC, 0x03FC, 0x0024, 0x0024, 0x0024, 0x0024,
+ /* G */ 0x0000, 0x01F8, 0x03FC, 0x0204, 0x0204, 0x0244, 0x03C4, 0x03C8,
+ /* H */ 0x0000, 0x03FC, 0x03FC, 0x0020, 0x0020, 0x0020, 0x03FC, 0x03FC,
+ /* I */ 0x0000, 0x0204, 0x03FC, 0x03FC, 0x0204,
+ /* J */ 0x0200, 0x0204, 0x0204, 0x03FC, 0x01FC,
+ /* K */ 0x0000, 0x03FC, 0x03FC, 0x00F0, 0x0198, 0x030C, 0x0204,
+ /* L */ 0x0000, 0x03FC, 0x03FC, 0x0200, 0x0200, 0x0200, 0x0200,
+ /* M */ 0x0000, 0x03FC, 0x001C, 0x0038, 0x0070, 0x0020, 0x0010, 0x03F8, 0x03FC,
+ /* N */ 0x0000, 0x03FC, 0x0018, 0x0030, 0x0060, 0x00C0, 0x0180, 0x03FC,
+ /* O */ 0x0000, 0x01F8, 0x03FC, 0x0204, 0x0204, 0x0204, 0x03FC, 0x01F8,
+ /* P */ 0x0000, 0x03FC, 0x03FC, 0x0044, 0x0044, 0x007C, 0x0038,
+ /* Q */ 0x0000, 0x01F8, 0x03FC, 0x0204, 0x0604, 0x0E04, 0x0BFC, 0x09F8,
+ /* R */ 0x0000, 0x03FC, 0x03FC, 0x0044, 0x00C4, 0x01FC, 0x0338, 0x0200,
+ /* S */ 0x0000, 0x0138, 0x027C, 0x0264, 0x0264, 0x03E4, 0x01C8,
+ /* T */ 0x0004, 0x0004, 0x0004, 0x03FC, 0x03FC, 0x0004, 0x0004, 0x0004,
+ /* U */ 0x0000, 0x01FC, 0x03FC, 0x0200, 0x0200, 0x0200, 0x03FC, 0x01FC,
+ /* V */ 0x0000, 0x001C, 0x00FC, 0x03E0, 0x03E0, 0x00FC, 0x001C,
+ /* W */ 0x0000, 0x001C, 0x00FC, 0x03E0, 0x03C0, 0x007C, 0x007C, 0x03C0, 0x03E0, 0x00FC, 0x001C,
+ /* X */ 0x0000, 0x030C, 0x039C, 0x00F0, 0x00F0, 0x039C, 0x030C,
+ /* Y */ 0x0000, 0x000C, 0x003C, 0x03F0, 0x03F0, 0x003C, 0x000C,
+ /* Z */ 0x0000, 0x0384, 0x03C4, 0x02E4, 0x0274, 0x023C, 0x021C,
+ /* [ */ 0x0000, 0x0FFE, 0x0FFE, 0x0802, 0x0802,
+ /* \ */ 0x0000, 0x0006, 0x001E, 0x00F8, 0x03E0, 0x0F00, 0x0C00,
+ /* ] */ 0x0000, 0x0802, 0x0802, 0x0FFE, 0x0FFE,
+ /* ^ */ 0x0000, 0x0020, 0x0030, 0x0018, 0x000C, 0x000C, 0x0018, 0x0030, 0x0020,
+ /* _ */ 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800,
+ /* ` */ 0x0000, 0x0000, 0x0002, 0x0006, 0x0004,
+ /* a */ 0x0000, 0x0180, 0x03D0, 0x0250, 0x0250, 0x03F0, 0x03E0,
+ /* b */ 0x0000, 0x03FE, 0x03FE, 0x0210, 0x0210, 0x03F0, 0x01E0,
+ /* c */ 0x0000, 0x01E0, 0x03F0, 0x0210, 0x0210, 0x0210,
+ /* d */ 0x0000, 0x01E0, 0x03F0, 0x0210, 0x0210, 0x03FE, 0x03FE,
+ /* e */ 0x0000, 0x01E0, 0x03F0, 0x0250, 0x0250, 0x0270, 0x0160,
+ /* f */ 0x0010, 0x03FC, 0x03FE, 0x0012, 0x0012,
+ /* g */ 0x0000, 0x01E0, 0x0BF0, 0x0A10, 0x0A10, 0x0FF0, 0x07F0,
+ /* h */ 0x0000, 0x03FE, 0x03FE, 0x0010, 0x0010, 0x03F0, 0x03E0,
+ /* i */ 0x0000, 0x03F4, 0x03F4,
+ /* j */ 0x0800, 0x0810, 0x0FF4, 0x07F4,
+ /* k */ 0x0000, 0x03FE, 0x03FE, 0x00C0, 0x01E0, 0x0330, 0x0210,
+ /* l */ 0x0000, 0x03FE, 0x03FE,
+ /* m */ 0x0000, 0x03F0, 0x03F0, 0x0010, 0x0010, 0x03F0, 0x03E0, 0x0010, 0x0010, 0x03F0, 0x03E0,
+ /* n */ 0x0000, 0x03F0, 0x03F0, 0x0010, 0x0010, 0x03F0, 0x03E0,
+ /* o */ 0x0000, 0x01E0, 0x03F0, 0x0210, 0x0210, 0x03F0, 0x01E0,
+ /* p */ 0x0000, 0x0FF0, 0x0FF0, 0x0210, 0x0210, 0x03F0, 0x01E0,
+ /* q */ 0x0000, 0x01E0, 0x03F0, 0x0210, 0x0210, 0x0FF0, 0x0FF0,
+ /* r */ 0x0000, 0x03F0, 0x03F0, 0x0020, 0x0030, 0x0030,
+ /* s */ 0x0000, 0x0260, 0x02F0, 0x02D0, 0x03D0, 0x0190,
+ /* t */ 0x0010, 0x01FC, 0x03FC, 0x0210, 0x0210,
+ /* u */ 0x0000, 0x01F0, 0x03F0, 0x0200, 0x0200, 0x03F0, 0x03F0,
+ /* v */ 0x0000, 0x0070, 0x01F0, 0x0380, 0x0380, 0x01F0, 0x0070,
+ /* w */ 0x0000, 0x00F0, 0x03F0, 0x0300, 0x00F0, 0x00F0, 0x0300, 0x03F0, 0x00F0,
+ /* x */ 0x0000, 0x0330, 0x03F0, 0x00C0, 0x00C0, 0x03F0, 0x0330,
+ /* y */ 0x0000, 0x0030, 0x0CF0, 0x0FC0, 0x03C0, 0x00F0, 0x0030,
+ /* z */ 0x0000, 0x0310, 0x0390, 0x02D0, 0x0270, 0x0230,
+ /* { */ 0x0000, 0x0040, 0x0040, 0x07FC, 0x0FBE, 0x0802, 0x0802,
+ /* | */ 0x0000, 0x0000, 0x0FFE, 0x0FFE,
+ /* } */ 0x0000, 0x0802, 0x0802, 0x0FBE, 0x07FC, 0x0040, 0x0040,
+ /* ~ */ 0x0000, 0x01C0, 0x0020, 0x0020, 0x00C0, 0x0100, 0x0100, 0x00E0
+ };
+#endif
+
+/* fontUI1 - UI Font 2 Medium Bold */
+#if GDISP_INCLUDE_FONT_UI2
+ /* Forward Declarations of internal arrays */
+ static const uint8_t fontUI2_Widths[];
+ static const uint16_t fontUI2_Offsets[];
+ static const fontcolumn_t fontUI2_Data[];
+
+ FONT_DECL const struct font fontUI2 = {
+ "UI2",
+ 11, 1, 13, 2, 2, 12, ' ', '~', 1, 1,
+ fontUI2_Widths,
+ fontUI2_Offsets,
+ fontUI2_Data};
+ FONT_DECL const struct font fontUI2Double = {
+ "UI2 Double",
+ 11, 1, 13, 2, 2, 12, ' ', '~', 2, 2,
+ fontUI2_Widths,
+ fontUI2_Offsets,
+ fontUI2_Data};
+ FONT_DECL const struct font fontUI2Narrow = {
+ "UI2 Narrow",
+ 11, 1, 13, 2, 2, 12, ' ', '~', 1, 2,
+ fontUI2_Widths,
+ fontUI2_Offsets,
+ fontUI2_Data};
+
+ static const uint8_t fontUI2_Widths[] = {
+ 2, 2, 5, 8, 6, 12, 8, 2, 4, 4, 6, 8, 2, 4, 2, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 8, 8, 8, 5,
+ 9, 7, 6, 6, 7, 5, 5, 7, 7, 4, 5, 6, 5, 9, 6, 7,
+ 6, 7, 7, 6, 6, 7, 6, 10, 6, 6, 6, 4, 5, 4, 7, 7,
+ 4, 6, 6, 5, 6, 6, 4, 6, 6, 2, 3, 6, 2, 10, 6, 6,
+ 6, 6, 4, 5, 4, 6, 6, 8, 6, 6, 5, 6, 4, 6, 8, 0
+ };
+ static const uint16_t fontUI2_Offsets[] = {
+ 0, 2, 4, 9, 17, 23, 35, 43,
+ 45, 49, 53, 59, 67, 69, 73, 75,
+ 80, 86, 92, 98, 104, 110, 116, 122,
+ 128, 134, 140, 142, 144, 152, 160, 168,
+ 173, 182, 189, 195, 201, 208, 213, 218,
+ 225, 232, 236, 241, 247, 252, 261, 267,
+ 274, 280, 287, 294, 300, 306, 313, 319,
+ 329, 335, 341, 347, 351, 356, 360, 367,
+ 374, 378, 384, 390, 395, 401, 407, 411,
+ 417, 423, 425, 428, 434, 436, 446, 452,
+ 458, 464, 470, 474, 479, 483, 489, 495,
+ 503, 509, 515, 520, 526, 530, 536, 0
+ };
+ static const fontcolumn_t fontUI2_Data[] = {
+ /* */ 0x0000, 0x0000,
+ /* ! */ 0x017E, 0x017E,
+ /* " */ 0x0007, 0x0007, 0x0000, 0x0007, 0x0007,
+ /* # */ 0x00C0, 0x03D8, 0x00F8, 0x00DE, 0x03D8, 0x00F8, 0x00DE, 0x0018,
+ /* $ */ 0x0098, 0x013C, 0x07E4, 0x013F, 0x01E4, 0x00C8,
+ /* % */ 0x001C, 0x003E, 0x0022, 0x003E, 0x019C, 0x0060, 0x0018, 0x00E6, 0x01F0, 0x0110, 0x01F0, 0x00E0,
+ /* & */ 0x00EC, 0x01FE, 0x0112, 0x013E, 0x016C, 0x00C0, 0x01B0, 0x0110,
+ /* ' */ 0x0007, 0x0007,
+ /* ( */ 0x00F8, 0x03FE, 0x0707, 0x0401,
+ /* ) */ 0x0401, 0x0707, 0x03FE, 0x00F8,
+ /* * */ 0x000A, 0x0004, 0x001F, 0x001F, 0x0004, 0x000A,
+ /* + */ 0x0000, 0x0020, 0x0020, 0x0020, 0x01FC, 0x0020, 0x0020, 0x0020,
+ /* , */ 0x0780, 0x0380,
+ /* - */ 0x0020, 0x0020, 0x0020, 0x0020,
+ /* . */ 0x0180, 0x0180,
+ /* / */ 0x0600, 0x0180, 0x0070, 0x000C, 0x0003,
+ /* 0 */ 0x00FC, 0x01FE, 0x0102, 0x0102, 0x01FE, 0x00FC,
+ /* 1 */ 0x0000, 0x0104, 0x01FE, 0x01FE, 0x0100, 0x0000,
+ /* 2 */ 0x0184, 0x01C6, 0x0162, 0x0132, 0x011E, 0x010C,
+ /* 3 */ 0x0084, 0x0186, 0x0112, 0x0112, 0x01FE, 0x00EC,
+ /* 4 */ 0x0060, 0x0050, 0x0048, 0x01FC, 0x01FE, 0x0040,
+ /* 5 */ 0x0080, 0x019E, 0x011E, 0x0112, 0x01F2, 0x00E2,
+ /* 6 */ 0x00FC, 0x01FE, 0x0112, 0x0112, 0x01F2, 0x00E0,
+ /* 7 */ 0x0002, 0x0002, 0x01C2, 0x01FA, 0x003E, 0x0006,
+ /* 8 */ 0x00EC, 0x01FE, 0x0112, 0x0112, 0x01FE, 0x00EC,
+ /* 9 */ 0x001C, 0x013E, 0x0122, 0x0122, 0x01FE, 0x00FC,
+ /* : */ 0x0198, 0x0198,
+ /* ; */ 0x0798, 0x0398,
+ /* < */ 0x0000, 0x0020, 0x0050, 0x0050, 0x0088, 0x0088, 0x0104, 0x0104,
+ /* = */ 0x0000, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ /* > */ 0x0000, 0x0104, 0x0104, 0x0088, 0x0088, 0x0050, 0x0050, 0x0020,
+ /* ? */ 0x0004, 0x0162, 0x0172, 0x001E, 0x000C,
+ /* @ */ 0x00F8, 0x0104, 0x0272, 0x02FA, 0x028A, 0x027A, 0x02FA, 0x0084, 0x0078,
+ /* A */ 0x01C0, 0x01F8, 0x007E, 0x0046, 0x007E, 0x01F8, 0x01C0,
+ /* B */ 0x01FE, 0x01FE, 0x0112, 0x0112, 0x01FE, 0x00EC,
+ /* C */ 0x00FC, 0x01FE, 0x0102, 0x0102, 0x0102, 0x0102,
+ /* D */ 0x01FE, 0x01FE, 0x0102, 0x0102, 0x0186, 0x00FC, 0x0078,
+ /* E */ 0x01FE, 0x01FE, 0x0112, 0x0112, 0x0112,
+ /* F */ 0x01FE, 0x01FE, 0x0012, 0x0012, 0x0012,
+ /* G */ 0x00FC, 0x01FE, 0x0102, 0x0102, 0x0122, 0x01E2, 0x01E2,
+ /* H */ 0x01FE, 0x01FE, 0x0010, 0x0010, 0x0010, 0x01FE, 0x01FE,
+ /* I */ 0x0102, 0x01FE, 0x01FE, 0x0102,
+ /* J */ 0x0100, 0x0102, 0x0102, 0x01FE, 0x00FE,
+ /* K */ 0x01FE, 0x01FE, 0x0078, 0x00CC, 0x0186, 0x0102,
+ /* L */ 0x01FE, 0x01FE, 0x0100, 0x0100, 0x0100,
+ /* M */ 0x01FE, 0x000E, 0x001C, 0x0038, 0x0030, 0x0018, 0x000C, 0x01FE, 0x01FE,
+ /* N */ 0x01FE, 0x000E, 0x001C, 0x0038, 0x0070, 0x01FE,
+ /* O */ 0x00FC, 0x01FE, 0x0102, 0x0102, 0x0102, 0x01FE, 0x00FC,
+ /* P */ 0x01FE, 0x01FE, 0x0022, 0x0022, 0x003E, 0x001C,
+ /* Q */ 0x00FC, 0x01FE, 0x0102, 0x0302, 0x0702, 0x05FE, 0x04FC,
+ /* R */ 0x01FE, 0x01FE, 0x0022, 0x0062, 0x00FE, 0x019C, 0x0100,
+ /* S */ 0x011C, 0x013E, 0x0132, 0x0132, 0x01F2, 0x00E2,
+ /* T */ 0x0002, 0x0002, 0x01FE, 0x01FE, 0x0002, 0x0002,
+ /* U */ 0x00FE, 0x01FE, 0x0100, 0x0100, 0x0100, 0x01FE, 0x00FE,
+ /* V */ 0x000E, 0x007E, 0x01F0, 0x01F0, 0x007E, 0x000E,
+ /* W */ 0x000E, 0x007E, 0x01F0, 0x01E0, 0x003E, 0x003E, 0x01E0, 0x01F0, 0x007E, 0x000E,
+ /* X */ 0x0186, 0x01CE, 0x0078, 0x0078, 0x01CE, 0x0186,
+ /* Y */ 0x0006, 0x001E, 0x01F8, 0x01F8, 0x001E, 0x0006,
+ /* Z */ 0x01C2, 0x01E2, 0x0172, 0x013A, 0x011E, 0x010E,
+ /* [ */ 0x07FF, 0x07FF, 0x0401, 0x0401,
+ /* \ */ 0x0003, 0x000C, 0x0070, 0x0180, 0x0600,
+ /* ] */ 0x0401, 0x0401, 0x07FF, 0x07FF,
+ /* ^ */ 0x0010, 0x0008, 0x0004, 0x0002, 0x0004, 0x0008, 0x0010,
+ /* _ */ 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
+ /* ` */ 0x0000, 0x0001, 0x0003, 0x0002,
+ /* a */ 0x00C0, 0x01E8, 0x0128, 0x0128, 0x01F8, 0x01F0,
+ /* b */ 0x01FF, 0x01FF, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* c */ 0x00F0, 0x01F8, 0x0108, 0x0108, 0x0108,
+ /* d */ 0x00F0, 0x01F8, 0x0108, 0x0108, 0x01FF, 0x01FF,
+ /* e */ 0x00F0, 0x01F8, 0x0128, 0x0128, 0x0138, 0x0130,
+ /* f */ 0x01FE, 0x01FF, 0x0009, 0x0001,
+ /* g */ 0x00F0, 0x05F8, 0x0508, 0x0508, 0x07F8, 0x03F8,
+ /* h */ 0x01FF, 0x01FF, 0x0008, 0x0008, 0x01F8, 0x01F0,
+ /* i */ 0x01FA, 0x01FA,
+ /* j */ 0x0408, 0x07FA, 0x03FA,
+ /* k */ 0x01FF, 0x01FF, 0x0060, 0x00F0, 0x0198, 0x0108,
+ /* l */ 0x01FF, 0x01FF,
+ /* m */ 0x01F8, 0x01F8, 0x0008, 0x0008, 0x01F8, 0x01F0, 0x0008, 0x0008, 0x01F8, 0x01F0,
+ /* n */ 0x01F8, 0x01F8, 0x0008, 0x0008, 0x01F8, 0x01F0,
+ /* o */ 0x00F0, 0x01F8, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* p */ 0x07F8, 0x07F8, 0x0108, 0x0108, 0x01F8, 0x00F0,
+ /* q */ 0x00F0, 0x01F8, 0x0108, 0x0108, 0x07F8, 0x07F8,
+ /* r */ 0x01F8, 0x01F8, 0x0010, 0x0018,
+ /* s */ 0x0130, 0x0178, 0x0168, 0x01E8, 0x00C8,
+ /* t */ 0x00FE, 0x01FE, 0x0108, 0x0108,
+ /* u */ 0x00F8, 0x01F8, 0x0100, 0x0100, 0x01F8, 0x01F8,
+ /* v */ 0x0018, 0x0078, 0x01E0, 0x01E0, 0x0078, 0x0018,
+ /* w */ 0x0078, 0x01F8, 0x01C0, 0x0078, 0x0078, 0x01C0, 0x01F8, 0x0078,
+ /* x */ 0x0198, 0x01F8, 0x0060, 0x0060, 0x01F8, 0x0198,
+ /* y */ 0x0018, 0x0678, 0x07E0, 0x01E0, 0x0078, 0x0018,
+ /* z */ 0x0188, 0x01C8, 0x0168, 0x0138, 0x0118,
+ /* { */ 0x0020, 0x0020, 0x03FE, 0x07DF, 0x0401, 0x0401,
+ /* | */ 0x0000, 0x0000, 0x07FF, 0x07FF,
+ /* } */ 0x0401, 0x0401, 0x07DF, 0x03FE, 0x0020, 0x0020,
+ /* ~ */ 0x0060, 0x0010, 0x0010, 0x0030, 0x0060, 0x0040, 0x0040, 0x0030
+ };
+#endif
+
+/*
+ fontLargeNumbers:
+ Large numbers font, height = 16 (including the decenders)
+ Characters include: 0 - 9, -, +, ., %, :, Space, Comma
+*/
+#if GDISP_INCLUDE_FONT_LARGENUMBERS
+ /* Forward Declarations of internal arrays */
+ static const uint8_t fontLargeNumbers_Widths[];
+ static const uint16_t fontLargeNumbers_Offsets[];
+ static const fontcolumn_t fontLargeNumbers_Data[];
+
+ FONT_DECL const struct font fontLargeNumbers = {
+ "LargeNumbers",
+ 16, 2, 21, 1, 3, 15, '%', ':', 1, 1,
+ fontLargeNumbers_Widths,
+ fontLargeNumbers_Offsets,
+ fontLargeNumbers_Data};
+ FONT_DECL const struct font fontLargeNumbersDouble = {
+ "LargeNumbers Double",
+ 16, 2, 21, 1, 3, 15, '%', ':', 2, 2,
+ fontLargeNumbers_Widths,
+ fontLargeNumbers_Offsets,
+ fontLargeNumbers_Data};
+ FONT_DECL const struct font fontLargeNumbersNarrow = {
+ "LargeNumbers Narrow", 16, 2, 21, 1, 3, 15, '%', ':', 1, 2,
+ fontLargeNumbers_Widths,
+ fontLargeNumbers_Offsets,
+ fontLargeNumbers_Data};
+
+ static const uint8_t fontLargeNumbers_Widths[] = {
+ 15, 0, 0, 0, 0, 0, 11, 3, 6, 3, 0, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 4, 0, 0
+ };
+ static const uint16_t fontLargeNumbers_Offsets[] = {
+ 0, 0, 0, 0, 0, 0, 15, 26,
+ 29, 35, 0, 38, 48, 58, 68, 78,
+ 88, 98, 108, 118, 128, 138, 0, 0
+ };
+ static const fontcolumn_t fontLargeNumbers_Data[] = {
+ /* % */ 0x007E, 0x00FF, 0x00C3, 0x80C3, 0xE0FF, 0x7C7E, 0x1F00, 0x07C0, 0x00F0, 0x7E3E, 0xFF0F, 0xC303,
+ 0xC300, 0xFF00, 0x7E00,
+ /* + */ 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x1FFC, 0x1FFC, 0x1FFC, 0x01C0, 0x01C0, 0x01C0, 0x01C0,
+ /* , */ 0x7000, 0x7000, 0xF000,
+ /* - */ 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700,
+ /* . */ 0x7000, 0x7000, 0x7000,
+ /* 0 */ 0x0FF8, 0x3FFE, 0x3FFE, 0x7007, 0x6003, 0x6003, 0x7007, 0x3FFE, 0x3FFE, 0x0FF8,
+ /* 1 */ 0x0000, 0x0070, 0x0038, 0x0038, 0x001C, 0x7FFF, 0x7FFF, 0x7FFF, 0x0000, 0x0000,
+ /* 2 */ 0x600C, 0x700E, 0x7C0F, 0x7E07, 0x6F03, 0x6783, 0x63C7, 0x61FF, 0x60FE, 0x603C,
+ /* 3 */ 0x180C, 0x380E, 0x780F, 0x70C3, 0x60C3, 0x60E3, 0x71FF, 0x3FFE, 0x3F3C, 0x0E00,
+ /* 4 */ 0x0F00, 0x0DC0, 0x0CE0, 0x0C38, 0x0C1E, 0x7FFF, 0x7FFF, 0x7FFF, 0x0C00, 0x0C00,
+ /* 5 */ 0x18C0, 0x38FC, 0x78FF, 0x707F, 0x6063, 0x6063, 0x70E3, 0x3FE3, 0x3FC3, 0x0F80,
+ /* 6 */ 0x0FF8, 0x3FFE, 0x3FFE, 0x70C7, 0x6063, 0x6063, 0x70E7, 0x3FEF, 0x3FC6, 0x0F04,
+ /* 7 */ 0x0003, 0x0003, 0x7803, 0x7F03, 0x7FC3, 0x07F3, 0x00FB, 0x003F, 0x000F, 0x0007,
+ /* 8 */ 0x1E1C, 0x3F3E, 0x7FFF, 0x71E7, 0x60C3, 0x60C3, 0x71E7, 0x7FFF, 0x3F3E, 0x1E1C,
+ /* 9 */ 0x1078, 0x39FE, 0x7BFE, 0x7387, 0x6303, 0x6303, 0x7187, 0x3FFE, 0x3FFE, 0x0FF8,
+ /* : */ 0x0000, 0x0E38, 0x0E38, 0x0E38
+ };
+#endif
+
+static const struct font *BuiltinFontTable[] = {
+ #if GDISP_INCLUDE_FONT_SMALL
+ &fontSmall, &fontSmallDouble, &fontSmallNarrow,
+ #endif
+ #if GDISP_INCLUDE_FONT_LARGER
+ &fontLarger, &fontLargerDouble, &fontLargerNarrow,
+ #endif
+ #if GDISP_INCLUDE_FONT_UI1
+ &fontUI1, &fontUI1Double, &fontUI1Narrow,
+ #endif
+ #if GDISP_INCLUDE_FONT_UI2
+ &fontUI2, &fontUI2Double, &fontUI2Narrow,
+ #endif
+ #if GDISP_INCLUDE_FONT_LARGENUMBERS
+ &fontLargeNumbers, &fontLargeNumbersDouble, &fontLargeNumbersNarrow,
+ #endif
+ };
+
+/**
+ * Match a pattern against the font name.
+ */
+static bool_t matchfont(const char *pattern, const char *name) {
+ while(1) {
+ switch (pattern[0]) {
+ case '*':
+ if (name[0] == 0)
+ return pattern[1] == 0;
+ if (pattern[1] == name[0])
+ pattern++;
+ else
+ name++;
+ break;
+ case 0:
+ return name[0] == 0;
+ default:
+ if (name[0] != pattern[0])
+ return FALSE;
+ pattern++;
+ name++;
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Find a font and return it.
+ * @details The supplied name is matched against the font name. A '*' will replace 0 or more characters.
+ * @return Returns a font or NULL if no matching font could be found.
+ *
+ * @param[in] name The font name to find.
+ *
+ * @note Wildcard matching will match the shortest possible match.
+ *
+ * @api
+ */
+font_t gdispOpenFont(const char *name) {
+ const struct font **p;
+
+ for(p = BuiltinFontTable; p < BuiltinFontTable+sizeof(BuiltinFontTable)/sizeof(BuiltinFontTable[0]); p++) {
+ if (matchfont(name, p[0]->name))
+ return p[0];
+ }
+ return 0;
+}
+
+/**
+ * @brief Release a font after use.
+ *
+ * @param[in] font The font to release.
+ *
+ * @api
+ */
+void gdispCloseFont(font_t font) {
+ (void) font;
+}
+
+/**
+ * @brief Get the name of the specified font.
+ * @returns The name of the font.
+ *
+ * @param[in] font The font to get the name for.
+ *
+ * @api
+ */
+const char *gdispGetFontName(font_t font) {
+ return font->name;
+}
+
+#endif /* GFX_USE_GDISP && GDISP_NEED_TEXT */
+/** @} */
diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c
new file mode 100644
index 00000000..2d757fcb
--- /dev/null
+++ b/src/gdisp/gdisp.c
@@ -0,0 +1,1268 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gdisp/gdisp.c
+ * @brief GDISP Driver code.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP || defined(__DOXYGEN__)
+
+#ifdef GDISP_NEED_TEXT
+ #include "gdisp/fonts.h"
+#endif
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if GDISP_NEED_MULTITHREAD
+ #if !CH_USE_MUTEXES
+ #error "GDISP: CH_USE_MUTEXES must be defined in chconf.h because GDISP_NEED_MULTITHREAD is defined"
+ #endif
+#endif
+
+#if GDISP_NEED_ASYNC
+ #if !CH_USE_MAILBOXES || !CH_USE_MUTEXES || !CH_USE_SEMAPHORES
+ #error "GDISP: CH_USE_MAILBOXES, CH_USE_SEMAPHORES and CH_USE_MUTEXES must be defined in chconf.h because GDISP_NEED_ASYNC is defined"
+ #endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+#if GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC
+ static Mutex gdispMutex;
+#endif
+
+#if GDISP_NEED_ASYNC
+ #define GDISP_THREAD_STACK_SIZE 512 /* Just a number - not yet a reflection of actual use */
+ #define GDISP_QUEUE_SIZE 8 /* We only allow a short queue */
+
+ static Thread * lldThread;
+ static Mailbox gdispMailbox;
+ static msg_t gdispMailboxQueue[GDISP_QUEUE_SIZE];
+ static Semaphore gdispMsgsSem;
+ static Mutex gdispMsgsMutex;
+ static gdisp_lld_msg_t gdispMsgs[GDISP_QUEUE_SIZE];
+ static WORKING_AREA(waGDISPThread, GDISP_THREAD_STACK_SIZE);
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if GDISP_NEED_ASYNC
+ static msg_t GDISPThreadHandler(void *arg) {
+ (void)arg;
+ gdisp_lld_msg_t *pmsg;
+
+ #if CH_USE_REGISTRY
+ chRegSetThreadName("GDISPAsyncAPI");
+ #endif
+
+ while(1) {
+ /* Wait for msg with work to do. */
+ chMBFetch(&gdispMailbox, (msg_t *)&pmsg, TIME_INFINITE);
+
+ /* OK - we need to obtain the mutex in case a synchronous operation is occurring */
+ chMtxLock(&gdispMutex);
+ GDISP_LLD(msgdispatch)(pmsg);
+ chMtxUnlock();
+
+ /* Mark the message as free */
+ pmsg->action = GDISP_LLD_MSG_NOP;
+ chSemSignal(&gdispMsgsSem);
+ }
+ return 0;
+ }
+
+ static gdisp_lld_msg_t *gdispAllocMsg(gdisp_msgaction_t action) {
+ gdisp_lld_msg_t *p;
+
+ while(1) { /* To be sure, to be sure */
+
+ /* Wait for a slot */
+ chSemWait(&gdispMsgsSem);
+
+ /* Find the slot */
+ chMtxLock(&gdispMsgsMutex);
+ for(p=gdispMsgs; p < &gdispMsgs[GDISP_QUEUE_SIZE]; p++) {
+ if (p->action == GDISP_LLD_MSG_NOP) {
+ /* Allocate it */
+ p->action = action;
+ chMtxUnlock();
+ return p;
+ }
+ }
+ chMtxUnlock();
+
+ /* Oops - none found, try again */
+ chSemSignal(&gdispMsgsSem);
+ }
+ }
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief GDISP Driver initialization.
+ * @note This function is NOT currently implicitly invoked by @p halInit().
+ * It must be called manually.
+ *
+ * @return True if succeeded, False otherwise
+ *
+ * @init
+ */
+ bool_t gdispInit(void) {
+ bool_t res;
+
+ /* Initialise Mutex */
+ chMtxInit(&gdispMutex);
+
+ /* Initialise driver */
+ chMtxLock(&gdispMutex);
+ res = lld_gdisp_init();
+ chMtxUnlock();
+
+ return res;
+ }
+#elif GDISP_NEED_ASYNC
+ bool_t gdispInit(void) {
+ bool_t res;
+ unsigned i;
+
+ /* Mark all the Messages as free */
+ for(i=0; i < GDISP_QUEUE_SIZE; i++)
+ gdispMsgs[i].action = GDISP_LLD_MSG_NOP;
+
+ /* Initialise our Mailbox, Mutex's and Counting Semaphore.
+ * A Mutex is required as well as the Mailbox and Thread because some calls have to be synchronous.
+ * Synchronous calls get handled by the calling thread, asynchronous by our worker thread.
+ */
+ chMBInit(&gdispMailbox, gdispMailboxQueue, sizeof(gdispMailboxQueue)/sizeof(gdispMailboxQueue[0]));
+ chMtxInit(&gdispMutex);
+ chMtxInit(&gdispMsgsMutex);
+ chSemInit(&gdispMsgsSem, GDISP_QUEUE_SIZE);
+
+ lldThread = chThdCreateStatic(waGDISPThread, sizeof(waGDISPThread), NORMALPRIO, GDISPThreadHandler, NULL);
+
+ /* Initialise driver - synchronous */
+ chMtxLock(&gdispMutex);
+ res = lld_gdisp_init();
+ chMtxUnlock();
+
+ return res;
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Test if the GDISP engine is currently drawing.
+ * @note This function will always return FALSE if
+ * GDISP_NEED_ASYNC is not defined.
+ *
+ * @return TRUE if gdisp is busy, FALSE otherwise
+ *
+ * @init
+ */
+ bool_t gdispIsBusy(void) {
+ return FALSE;
+ }
+#elif GDISP_NEED_ASYNC
+ bool_t gdispIsBusy(void) {
+ return chMBGetUsedCountI(&gdispMailbox) != FALSE;
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Clear the display to the specified color.
+ *
+ * @param[in] color The color to use when clearing the screen
+ *
+ * @api
+ */
+ void gdispClear(color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_clear(color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ASYNC
+ void gdispClear(color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CLEAR);
+ p->clear.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Set a pixel in the specified color.
+ *
+ * @param[in] x,y The position to set the pixel.
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawPixel(coord_t x, coord_t y, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_pixel(x, y, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ASYNC
+ void gdispDrawPixel(coord_t x, coord_t y, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWPIXEL);
+ p->drawpixel.x = x;
+ p->drawpixel.y = y;
+ p->drawpixel.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a line.
+ *
+ * @param[in] x0,y0 The start position
+ * @param[in] x1,y1 The end position
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_line(x0, y0, x1, y1, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ASYNC
+ void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWLINE);
+ p->drawline.x0 = x0;
+ p->drawline.y0 = y0;
+ p->drawline.x1 = x1;
+ p->drawline.y1 = y1;
+ p->drawline.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_fill_area(x, y, cx, cy, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ASYNC
+ void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLAREA);
+ p->fillarea.x = x;
+ p->fillarea.y = y;
+ p->fillarea.cx = cx;
+ p->fillarea.cy = cy;
+ p->fillarea.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if GDISP_NEED_MULTITHREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area using the supplied bitmap.
+ * @details The bitmap is in the pixel format specified by the low level driver
+ * @note If a packed pixel format is used and the width doesn't
+ * match a whole number of bytes, the next line will start on a
+ * non-byte boundary (no end-of-line padding).
+ * @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.
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the filled area
+ * @param[in] srcx,srcy The bitmap position to start the fill form
+ * @param[in] srccx The width of a line in the bitmap
+ * @param[in] buffer The bitmap in the driver's pixel format
+ *
+ * @api
+ */
+ void gdispBlitAreaEx(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) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_blit_area_ex(x, y, cx, cy, srcx, srcy, srccx, buffer);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ASYNC
+ void gdispBlitAreaEx(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) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_BLITAREA);
+ p->blitarea.x = x;
+ p->blitarea.y = y;
+ p->blitarea.cx = cx;
+ p->blitarea.cy = cy;
+ p->blitarea.srcx = srcx;
+ p->blitarea.srcy = srcy;
+ p->blitarea.srccx = srccx;
+ p->blitarea.buffer = buffer;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_CLIP && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Clip all drawing to the defined area.
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the clip area
+ *
+ * @api
+ */
+ void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_set_clip(x, y, cx, cy);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_CLIP && GDISP_NEED_ASYNC
+ void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_SETCLIP);
+ p->setclip.x = x;
+ p->setclip.y = y;
+ p->setclip.cx = cx;
+ p->setclip.cy = cy;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a circle.
+ *
+ * @param[in] x,y The center of the circle
+ * @param[in] radius The radius of the circle
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_circle(x, y, radius, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC
+ void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWCIRCLE);
+ p->drawcircle.x = x;
+ p->drawcircle.y = y;
+ p->drawcircle.radius = radius;
+ p->drawcircle.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a filled circle.
+ *
+ * @param[in] x,y The center of the circle
+ * @param[in] radius The radius of the circle
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_fill_circle(x, y, radius, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC
+ void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLCIRCLE);
+ p->fillcircle.x = x;
+ p->fillcircle.y = y;
+ p->fillcircle.radius = radius;
+ p->fillcircle.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw an ellipse.
+ *
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_ellipse(x, y, a, b, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC
+ void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWELLIPSE);
+ p->drawellipse.x = x;
+ p->drawellipse.y = y;
+ p->drawellipse.a = a;
+ p->drawellipse.b = b;
+ p->drawellipse.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a filled ellipse.
+ *
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_fill_ellipse(x, y, a, b, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC
+ void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLELLIPSE);
+ p->fillellipse.x = x;
+ p->fillellipse.y = y;
+ p->fillellipse.a = a;
+ p->fillellipse.b = b;
+ p->fillellipse.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /*
+ * @brief Draw an arc.
+ *
+ * @param[in] x0,y0 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)
+ * @param[in] color The color of the arc
+ *
+ * @api
+ */
+ void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_arc(x, y, radius, start, end, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC
+ void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC);
+ p->drawarc.x = x;
+ p->drawarc.y = y;
+ p->drawarc.radius = radius;
+ p->drawarc.start = start;
+ p->drawarc.end = end;
+ p->drawarc.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /*
+ * @brief Draw a filled arc.
+ * @note Not very efficient currently - does lots of overdrawing
+ *
+ * @param[in] x0,y0 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)
+ * @param[in] color The color of the arc
+ *
+ * @api
+ */
+ void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_fill_arc(x, y, radius, start, end, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC
+ void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC);
+ p->fillarc.x = x;
+ p->fillarc.y = y;
+ p->fillarc.radius = radius;
+ p->fillarc.start = start;
+ p->fillarc.end = end;
+ p->fillarc.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if GDISP_NEED_ARC || defined(__DOXYGEN__)
+/**
+ * @brief Draw a rectangular box with rounded corners
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ * @param[in] radius The radius of the rounded corners
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
+ if (2*radius > cx || 2*radius > cy) {
+ gdispDrawBox(x, y, cx, cy, color);
+ return;
+ }
+ gdispDrawArc(x+radius, y+radius, radius, 90, 180, color);
+ gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color);
+ gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color);
+ gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color);
+ gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
+ gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color);
+ gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color);
+ gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color);
+}
+#endif
+
+#if GDISP_NEED_ARC || defined(__DOXYGEN__)
+/**
+ * @brief Draw a filled rectangular box with rounded corners
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ * @param[in] radius The radius of the rounded corners
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
+ coord_t radius2;
+
+ radius2 = radius*2;
+ if (radius2 > cx || radius2 > cy) {
+ gdispFillArea(x, y, cx, cy, color);
+ return;
+ }
+ gdispFillArc(x+radius, y+radius, radius, 90, 180, color);
+ gdispFillArea(x+radius+1, y, cx-radius2, radius, color);
+ gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color);
+ gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
+ gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color);
+ gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color);
+ gdispFillArea(x, y+radius, cx, cy-radius2, color);
+}
+#endif
+
+#if (GDISP_NEED_TEXT && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text character.
+ *
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ * @param[in] font The font to use
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawChar(coord_t x, coord_t y, char c, font_t font, color_t color) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_draw_char(x, y, c, font, color);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_TEXT && GDISP_NEED_ASYNC
+ void gdispDrawChar(coord_t x, coord_t y, char c, font_t font, color_t color) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWCHAR);
+ p->drawchar.x = x;
+ p->drawchar.y = y;
+ p->drawchar.c = c;
+ p->drawchar.font = font;
+ p->drawchar.color = color;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_TEXT && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text character with a filled background.
+ *
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ * @param[in] font The font to use
+ * @param[in] color The color to use
+ * @param[in] bgcolor The background color to use
+ *
+ * @api
+ */
+ void gdispFillChar(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_fill_char(x, y, c, font, color, bgcolor);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_TEXT && GDISP_NEED_ASYNC
+ void gdispFillChar(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLCHAR);
+ p->fillchar.x = x;
+ p->fillchar.y = y;
+ p->fillchar.c = c;
+ p->fillchar.font = font;
+ p->fillchar.color = color;
+ p->fillchar.bgcolor = bgcolor;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC)) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a pixel.
+ * @return The color of the pixel.
+ *
+ * @param[in] x,y The position of the pixel
+ *
+ * @api
+ */
+ color_t gdispGetPixelColor(coord_t x, coord_t y) {
+ color_t c;
+
+ /* Always synchronous as it must return a value */
+ chMtxLock(&gdispMutex);
+ c = lld_gdisp_get_pixel_color(x, y);
+ chMtxUnlock();
+
+ return c;
+ }
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @pre GDISP_NEED_SCROLL must be set to TRUE in halconf.h
+ * @note Optional.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @api
+ */
+ void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_vertical_scroll(x, y, cx, cy, lines, bgcolor);
+ chMtxUnlock();
+ }
+#elif GDISP_NEED_SCROLL && GDISP_NEED_ASYNC
+ void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_VERTICALSCROLL);
+ p->verticalscroll.x = x;
+ p->verticalscroll.y = y;
+ p->verticalscroll.cx = cx;
+ p->verticalscroll.cy = cy;
+ p->verticalscroll.lines = lines;
+ p->verticalscroll.bgcolor = bgcolor;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Set the power mode for the display.
+ * @pre The GDISP unit must have been initialised using @p gdispInit().
+ * @note Depending on the hardware implementation this function may not
+ * support some codes. They will be ignored.
+ *
+ * @param[in] what what you want to control
+ * @param[in] value The value to be assigned
+ *
+ * @api
+ */
+ void gdispControl(unsigned what, void *value) {
+ chMtxLock(&gdispMutex);
+ lld_gdisp_control(what, value);
+ chMtxUnlock();
+ chThdSleepMilliseconds(100);
+ }
+#elif GDISP_NEED_CONTROL && GDISP_NEED_ASYNC
+ void gdispControl(unsigned what, void *value) {
+ gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CONTROL);
+ p->control.what = what;
+ p->control.value = value;
+ chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
+ chThdSleepMilliseconds(100);
+ }
+#endif
+
+#if (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC) || defined(__DOXYGEN__)
+ /**
+ * @brief Query a property of the display.
+ * @pre The GDISP unit must have been initialised using @p gdispInit().
+ * @note The result must be typecast to the correct type.
+ * @note An uunsupported query will return (void *)-1.
+ *
+ * @param[in] what What to query
+ *
+ * @api
+ */
+ void *gdispQuery(unsigned what) {
+ void *res;
+
+ chMtxLock(&gdispMutex);
+ res = lld_gdisp_query(what);
+ chMtxUnlock();
+ return res;
+ }
+#endif
+
+/*===========================================================================*/
+/* High Level Driver Routines. */
+/*===========================================================================*/
+
+/**
+ * @brief Draw a rectangular box.
+ *
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ /* No mutex required as we only call high level functions which have their own mutex */
+ coord_t x1, y1;
+
+ x1 = x+cx-1;
+ y1 = y+cy-1;
+
+ if (cx > 2) {
+ if (cy >= 1) {
+ gdispDrawLine(x, y, x1, y, color);
+ if (cy >= 2) {
+ gdispDrawLine(x, y1, x1, y1, color);
+ if (cy > 2) {
+ gdispDrawLine(x, y+1, x, y1-1, color);
+ gdispDrawLine(x1, y+1, x1, y1-1, color);
+ }
+ }
+ }
+ } else if (cx == 2) {
+ gdispDrawLine(x, y, x, y1, color);
+ gdispDrawLine(x1, y, x1, y1, color);
+ } else if (cx == 1) {
+ gdispDrawLine(x, y, x, y1, color);
+ }
+}
+
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text string.
+ *
+ * @param[in] x,y The position for the text
+ * @param[in] font The font to use
+ * @param[in] str The string to draw
+ * @param[in] color The color to use
+ *
+ * @api
+ */
+ void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) {
+ /* No mutex required as we only call high level functions which have their own mutex */
+ coord_t w, p;
+ char c;
+ int first;
+
+ if (!str) return;
+
+ first = 1;
+ p = font->charPadding * font->xscale;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first)
+ x += p;
+ else
+ first = 0;
+ }
+
+ /* Print the character */
+ gdispDrawChar(x, y, c, font, color);
+ x += w;
+ }
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text string.
+ *
+ * @param[in] x,y The position for the text
+ * @param[in] str The string to draw
+ * @param[in] font The font to use
+ * @param[in] color The color to use
+ * @param[in] bgcolor The background color to use
+ *
+ * @api
+ */
+ void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) {
+ /* No mutex required as we only call high level functions which have their own mutex */
+ coord_t w, h, p;
+ char c;
+ int first;
+
+ if (!str) return;
+
+ first = 1;
+ h = font->height * font->yscale;
+ p = font->charPadding * font->xscale;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ gdispFillArea(x, y, p, h, bgcolor);
+ x += p;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ gdispFillChar(x, y, c, font, color, bgcolor);
+ x += w;
+ }
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text string verticly centered within the specified box.
+ *
+ * @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] font The font to use
+ * @param[in] color The color to use
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+ void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) {
+ /* No mutex required as we only call high level functions which have their own mutex */
+ coord_t w, h, p, ypos, xpos;
+ char c;
+ int first;
+ const char *rstr;
+
+ if (!str) str = "";
+
+ h = font->height * font->yscale;
+ p = font->charPadding * font->xscale;
+
+ /* Oops - font too large for the area */
+ if (h > cy) return;
+
+ /* See if we need to fill above the font */
+ ypos = (cy - h + 1)/2;
+ if (ypos > 0) {
+ y += ypos;
+ cy -= ypos;
+ }
+
+ /* See if we need to fill below the font */
+ ypos = cy - h;
+ if (ypos > 0)
+ cy -= ypos;
+
+ /* get the start of the printable string and the xpos */
+ switch(justify) {
+ case justifyCenter:
+ /* Get the length of the entire string */
+ w = gdispGetStringWidth(str, font);
+ if (w <= cx)
+ xpos = x + (cx - w)/2;
+ else {
+ /* Calculate how much of the string we need to get rid of */
+ ypos = (w - cx)/2;
+ xpos = 0;
+ first = 1;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ xpos += p;
+ if (xpos > ypos) break;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ xpos += w;
+ if (xpos > ypos) break;
+ }
+ xpos = ypos - xpos + x;
+ }
+ break;
+ case justifyRight:
+ /* Find the end of the string */
+ for(rstr = str; *str; str++);
+ xpos = x+cx - 2;
+ first = 1;
+ for(str--; str >= rstr; str--) {
+ /* Get the next printable character */
+ c = *str;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ if (xpos - p < x) break;
+ xpos -= p;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ if (xpos - w < x) break;
+ xpos -= w;
+ }
+ str++;
+ break;
+ case justifyLeft:
+ /* Fall through */
+ default:
+ xpos = x+1;
+ break;
+ }
+
+ /* Print characters until we run out of room */
+ first = 1;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ if (xpos + p > x+cx) break;
+ xpos += p;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ if (xpos + w > x+cx) break;
+ gdispDrawChar(xpos, y, c, font, color);
+ xpos += w;
+ }
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text string verticly centered within the specified box. The box background is filled with the specified background color.
+ * @note The entire box is filled
+ *
+ * @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] font The font to use
+ * @param[in] color The color to use
+ * @param[in] bgcolor The background color to use
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+ void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) {
+ /* No mutex required as we only call high level functions which have their own mutex */
+ coord_t w, h, p, ypos, xpos;
+ char c;
+ int first;
+ const char *rstr;
+
+ if (!str) str = "";
+
+ h = font->height * font->yscale;
+ p = font->charPadding * font->xscale;
+
+ /* Oops - font too large for the area */
+ if (h > cy) return;
+
+ /* See if we need to fill above the font */
+ ypos = (cy - h + 1)/2;
+ if (ypos > 0) {
+ gdispFillArea(x, y, cx, ypos, bgcolor);
+ y += ypos;
+ cy -= ypos;
+ }
+
+ /* See if we need to fill below the font */
+ ypos = cy - h;
+ if (ypos > 0) {
+ gdispFillArea(x, y+cy-ypos, cx, ypos, bgcolor);
+ cy -= ypos;
+ }
+
+ /* get the start of the printable string and the xpos */
+ switch(justify) {
+ case justifyCenter:
+ /* Get the length of the entire string */
+ w = gdispGetStringWidth(str, font);
+ if (w <= cx)
+ xpos = x + (cx - w)/2;
+ else {
+ /* Calculate how much of the string we need to get rid of */
+ ypos = (w - cx)/2;
+ xpos = 0;
+ first = 1;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ xpos += p;
+ if (xpos > ypos) break;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ xpos += w;
+ if (xpos > ypos) break;
+ }
+ xpos = ypos - xpos + x;
+ }
+ break;
+ case justifyRight:
+ /* Find the end of the string */
+ for(rstr = str; *str; str++);
+ xpos = x+cx - 2;
+ first = 1;
+ for(str--; str >= rstr; str--) {
+ /* Get the next printable character */
+ c = *str;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ if (xpos - p < x) break;
+ xpos -= p;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ if (xpos - w < x) break;
+ xpos -= w;
+ }
+ str++;
+ break;
+ case justifyLeft:
+ /* Fall through */
+ default:
+ xpos = x+1;
+ break;
+ }
+
+ /* Fill any space to the left */
+ if (x < xpos)
+ gdispFillArea(x, y, xpos-x, cy, bgcolor);
+
+ /* Print characters until we run out of room */
+ first = 1;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first) {
+ if (xpos + p > x+cx) break;
+ gdispFillArea(xpos, y, p, cy, bgcolor);
+ xpos += p;
+ } else
+ first = 0;
+ }
+
+ /* Print the character */
+ if (xpos + w > x+cx) break;
+ gdispFillChar(xpos, y, c, font, color, bgcolor);
+ xpos += w;
+ }
+
+ /* Fill any space to the right */
+ if (xpos < x+cx)
+ gdispFillArea(xpos, y, x+cx-xpos, cy, bgcolor);
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Get a metric of a font.
+ * @return The metric requested in pixels.
+ *
+ * @param[in] font The font to test
+ * @param[in] metric The metric to measure
+ *
+ * @api
+ */
+ coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) {
+ /* No mutex required as we only read static data */
+ switch(metric) {
+ case fontHeight: return font->height * font->yscale;
+ case fontDescendersHeight: return font->descenderHeight * font->yscale;
+ case fontLineSpacing: return font->lineSpacing * font->yscale;
+ case fontCharPadding: return font->charPadding * font->xscale;
+ case fontMinWidth: return font->minWidth * font->xscale;
+ case fontMaxWidth: return font->maxWidth * font->xscale;
+ }
+ return 0;
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Get the pixel width of a character.
+ * @return The width of the character in pixels. Does not include any between character padding.
+ *
+ * @param[in] c The character to draw
+ * @param[in] font The font to use
+ *
+ * @api
+ */
+ coord_t gdispGetCharWidth(char c, font_t font) {
+ /* No mutex required as we only read static data */
+ return _getCharWidth(font, c) * font->xscale;
+ }
+#endif
+
+#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Get the pixel width of a string.
+ * @return The width of the string in pixels.
+ *
+ * @param[in] str The string to measure
+ * @param[in] font The font to use
+ *
+ * @api
+ */
+ coord_t gdispGetStringWidth(const char* str, font_t font) {
+ /* No mutex required as we only read static data */
+ coord_t w, p, x;
+ char c;
+ int first;
+
+ first = 1;
+ x = 0;
+ p = font->charPadding * font->xscale;
+ while(*str) {
+ /* Get the next printable character */
+ c = *str++;
+ w = _getCharWidth(font, c) * font->xscale;
+ if (!w) continue;
+
+ /* Handle inter-character padding */
+ if (p) {
+ if (!first)
+ x += p;
+ else
+ first = 0;
+ }
+
+ /* Add the character width */
+ x += w;
+ }
+ return x;
+ }
+#endif
+
+#if (!defined(gdispPackPixels) && !defined(GDISP_PIXELFORMAT_CUSTOM)) || defined(__DOXYGEN__)
+ /**
+ * @brief Pack a pixel into a pixel buffer.
+ * @note This function performs no buffer boundary checking
+ * regardless of whether GDISP_NEED_CLIP has been specified.
+ *
+ * @param[in] buf The buffer to put the pixel in
+ * @param[in] cx The width of a pixel line
+ * @param[in] x, y The location of the pixel to place
+ * @param[in] color The color to put into the buffer
+ *
+ * @api
+ */
+ void gdispPackPixels(pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color) {
+ /* No mutex required as we only read static data */
+ #if defined(GDISP_PIXELFORMAT_RGB888)
+ #error "GDISP: Packed pixels not supported yet"
+ #elif defined(GDISP_PIXELFORMAT_RGB444)
+ #error "GDISP: Packed pixels not supported yet"
+ #elif defined(GDISP_PIXELFORMAT_RGB666)
+ #error "GDISP: Packed pixels not supported yet"
+ #elif
+ #error "GDISP: Unsupported packed pixel format"
+ #endif
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/src/gdisp/gdisp.mk b/src/gdisp/gdisp.mk
new file mode 100644
index 00000000..426e9e2c
--- /dev/null
+++ b/src/gdisp/gdisp.mk
@@ -0,0 +1,2 @@
+GFXSRC += $(GFXLIB)/src/gdisp/gdisp.c \
+ $(GFXLIB)/src/gdisp/fonts.c
diff --git a/src/gevent/gevent.c b/src/gevent/gevent.c
new file mode 100644
index 00000000..f3d909f0
--- /dev/null
+++ b/src/gevent/gevent.c
@@ -0,0 +1,197 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @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 */
+/** @} */
diff --git a/src/gevent/gevent.mk b/src/gevent/gevent.mk
new file mode 100644
index 00000000..59226318
--- /dev/null
+++ b/src/gevent/gevent.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gevent/gevent.c
diff --git a/src/ginput/dial.c b/src/ginput/dial.c
new file mode 100644
index 00000000..a447d8bc
--- /dev/null
+++ b/src/ginput/dial.c
@@ -0,0 +1,36 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/ginput/dial.c
+ * @brief GINPUT dial code.
+ *
+ * @defgroup Dial Dial
+ * @ingroup GINPUT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_DIAL) || defined(__DOXYGEN__)
+ #error "GINPUT: GINPUT_NEED_DIAL - Not Implemented Yet"
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_DIAL */
+/** @} */
diff --git a/src/ginput/ginput.mk b/src/ginput/ginput.mk
new file mode 100644
index 00000000..06bcfc07
--- /dev/null
+++ b/src/ginput/ginput.mk
@@ -0,0 +1,4 @@
+GFXSRC += $(GFXLIB)/src/ginput/mouse.c \
+ $(GFXLIB)/src/ginput/keyboard.c \
+ $(GFXLIB)/src/ginput/toggle.c \
+ $(GFXLIB)/src/ginput/dial.c
diff --git a/src/ginput/keyboard.c b/src/ginput/keyboard.c
new file mode 100644
index 00000000..56ff5e8a
--- /dev/null
+++ b/src/ginput/keyboard.c
@@ -0,0 +1,38 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/ginput/keyboard.c
+ * @brief GINPUT keyboard code.
+ *
+ * @defgroup Keyboard Keyboard
+ * @ingroup GINPUT
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || defined(__DOXYGEN__)
+ #error "GINPUT: GINPUT_NEED_KEYBOARD - Not Implemented Yet"
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD */
+/** @} */
diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c
new file mode 100644
index 00000000..94734888
--- /dev/null
+++ b/src/ginput/mouse.c
@@ -0,0 +1,589 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/ginput/mouse.c
+ * @brief GINPUT mouse/touch code.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
+
+#include "ginput/lld/mouse.h"
+
+#if GINPUT_MOUSE_NEED_CALIBRATION
+ #if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
+ #error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
+ #endif
+
+ #define GINPUT_MOUSE_CALIBRATION_FONT "* Double"
+ #define GINPUT_MOUSE_CALIBRATION_FONT2 "* Narrow"
+ #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration"
+ #define GINPUT_MOUSE_CALIBRATION_ERROR_TEXT "Failed - Please try again!"
+ #define GINPUT_MOUSE_CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!"
+
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR < 0
+ #define GINPUT_MOUSE_CALIBRATION_POINTS 3
+ #else
+ #define GINPUT_MOUSE_CALIBRATION_POINTS 4
+ #endif
+
+ typedef struct Calibration_t {
+ float ax;
+ float bx;
+ float cx;
+ float ay;
+ float by;
+ float cy;
+ } Calibration;
+#endif
+
+typedef struct MousePoint_t {
+ coord_t x, y;
+ } MousePoint;
+
+static GTIMER_DECL(MouseTimer);
+
+static struct MouseConfig_t {
+ MouseReading t;
+ MousePoint movepos;
+ MousePoint clickpos;
+ systime_t clicktime;
+ uint16_t last_buttons;
+ uint16_t flags;
+ #define FLG_INIT_DONE 0x8000
+ #define FLG_CLICK_TIMER 0x0001
+ #define FLG_IN_CAL 0x0010
+ #define FLG_CAL_OK 0x0020
+ #define FLG_CAL_SAVED 0x0040
+ #define FLG_CAL_FREE 0x0080
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ GMouseCalibrationSaveRoutine fnsavecal;
+ GMouseCalibrationLoadRoutine fnloadcal;
+ Calibration caldata;
+ #endif
+ } MouseConfig;
+
+#if GINPUT_MOUSE_NEED_CALIBRATION
+ static __inline void _tsDrawCross(const MousePoint *pp) {
+ gdispDrawLine(pp->x-15, pp->y, pp->x-2, pp->y, White);
+ gdispDrawLine(pp->x+2, pp->y, pp->x+15, pp->y, White);
+ gdispDrawLine(pp->x, pp->y-15, pp->x, pp->y-2, White);
+ gdispDrawLine(pp->x, pp->y+2, pp->x, pp->y+15, White);
+
+ gdispDrawLine(pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131));
+ }
+
+ static __inline void _tsClearCross(const MousePoint *pp) {
+ gdispFillArea(pp->x - 15, pp->y - 15, 42, 42, Blue);
+ }
+
+ static __inline void _tsTransform(MouseReading *pt, const Calibration *c) {
+ pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx);
+ pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy);
+ }
+
+ static __inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, Calibration *c) {
+ float dx, dx0, dx1, dx2, dy0, dy1, dy2;
+
+ /* Compute all the required determinants */
+ dx = ((float)(points[0].x - points[2].x)) * ((float)(points[1].y - points[2].y))
+ - ((float)(points[1].x - points[2].x)) * ((float)(points[0].y - points[2].y));
+
+ dx0 = ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].y - points[2].y))
+ - ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].y - points[2].y));
+
+ dx1 = ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].x - points[2].x))
+ - ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].x - points[2].x));
+
+ dx2 = cross[0].x * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
+ cross[1].x * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
+ cross[2].x * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
+
+ dy0 = ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].y - points[2].y))
+ - ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].y - points[2].y));
+
+ dy1 = ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].x - points[2].x))
+ - ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].x - points[2].x));
+
+ dy2 = cross[0].y * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
+ cross[1].y * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
+ cross[2].y * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
+
+ /* Now, calculate all the required coefficients */
+ c->ax = dx0 / dx;
+ c->bx = dx1 / dx;
+ c->cx = dx2 / dx;
+
+ c->ay = dy0 / dx;
+ c->by = dy1 / dx;
+ c->cy = dy2 / dx;
+ }
+#endif
+
+#if GINPUT_MOUSE_READ_CYCLES > 1
+ static void get_raw_reading(MouseReading *pt) {
+ int32_t x, y, z;
+ unsigned i;
+
+ x = y = z = 0;
+ for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
+ ginput_lld_mouse_get_reading(pt);
+ x += pt->x;
+ y += pt->y;
+ z += pt->z;
+ }
+
+ /* Take the average of the readings */
+ pt->x = x / GINPUT_MOUSE_READ_CYCLES;
+ pt->y = y / GINPUT_MOUSE_READ_CYCLES;
+ pt->z = z / GINPUT_MOUSE_READ_CYCLES;
+ }
+#else
+ #define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
+#endif
+
+static void get_calibrated_reading(MouseReading *pt) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
+ coord_t w, h;
+ #endif
+
+ get_raw_reading(pt);
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
+ w = gdispGetWidth();
+ h = gdispGetHeight();
+ #endif
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ _tsTransform(pt, &MouseConfig.caldata);
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(gdispGetOrientation()) {
+ case GDISP_ROTATE_0:
+ break;
+ case GDISP_ROTATE_90:
+ {
+ coord_t t = pt->y;
+ pt->y = h - 1 - pt->x;
+ pt->x = t;
+ }
+ break;
+ case GDISP_ROTATE_180:
+ pt->x = w - 1 - pt->x;
+ pt->y = h - 1 - pt->y;
+ break;
+ case GDISP_ROTATE_270:
+ {
+ coord_t t = pt->x;
+ pt->x = w - 1 - pt->y;
+ pt->y = t;
+ }
+ break;
+ }
+ #endif
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ if (pt->x < 0) pt->x = 0;
+ else if (pt->x >= w) pt->x = w-1;
+ if (pt->y < 0) pt->y = 0;
+ else if (pt->y >= h) pt->y = h-1;
+ #endif
+}
+
+static void MousePoll(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventMouse *pe;
+ unsigned meta;
+ uint16_t tbtns;
+ uint32_t cdiff;
+ uint32_t mdiff;
+
+ // Save the last mouse state
+ MouseConfig.last_buttons = MouseConfig.t.buttons;
+
+ // Get the new mouse reading
+ get_calibrated_reading(&MouseConfig.t);
+
+ // Calculate out new event meta value and handle CLICK and CXTCLICK
+ meta = GMETA_NONE;
+
+ // Calculate the position difference from our movement reference (update the reference if out of range)
+ mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
+ (MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
+ if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
+ MouseConfig.movepos.x = MouseConfig.t.x;
+ MouseConfig.movepos.y = MouseConfig.t.y;
+ }
+
+ // Check if the click has moved outside the click area and if so cancel the click
+ if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
+ cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
+ (MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
+ if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
+ MouseConfig.flags &= ~FLG_CLICK_TIMER;
+ }
+
+ // Mouse down
+ tbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
+ meta |= GMETA_MOUSE_DOWN;
+ if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
+ MouseConfig.clickpos.x = MouseConfig.t.x;
+ MouseConfig.clickpos.y = MouseConfig.t.y;
+ MouseConfig.clicktime = chTimeNow();
+ MouseConfig.flags |= FLG_CLICK_TIMER;
+ }
+
+ // Mouse up
+ tbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
+ meta |= GMETA_MOUSE_UP;
+ if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
+ if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT)
+ #if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
+ && chTimeNow() - MouseConfig.clicktime < MS2ST(GINPUT_MOUSE_CLICK_TIME)
+ #endif
+ )
+ meta |= GMETA_MOUSE_CLICK;
+ else
+ meta |= GMETA_MOUSE_CXTCLICK;
+ MouseConfig.flags &= ~FLG_CLICK_TIMER;
+ }
+ }
+
+ // Send the event to the listeners that are interested.
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
+ if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save the meta events that have happened
+ psl->srcflags |= meta;
+ continue;
+ }
+
+ // If we haven't really moved (and there are no meta events) don't bother sending the event
+ if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags && !meta && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
+ continue;
+
+ // Send the event if we are listening for it
+ if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
+ || (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
+ || (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
+ pe->type = GINPUT_MOUSE_EVENT_TYPE;
+ pe->instance = 0;
+ pe->x = MouseConfig.t.x;
+ pe->y = MouseConfig.t.y;
+ pe->z = MouseConfig.t.z;
+ pe->current_buttons = MouseConfig.t.buttons;
+ pe->last_buttons = MouseConfig.last_buttons;
+ pe->meta = meta;
+ if (psl->srcflags) {
+ pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
+ pe->meta |= psl->srcflags;
+ psl->srcflags = 0;
+ }
+ geventSendEvent(psl);
+ }
+ }
+}
+
+GSourceHandle ginputGetMouse(uint16_t instance) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ Calibration *pc;
+ #endif
+
+ // We only support a single mouse instance currently
+ // Instance 9999 is the same as instance 0 except that it installs
+ // a special "raw" calibration if there isn't one we can load.
+ if (instance && instance != 9999)
+ return 0;
+
+ // Do we need to initialise the mouse subsystem?
+ if (!(MouseConfig.flags & FLG_INIT_DONE)) {
+ ginput_lld_mouse_init();
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ if (!MouseConfig.fnloadcal) {
+ MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ }
+ if (!MouseConfig.fnsavecal)
+ MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
+ #endif
+ if (MouseConfig.fnloadcal && (pc = (Calibration *)MouseConfig.fnloadcal(instance))) {
+ MouseConfig.caldata = pc[0];
+ MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
+ if ((MouseConfig.flags & FLG_CAL_FREE))
+ chHeapFree((void *)pc);
+ } else if (instance == 9999) {
+ MouseConfig.caldata.ax = 1;
+ MouseConfig.caldata.bx = 0;
+ MouseConfig.caldata.cx = 0;
+ MouseConfig.caldata.ay = 0;
+ MouseConfig.caldata.by = 1;
+ MouseConfig.caldata.cy = 0;
+ MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
+ } else
+ ginputCalibrateMouse(instance);
+ #endif
+
+ // Get the first reading
+ MouseConfig.last_buttons = 0;
+ get_calibrated_reading(&MouseConfig.t);
+
+ // Mark init as done and start the Poll timer
+ MouseConfig.flags |= FLG_INIT_DONE;
+ gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+ }
+
+ // Return our structure as the handle
+ return (GSourceHandle)&MouseConfig;
+}
+
+bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
+ // Win32 threads don't seem to recognise priority and/or pre-emption
+ // so we add a sleep here to prevent 100% polled applications from locking up.
+ chThdSleepMilliseconds(1);
+
+ if (instance || (MouseConfig.flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE)
+ return FALSE;
+
+ pe->type = GINPUT_MOUSE_EVENT_TYPE;
+ pe->instance = instance;
+ pe->x = MouseConfig.t.x;
+ pe->y = MouseConfig.t.y;
+ pe->z = MouseConfig.t.z;
+ pe->current_buttons = MouseConfig.t.buttons;
+ pe->last_buttons = MouseConfig.last_buttons;
+ if (pe->current_buttons & ~pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
+ pe->meta = GMETA_MOUSE_DOWN;
+ else if (~pe->current_buttons & pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
+ pe->meta = GMETA_MOUSE_UP;
+ else
+ pe->meta = GMETA_NONE;
+ return TRUE;
+}
+
+bool_t ginputCalibrateMouse(uint16_t instance) {
+ #if !GINPUT_MOUSE_NEED_CALIBRATION
+ (void) instance;
+
+ return FALSE;
+ #else
+
+ const coord_t height = gdispGetHeight();
+ const coord_t width = gdispGetWidth();
+ const MousePoint cross[] = {{(width / 4), (height / 4)},
+ {(width - (width / 4)) , (height / 4)},
+ {(width - (width / 4)) , (height - (height / 4))},
+ {(width / 2), (height / 2)}}; /* Check point */
+ MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS];
+ const MousePoint *pc;
+ MousePoint *pt;
+ int32_t px, py;
+ unsigned i, j;
+ font_t font1, font2;
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ unsigned err;
+ #endif
+
+ if (instance || (MouseConfig.flags & FLG_IN_CAL))
+ return FALSE;
+
+ font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT);
+ font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2);
+
+ MouseConfig.flags |= FLG_IN_CAL;
+ gtimerStop(&MouseTimer);
+ MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED);
+
+ #if GDISP_NEED_CONTROL
+ gdispSetOrientation(GDISP_ROTATE_0);
+ #endif
+
+ #if GDISP_NEED_CLIP
+ gdispSetClip(0, 0, width, height);
+ #endif
+
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ while(1) {
+ #endif
+ gdispClear(Blue);
+
+ gdispFillStringBox(0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1, White, Blue, justifyCenter);
+
+ for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {
+ _tsDrawCross(pc);
+
+ do {
+
+ /* Wait for the mouse to be pressed */
+ while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT))
+ chThdSleepMilliseconds(20);
+
+ /* Average all the samples while the mouse is down */
+ for(px = py = 0, j = 0;
+ chThdSleepMilliseconds(20), /* Settling time between readings */
+ get_raw_reading(&MouseConfig.t),
+ (MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT);
+ j++) {
+ px += MouseConfig.t.x;
+ py += MouseConfig.t.y;
+ }
+
+ } while(!j);
+
+ pt->x = px / j;
+ pt->y = py / j;
+
+ _tsClearCross(pc);
+
+ if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) {
+ gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2, Red, Yellow, justifyCenter);
+ chThdSleepMilliseconds(5000);
+ gdispFillArea(0, 35, width, 40, Blue);
+ }
+
+ }
+
+ /* Apply 3 point calibration algorithm */
+ _tsDo3PointCalibration(cross, points, &MouseConfig.caldata);
+
+ /* Verification of correctness of calibration (optional) :
+ * See if the 4th point (Middle of the screen) coincides with the calibrated
+ * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
+ * Else, start from the beginning.
+ */
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ /* Transform the co-ordinates */
+ MouseConfig.t.x = points[3].x;
+ MouseConfig.t.y = points[3].y;
+ _tsTransform(&MouseConfig.t, &MouseConfig.caldata);
+
+ /* Calculate the delta */
+ err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) +
+ (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y);
+
+ if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)
+ break;
+
+ gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2, Red, Yellow, justifyCenter);
+ chThdSleepMilliseconds(5000);
+ }
+ #endif
+
+ // Restart everything
+ gdispCloseFont(font1);
+ gdispCloseFont(font2);
+ MouseConfig.flags |= FLG_CAL_OK;
+ MouseConfig.last_buttons = 0;
+ get_calibrated_reading(&MouseConfig.t);
+ MouseConfig.flags &= ~FLG_IN_CAL;
+ if ((MouseConfig.flags & FLG_INIT_DONE))
+ gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+
+ // Save the calibration data (if possible)
+ if (MouseConfig.fnsavecal) {
+ MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
+ MouseConfig.flags |= FLG_CAL_SAVED;
+ }
+
+ return TRUE;
+ #endif
+}
+
+/* Set the routines to save and fetch calibration data.
+ * This function should be called before first calling ginputGetMouse() for a particular instance
+ * as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it.
+ * If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.
+ * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
+ */
+void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ if (instance)
+ return;
+
+ MouseConfig.fnloadcal = fnload;
+ MouseConfig.fnsavecal = fnsave;
+ if (requireFree)
+ MouseConfig.flags |= FLG_CAL_FREE;
+ else
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ if (!MouseConfig.fnloadcal) {
+ MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ }
+ if (!MouseConfig.fnsavecal)
+ MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
+ #endif
+ if (MouseConfig.fnsavecal && (MouseConfig.flags & (FLG_CAL_OK|FLG_CAL_SAVED)) == FLG_CAL_OK) {
+ MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
+ MouseConfig.flags |= FLG_CAL_SAVED;
+ }
+ #else
+ (void)instance, (void)fnsave, (void)fnload, (void)requireFree;
+ #endif
+}
+
+/* Test if a particular mouse instance requires routines to save its calibration data. */
+bool_t ginputRequireMouseCalibrationStorage(uint16_t instance) {
+ if (instance)
+ return FALSE;
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION && !GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ return TRUE;
+ #else
+ return FALSE;
+ #endif
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputMouseWakeup(void) {
+ gtimerJab(&MouseTimer);
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputMouseWakeupI(void) {
+ gtimerJabI(&MouseTimer);
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
+/** @} */
diff --git a/src/ginput/toggle.c b/src/ginput/toggle.c
new file mode 100644
index 00000000..4401e295
--- /dev/null
+++ b/src/ginput/toggle.c
@@ -0,0 +1,171 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/ginput/toggle.c
+ * @brief GINPUT toggle code.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__)
+
+#include "ginput/lld/toggle.h"
+
+#define GINPUT_TOGGLE_ISON 0x01
+#define GINPUT_TOGGLE_INVERT 0x02
+
+static GTIMER_DECL(ToggleTimer);
+static struct GEventToggleStatus_t {
+ uint8_t status;
+} ToggleStatus[GINPUT_TOGGLE_NUM_PORTS];
+
+// Our polling function
+static void TogglePoll(void *param) {
+ (void) param;
+
+ const GToggleConfig *ptc;
+ GSourceListener *psl;
+ GEventToggle *pe;
+ unsigned i, bits, mask;
+ uint8_t state;
+
+ // Loop while there are bits to get
+ for(ptc = GInputToggleConfigTable, i=0; i < GINPUT_TOGGLE_NUM_PORTS; ptc++) {
+
+ // Get the next block of bits
+ bits = ginput_lld_toggle_getbits(ptc) ^ ptc->invert;
+
+ // Extract the bits of use
+ for(mask = ptc->mask; i < GINPUT_TOGGLE_NUM_PORTS && mask; mask >>= 1, bits >>= 1) {
+ // Ignore bits not in our mask
+ if (!(mask & 1))
+ continue;
+
+ // Calculate our new state
+ state = ToggleStatus[i].status & ~GINPUT_TOGGLE_ISON;
+ if (state & GINPUT_TOGGLE_INVERT)
+ bits ^= 1;
+ if (bits & 1)
+ state |= GINPUT_TOGGLE_ISON;
+
+ // Has it changed?
+ if ((state ^ ToggleStatus[i].status) & GINPUT_TOGGLE_ISON) {
+
+ // Save the new state
+ ToggleStatus[i].status = state;
+
+ // Send the event to the listeners that are interested.
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)(ToggleStatus+i), psl))) {
+ if (!(pe = (GEventToggle *)geventGetEventBuffer(psl)))
+ continue;
+ if ((state & GINPUT_TOGGLE_ISON)) {
+ if ((psl->listenflags & GLISTEN_TOGGLE_ON)) {
+ pe->type = GEVENT_TOGGLE;
+ pe->instance = i;
+ pe->on = TRUE;
+ geventSendEvent(psl);
+ }
+ } else {
+ if ((psl->listenflags & GLISTEN_TOGGLE_OFF)) {
+ pe->type = GEVENT_TOGGLE;
+ pe->instance = i;
+ pe->on = FALSE;
+ geventSendEvent(psl);
+ }
+ }
+ }
+ }
+
+ // Next toggle switch
+ i++;
+ }
+ }
+}
+
+/* Hardware Toggle/Switch/Button Functions */
+GSourceHandle ginputGetToggle(uint16_t instance) {
+ const GToggleConfig *ptc;
+
+ if (instance >= GINPUT_TOGGLE_NUM_PORTS)
+ return 0;
+
+ // Do we need to initialise the toggle subsystem?
+ if (!gtimerIsActive(&ToggleTimer)) {
+ for(ptc = GInputToggleConfigTable; ptc < GInputToggleConfigTable+sizeof(GInputToggleConfigTable)/sizeof(GInputToggleConfigTable[0]); ptc++)
+ ginput_lld_toggle_init(ptc);
+ gtimerStart(&ToggleTimer, TogglePoll, 0, TRUE, GINPUT_TOGGLE_POLL_PERIOD);
+ }
+
+ // OK - return this input
+ return (GSourceHandle)(ToggleStatus+instance);
+}
+
+// If invert is true, invert the on/off sense for the toggle
+void ginputInvertToggle(uint16_t instance, bool_t invert) {
+ if (instance >= GINPUT_TOGGLE_NUM_PORTS)
+ return;
+ if (invert) {
+ if (!(ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) {
+ ToggleStatus[instance].status |= GINPUT_TOGGLE_INVERT;
+ ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON;
+ }
+ } else {
+ if ((ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) {
+ ToggleStatus[instance].status &= ~GINPUT_TOGGLE_INVERT;
+ ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON;
+ }
+ }
+}
+
+/* Get the current toggle status.
+ * Returns FALSE on error (eg invalid instance)
+ */
+bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle) {
+ // Win32 threads don't seem to recognise priority and/or pre-emption
+ // so we add a sleep here to prevent 100% polled applications from locking up.
+ chThdSleepMilliseconds(1);
+
+ if (instance >= GINPUT_TOGGLE_NUM_PORTS)
+ return FALSE;
+ ptoggle->type = GEVENT_TOGGLE;
+ ptoggle->instance = instance;
+ ptoggle->on = (ToggleStatus[instance].status & GINPUT_TOGGLE_ISON) ? TRUE : FALSE;
+ return TRUE;
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputToggleWakeup(void) {
+ gtimerJab(&ToggleTimer);
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputToggleWakeupI(void) {
+ gtimerJabI(&ToggleTimer);
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */
+/** @} */
diff --git a/src/gmisc/arrayops.c b/src/gmisc/arrayops.c
new file mode 100644
index 00000000..6eeb0e75
--- /dev/null
+++ b/src/gmisc/arrayops.c
@@ -0,0 +1,241 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gmisc/arrayops.c
+ * @brief GMISC Array Operations code.
+ *
+ * @addtogroup GMISC
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GMISC && GMISC_NEED_ARRAYOPS) || defined(__DOXYGEN__)
+
+void gmiscArrayConvert(ArrayDataFormat srcfmt, void *src, ArrayDataFormat dstfmt, void *dst, size_t cnt) {
+ uint8_t *src8, *dst8;
+ uint16_t *src16, *dst16;
+
+ dst8 = dst;
+ dst16 = dst;
+ src8 = src;
+ src16 = src;
+
+ /* We do this as a big switch in order to optimise efficiency for each transfer type */
+ switch(dstfmt) {
+ case ARRAY_DATA_4BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: if (dst != src) while(cnt--) { *dst8++ = *src8++; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 8); } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst8++ = *src8++ >> 4; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 128) >> 4; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 6; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 512) >> 6; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 8; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 2048) >> 8; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 10; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 8192) >> 10; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 12; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 32768) >> 12; } break;
+ }
+ break;
+ case ARRAY_DATA_4BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 8); } break;
+ case ARRAY_DATA_4BITSIGNED: if (dst != src) while(cnt--) { *dst8++ = *src8++; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 128) >> 4; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst8++ = *src8++ >> 4; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 512) >> 6; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 6; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 2048) >> 8; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 8; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 8192) >> 10; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 10; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 32768) >> 12; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 12; } break;
+ }
+ break;
+ case ARRAY_DATA_8BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst8++ = *src8++ << 4; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 8) << 4; } break;
+ case ARRAY_DATA_8BITUNSIGNED: if (dst != src) while(cnt--) { *dst8++ = *src8++; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 128); } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 512) >> 2; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 4; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 2048) >> 4; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 6; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 8192) >> 6; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst8++ = *src16++ >> 8; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 32768) >> 8; } break;
+ }
+ break;
+ case ARRAY_DATA_8BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 8) << 4; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst8++ = *src8++ << 4; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst8++ = (*src8++ ^ 128); } break;
+ case ARRAY_DATA_8BITSIGNED: if (dst != src) while(cnt--) { *dst8++ = *src8++; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 512) >> 2; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 2048) >> 4; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 4; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 8192) >> 6; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 6; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst8++ = (*src16++ ^ 32768) >> 8; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst8++ = *src16++ >> 8; } break;
+ }
+ break;
+ case ARRAY_DATA_10BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 6; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 6; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 2; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 2; } break;
+ case ARRAY_DATA_10BITUNSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512); } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) >> 2; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 4; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) >> 4; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 6; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 6; } break;
+ }
+ break;
+ case ARRAY_DATA_10BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 6; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 6; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 2; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 2; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512); } break;
+ case ARRAY_DATA_10BITSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) >> 2; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) >> 4; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 4; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 6; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 6; } break;
+ }
+ break;
+ case ARRAY_DATA_12BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 8; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 8; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 4; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 4; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ << 2; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 2; } break;
+ case ARRAY_DATA_12BITUNSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048); } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) >> 2; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 4; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 4; } break;
+ }
+ break;
+ case ARRAY_DATA_12BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 8; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 8; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 4; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 4; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 2; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = *src16++ << 2; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048); } break;
+ case ARRAY_DATA_12BITSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) >> 2; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 4; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 4; } break;
+ }
+ break;
+ case ARRAY_DATA_14BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 10; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 10; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 6; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 6; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ << 4; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 4; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ << 2; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) >> 2; } break;
+ case ARRAY_DATA_14BITUNSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192); } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 2; } break;
+ }
+ break;
+ case ARRAY_DATA_14BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 10; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 10; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 6; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 6; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 4; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = *src16++ << 4; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) << 2; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = *src16++ << 2; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192); } break;
+ case ARRAY_DATA_14BITSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768) >> 2; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ }
+ break;
+ case ARRAY_DATA_16BITUNSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 12; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 12; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = *src8++ << 8; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 8; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ << 6; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 6; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ << 4; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) >> 4; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) >> 2; } break;
+ case ARRAY_DATA_16BITUNSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ case ARRAY_DATA_16BITSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768); } break;
+ }
+ break;
+ case ARRAY_DATA_16BITSIGNED:
+ switch(srcfmt) {
+ case ARRAY_DATA_4BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 8) << 12; } break;
+ case ARRAY_DATA_4BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 12; } break;
+ case ARRAY_DATA_8BITUNSIGNED: while(cnt--) { *dst16++ = (*src8++ ^ 128) << 8; } break;
+ case ARRAY_DATA_8BITSIGNED: while(cnt--) { *dst16++ = *src8++ << 8; } break;
+ case ARRAY_DATA_10BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 512) << 6; } break;
+ case ARRAY_DATA_10BITSIGNED: while(cnt--) { *dst16++ = *src16++ << 6; } break;
+ case ARRAY_DATA_12BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 2048) << 4; } break;
+ case ARRAY_DATA_12BITSIGNED: while(cnt--) { *dst16++ = *src16++ << 4; } break;
+ case ARRAY_DATA_14BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 8192) << 2; } break;
+ case ARRAY_DATA_14BITSIGNED: while(cnt--) { *dst16++ = *src16++ >> 2; } break;
+ case ARRAY_DATA_16BITUNSIGNED: while(cnt--) { *dst16++ = (*src16++ ^ 32768); } break;
+ case ARRAY_DATA_16BITSIGNED: if (dst != src) while(cnt--) { *dst16++ = *src16++; } break;
+ }
+ break;
+ }
+}
+
+#endif /* GFX_USE_GMISC && GMISC_NEED_ARRAYOPS */
+/** @} */
diff --git a/src/gmisc/gmisc.mk b/src/gmisc/gmisc.mk
new file mode 100644
index 00000000..7e4caea8
--- /dev/null
+++ b/src/gmisc/gmisc.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gmisc/arrayops.c
diff --git a/src/gtimer/gtimer.c b/src/gtimer/gtimer.c
new file mode 100644
index 00000000..76dd57e2
--- /dev/null
+++ b/src/gtimer/gtimer.c
@@ -0,0 +1,240 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/gtimer/gtimer.c
+ * @brief GTIMER sub-system code.
+ *
+ * @addtogroup GTIMER
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GTIMER || defined(__DOXYGEN__)
+
+#if !CH_USE_MUTEXES || !CH_USE_SEMAPHORES
+ #error "GTIMER: CH_USE_MUTEXES and CH_USE_SEMAPHORES must be defined in chconf.h"
+#endif
+
+#define GTIMER_FLG_PERIODIC 0x0001
+#define GTIMER_FLG_INFINITE 0x0002
+#define GTIMER_FLG_JABBED 0x0004
+#define GTIMER_FLG_SCHEDULED 0x0008
+
+/* Don't rework this macro to use a ternary operator - the gcc compiler stuffs it up */
+#define TimeIsWithin(x, start, end) ((end >= start && x >= start && x <= end) || (end < start && (x >= start || x <= end)))
+
+/* This mutex protects access to our tables */
+static MUTEX_DECL(mutex);
+static Thread *pThread = 0;
+static GTimer *pTimerHead = 0;
+static BSEMAPHORE_DECL(waitsem, TRUE);
+static WORKING_AREA(waTimerThread, GTIMER_THREAD_WORKAREA_SIZE);
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static msg_t GTimerThreadHandler(void *arg) {
+ (void)arg;
+ GTimer *pt;
+ systime_t tm;
+ systime_t nxtTimeout;
+ systime_t lastTime;
+ GTimerFunction fn;
+ void *param;
+
+ #if CH_USE_REGISTRY
+ chRegSetThreadName("GTimer");
+ #endif
+
+ nxtTimeout = TIME_INFINITE;
+ lastTime = 0;
+ while(1) {
+ /* Wait for work to do. */
+ chThdYield(); // Give someone else a go no matter how busy we are
+ chBSemWaitTimeout(&waitsem, nxtTimeout);
+
+ restartTimerChecks:
+
+ // Our reference time
+ tm = chTimeNow();
+ nxtTimeout = TIME_INFINITE;
+
+ /* We need to obtain the mutex */
+ chMtxLock(&mutex);
+
+ if (pTimerHead) {
+ pt = pTimerHead;
+ do {
+ // Do we have something to do for this timer?
+ if ((pt->flags & GTIMER_FLG_JABBED) || (!(pt->flags & GTIMER_FLG_INFINITE) && TimeIsWithin(pt->when, lastTime, tm))) {
+
+ // Is this timer periodic?
+ if ((pt->flags & GTIMER_FLG_PERIODIC) && pt->period != TIME_IMMEDIATE) {
+ // Yes - Update ready for the next period
+ if (!(pt->flags & GTIMER_FLG_INFINITE)) {
+ // We may have skipped a period.
+ // We use this complicated formulae rather than a loop
+ // because the gcc compiler stuffs up the loop so that it
+ // either loops forever or doesn't get executed at all.
+ pt->when += ((tm + pt->period - pt->when) / pt->period) * pt->period;
+ }
+
+ // We are definitely no longer jabbed
+ pt->flags &= ~GTIMER_FLG_JABBED;
+
+ } else {
+ // No - get us off the timers list
+ if (pt->next == pt->prev)
+ pTimerHead = 0;
+ else {
+ pt->next->prev = pt->prev;
+ pt->prev->next = pt->next;
+ if (pTimerHead == pt)
+ pTimerHead = pt->next;
+ }
+ pt->flags = 0;
+ }
+
+ // Call the callback function
+ fn = pt->fn;
+ param = pt->param;
+ chMtxUnlock();
+ fn(param);
+
+ // We no longer hold the mutex, the callback function may have taken a while
+ // and our list may have been altered so start again!
+ goto restartTimerChecks;
+ }
+
+ // Find when we next need to wake up
+ if (!(pt->flags & GTIMER_FLG_INFINITE) && pt->when - tm < nxtTimeout)
+ nxtTimeout = pt->when - tm;
+ pt = pt->next;
+ } while(pt != pTimerHead);
+ }
+
+ // Ready for the next loop
+ lastTime = tm;
+ chMtxUnlock();
+ }
+ return 0;
+}
+
+void gtimerInit(GTimer *pt) {
+ pt->flags = 0;
+}
+
+void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, systime_t millisec) {
+ chMtxLock(&mutex);
+
+ // Start our thread if not already going
+ if (!pThread)
+ pThread = chThdCreateStatic(waTimerThread, sizeof(waTimerThread), HIGHPRIO, GTimerThreadHandler, NULL);
+
+ // Is this already scheduled?
+ if (pt->flags & GTIMER_FLG_SCHEDULED) {
+ // Cancel it!
+ if (pt->next == pt->prev)
+ pTimerHead = 0;
+ else {
+ pt->next->prev = pt->prev;
+ pt->prev->next = pt->next;
+ if (pTimerHead == pt)
+ pTimerHead = pt->next;
+ }
+ }
+
+ // Set up the timer structure
+ pt->fn = fn;
+ pt->param = param;
+ pt->flags = GTIMER_FLG_SCHEDULED;
+ if (periodic)
+ pt->flags |= GTIMER_FLG_PERIODIC;
+ if (millisec == TIME_INFINITE) {
+ pt->flags |= GTIMER_FLG_INFINITE;
+ pt->period = TIME_INFINITE;
+ } else {
+ pt->period = MS2ST(millisec);
+ pt->when = chTimeNow() + pt->period;
+ }
+
+ // Just pop it on the end of the queue
+ if (pTimerHead) {
+ pt->next = pTimerHead;
+ pt->prev = pTimerHead->prev;
+ pt->prev->next = pt;
+ pt->next->prev = pt;
+ } else
+ pt->next = pt->prev = pTimerHead = pt;
+
+ // Bump the thread
+ if (!(pt->flags & GTIMER_FLG_INFINITE))
+ chBSemSignal(&waitsem);
+ chMtxUnlock();
+}
+
+void gtimerStop(GTimer *pt) {
+ chMtxLock(&mutex);
+ if (pt->flags & GTIMER_FLG_SCHEDULED) {
+ // Cancel it!
+ if (pt->next == pt->prev)
+ pTimerHead = 0;
+ else {
+ pt->next->prev = pt->prev;
+ pt->prev->next = pt->next;
+ if (pTimerHead == pt)
+ pTimerHead = pt->next;
+ }
+ // Make sure we know the structure is dead!
+ pt->flags = 0;
+ }
+ chMtxUnlock();
+}
+
+bool_t gtimerIsActive(GTimer *pt) {
+ return (pt->flags & GTIMER_FLG_SCHEDULED) ? TRUE : FALSE;
+}
+
+void gtimerJab(GTimer *pt) {
+ chMtxLock(&mutex);
+
+ // Jab it!
+ pt->flags |= GTIMER_FLG_JABBED;
+
+ // Bump the thread
+ chBSemSignal(&waitsem);
+ chMtxUnlock();
+}
+
+void gtimerJabI(GTimer *pt) {
+ // Jab it!
+ pt->flags |= GTIMER_FLG_JABBED;
+
+ // Bump the thread
+ chBSemSignalI(&waitsem);
+}
+
+#endif /* GFX_USE_GTIMER */
+/** @} */
+
diff --git a/src/gtimer/gtimer.mk b/src/gtimer/gtimer.mk
new file mode 100644
index 00000000..e6c2b588
--- /dev/null
+++ b/src/gtimer/gtimer.mk
@@ -0,0 +1 @@
+GFXSRC += $(GFXLIB)/src/gtimer/gtimer.c
diff --git a/src/gwin/button.c b/src/gwin/button.c
new file mode 100644
index 00000000..8a904d95
--- /dev/null
+++ b/src/gwin/button.c
@@ -0,0 +1,275 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file src/gwin/button.c
+ * @brief GWIN sub-system button code.
+ *
+ * @defgroup Button Button
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__)
+
+#include
+
+#include "gwin/internal.h"
+
+static const GButtonStyle GButtonDefaultStyle = {
+ GBTN_3D,
+ HTML2COLOR(0x404040), // color_up_edge;
+ HTML2COLOR(0xE0E0E0), // color_up_fill;
+ HTML2COLOR(0x000000), // color_up_txt;
+ HTML2COLOR(0x404040), // color_dn_edge;
+ HTML2COLOR(0x808080), // color_dn_fill;
+ HTML2COLOR(0x404040), // color_dn_txt;
+ };
+
+// Process an event callback
+static void gwinButtonCallback(void *param, GEvent *pe) {
+ GSourceListener *psl;
+ #define gh ((GHandle)param)
+ #define gbw ((GButtonObject *)param)
+ #define gsh ((GSourceHandle)param)
+ #define pme ((GEventMouse *)pe)
+ #define pte ((GEventTouch *)pe)
+ #define pxe ((GEventToggle *)pe)
+ #define pbe ((GEventGWinButton *)pe)
+
+ switch (pe->type) {
+ #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
+ case GEVENT_MOUSE:
+ case GEVENT_TOUCH:
+ // Ignore anything other than the primary mouse button going up or down
+ if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT))
+ return;
+
+ if (gbw->state == GBTN_UP) {
+ // Our button is UP: Test for button down over the button
+ if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
+ && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
+ && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) {
+ gbw->state = GBTN_DOWN;
+ gwinButtonDraw((GHandle)param);
+ }
+ return;
+ }
+
+ // Our button is DOWN
+
+ // Skip more mouse downs
+ if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT))
+ return;
+
+ // This must be a mouse up - set the button as UP
+ gbw->state = GBTN_UP;
+ gwinButtonDraw((GHandle)param);
+
+ // If the mouse up was over the button then create the event
+ if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
+ && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height)
+ break;
+
+ return;
+ #endif
+
+ #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
+ case GEVENT_TOGGLE:
+ // State has changed - update the button
+ gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP;
+ gwinButtonDraw((GHandle)param);
+
+ // Trigger the event on button down (different than for mouse/touch)
+ if (gbw->state == GBTN_DOWN)
+ break;
+
+ return;
+ #endif
+
+ default:
+ return;
+ }
+
+ // Trigger a GWIN Button Event
+ psl = 0;
+ while ((psl = geventGetSourceListener(gsh, psl))) {
+ if (!(pe = geventGetEventBuffer(psl)))
+ continue;
+ pbe->type = GEVENT_GWIN_BUTTON;
+ pbe->button = gh;
+ geventSendEvent(psl);
+ }
+
+ #undef pbe
+ #undef pme
+ #undef pte
+ #undef pxe
+ #undef gsh
+ #undef gbw
+ #undef gh
+}
+
+GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) {
+ if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject))))
+ return 0;
+ gb->gwin.type = GW_BUTTON;
+ gwinSetFont(&gb->gwin, font);
+ gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle);
+ gb->type = type;
+ gb->state = GBTN_UP;
+ gb->txt = "";
+ geventListenerInit(&gb->listener);
+ geventRegisterCallback(&gb->listener, gwinButtonCallback, gb);
+ return (GHandle)gb;
+}
+
+void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) {
+ #define gbw ((GButtonObject *)gh)
+ if (gh->type != GW_BUTTON)
+ return;
+
+ gbw->style.shape = style->shape;
+ gbw->style.color_up_edge = style->color_up_edge;
+ gbw->style.color_up_fill = style->color_up_fill;
+ gbw->style.color_dn_edge = style->color_dn_edge;
+ gbw->style.color_dn_fill = style->color_dn_fill;
+ gbw->style.color_up_txt = style->color_up_txt;
+ gbw->style.color_dn_txt = style->color_dn_txt;
+ #undef gbw
+}
+
+void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) {
+ #define gbw ((GButtonObject *)gh)
+ if (gh->type != GW_BUTTON)
+ return;
+
+ // Dispose of the old string
+ if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GBTN_FLG_ALLOCTXT;
+ if (gbw->txt) {
+ chHeapFree((void *)gbw->txt);
+ gbw->txt = "";
+ }
+ }
+ // Alloc the new text if required
+ if (txt && useAlloc) {
+ char *str;
+
+ if ((str = (char *)chHeapAlloc(NULL, strlen(txt)+1))) {
+ gh->flags |= GBTN_FLG_ALLOCTXT;
+ strcpy(str, txt);
+ }
+ txt = (const char *)str;
+ }
+
+ gbw->txt = txt ? txt : "";
+ #undef gbw
+}
+
+void gwinButtonDraw(GHandle gh) {
+ color_t cedge;
+ color_t cfill;
+ color_t ctxt;
+ const char * txt;
+ #define gbw ((GButtonObject *)gh)
+ #define RND_CNR_SIZE 5
+
+ if (gh->type != GW_BUTTON)
+ return;
+
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+
+ // Get the text (safely)
+ txt = gh->font && gbw->txt ? gbw->txt : "";
+
+ // Determine the colors to use
+ switch(gbw->state) {
+ case GBTN_DOWN:
+ cedge = gbw->style.color_dn_edge;
+ cfill = gbw->style.color_dn_fill;
+ ctxt = gbw->style.color_dn_txt;
+ break;
+ case GBTN_UP: default:
+ cedge = gbw->style.color_up_edge;
+ cfill = gbw->style.color_up_fill;
+ ctxt = gbw->style.color_up_txt;
+ break;
+ }
+
+ // Draw according to the shape specified.
+ switch(gbw->style.shape) {
+#if GDISP_NEED_ARC
+ case GBTN_ROUNDED:
+ if (gh->width >= 2*RND_CNR_SIZE+10) {
+ gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill);
+ gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter);
+ gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge);
+ break;
+ }
+ /* Fall Through */
+#endif
+ case GBTN_SQUARE:
+ gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter);
+ gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge);
+ break;
+#if GDISP_NEED_ELLIPSE
+ case GBTN_ELLIPSE:
+ gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill);
+ gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter);
+ gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge);
+ break;
+#endif
+ case GBTN_3D: default:
+ gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter);
+ gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge);
+ gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge);
+ break;
+ }
+ #undef gbw
+}
+
+#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
+ bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) {
+ if (gh->type != GW_BUTTON)
+ return FALSE;
+
+ return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
+ }
+#endif
+
+#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
+ bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh) {
+ if (gh->type != GW_BUTTON)
+ return FALSE;
+
+ return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON);
+ }
+#endif
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
+/** @} */
+
diff --git a/src/gwin/console.c b/src/gwin/console.c
new file mode 100644
index 00000000..9be7ee34
--- /dev/null
+++ b/src/gwin/console.c
@@ -0,0 +1,158 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file src/gwin/console.c
+ * @brief GWIN sub-system console code.
+ *
+ * @defgroup Console Console
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__)
+
+#include
+
+#include "gwin/internal.h"
+
+#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE
+#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE
+
+/*
+ * Stream interface implementation. The interface is write only
+ */
+
+#define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream))))
+
+static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; }
+static size_t GWinStreamRead(void *ip, uint8_t *bp, size_t n) { (void)ip; (void)bp; (void)n; return 0; }
+static msg_t GWinStreamPut(void *ip, uint8_t b) { gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; }
+static msg_t GWinStreamGet(void *ip) {(void)ip; return RDY_OK; }
+static msg_t GWinStreamPutTimed(void *ip, uint8_t b, systime_t time) { (void)time; gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; }
+static msg_t GWinStreamGetTimed(void *ip, systime_t timeout) { (void)ip; (void)timeout; return RDY_OK; }
+static size_t GWinStreamWriteTimed(void *ip, const uint8_t *bp, size_t n, systime_t time) { (void)time; gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; }
+static size_t GWinStreamReadTimed(void *ip, uint8_t *bp, size_t n, systime_t time) { (void)ip; (void)bp; (void)n; (void)time; return 0; }
+
+struct GConsoleWindowVMT_t {
+ _base_asynchronous_channel_methods
+};
+
+static const struct GConsoleWindowVMT_t GWindowConsoleVMT = {
+ GWinStreamWrite,
+ GWinStreamRead,
+ GWinStreamPut,
+ GWinStreamGet,
+ GWinStreamPutTimed,
+ GWinStreamGetTimed,
+ GWinStreamWriteTimed,
+ GWinStreamReadTimed
+};
+
+GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) {
+ if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject))))
+ return 0;
+ gc->gwin.type = GW_CONSOLE;
+ gwinSetFont(&gc->gwin, font);
+ gc->stream.vmt = &GWindowConsoleVMT;
+ gc->cx = 0;
+ gc->cy = 0;
+ return (GHandle)gc;
+}
+
+BaseSequentialStream *gwinGetConsoleStream(GHandle gh) {
+ if (gh->type != GW_CONSOLE)
+ return 0;
+ return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream);
+}
+
+void gwinPutChar(GHandle gh, char c) {
+ uint8_t width;
+ #define gcw ((GConsoleObject *)gh)
+
+ if (gh->type != GW_CONSOLE || !gh->font) return;
+
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+
+ if (c == '\n') {
+ gcw->cx = 0;
+ gcw->cy += gcw->fy;
+ // We use lazy scrolling here and only scroll when the next char arrives
+ } else if (c == '\r') {
+ // gcw->cx = 0;
+ } else {
+ width = gdispGetCharWidth(c, gh->font) + gcw->fp;
+ if (gcw->cx + width >= gh->width) {
+ gcw->cx = 0;
+ gcw->cy += gcw->fy;
+ }
+
+ if (gcw->cy + gcw->fy > gh->height) {
+#if GDISP_NEED_SCROLL
+ /* scroll the console */
+ gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor);
+ /* reset the cursor to the start of the last line */
+ gcw->cx = 0;
+ gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy;
+#else
+ /* clear the console */
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
+ /* reset the cursor to the top of the window */
+ gcw->cx = 0;
+ gcw->cy = 0;
+#endif
+ }
+
+#if GWIN_CONSOLE_USE_CLEAR_LINES
+ /* clear to the end of the line */
+ if (gcw->cx == 0)
+ gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor);
+#endif
+#if GWIN_CONSOLE_USE_FILLED_CHARS
+ gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor);
+#else
+ gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color);
+#endif
+
+ /* update cursor */
+ gcw->cx += width;
+ }
+ #undef gcw
+}
+
+void gwinPutString(GHandle gh, const char *str) {
+ while(*str)
+ gwinPutChar(gh, *str++);
+}
+
+void gwinPutCharArray(GHandle gh, const char *str, size_t n) {
+ while(n--)
+ gwinPutChar(gh, *str++);
+}
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */
+/** @} */
+
diff --git a/src/gwin/graph.c b/src/gwin/graph.c
new file mode 100644
index 00000000..a9d20c4b
--- /dev/null
+++ b/src/gwin/graph.c
@@ -0,0 +1,362 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @file src/gwin/graph.c
+ * @brief GWIN sub-system button code.
+ *
+ * @defgroup Graph Graph
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GWIN && GWIN_NEED_GRAPH) || defined(__DOXYGEN__)
+
+#include "gwin/internal.h"
+
+#define GGRAPH_FLG_CONNECTPOINTS (GWIN_FIRST_CONTROL_FLAG<<0)
+#define GGRAPH_ARROW_SIZE 5
+
+static const GGraphStyle GGraphDefaultStyle = {
+ { GGRAPH_POINT_DOT, 0, White }, // point
+ { GGRAPH_LINE_DOT, 2, Gray }, // line
+ { GGRAPH_LINE_SOLID, 0, White }, // x axis
+ { GGRAPH_LINE_SOLID, 0, White }, // y axis
+ { GGRAPH_LINE_NONE, 0, White, 0 }, // x grid
+ { GGRAPH_LINE_NONE, 0, White, 0 }, // y grid
+ GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS // flags
+};
+
+static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointStyle *style) {
+ if (style->type == GGRAPH_POINT_NONE)
+ return;
+
+ // Convert to device space. Note the y-axis is inverted.
+ x += gg->gwin.x + gg->xorigin;
+ y = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y;
+
+ if (style->size <= 1) {
+ gdispDrawPixel(x, y, style->color);
+ return;
+ }
+
+ switch(style->type) {
+ case GGRAPH_POINT_SQUARE:
+ gdispDrawBox(x-style->size, y-style->size, 2*style->size, 2*style->size, style->color);
+ break;
+#if GDISP_NEED_CIRCLE
+ case GGRAPH_POINT_CIRCLE:
+ gdispDrawCircle(x, y, style->size, style->color);
+ break;
+#endif
+ case GGRAPH_POINT_DOT:
+ default:
+ gdispDrawPixel(x, y, style->color);
+ break;
+ }
+}
+
+static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t y1, const GGraphLineStyle *style) {
+ coord_t dy, dx;
+ coord_t addx, addy;
+ coord_t P, diff, i;
+ coord_t run_on, run_off, run;
+
+ if (style->type == GGRAPH_LINE_NONE)
+ return;
+
+ // Convert to device space. Note the y-axis is inverted.
+ x0 += gg->gwin.x + gg->xorigin;
+ y0 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y0;
+ x1 += gg->gwin.x + gg->xorigin;
+ y1 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y1;
+
+ if (style->size <= 0) {
+ // Use the driver to draw a solid line
+ gdispDrawLine(x0, y0, x1, y1, style->color);
+ return;
+ }
+
+ switch (style->type) {
+ case GGRAPH_LINE_DOT:
+ run_on = 1;
+ run_off = -style->size;
+ break;
+
+ case GGRAPH_LINE_DASH:
+ run_on = style->size;
+ run_off = -style->size;
+ break;
+
+ case GGRAPH_LINE_SOLID:
+ default:
+ // Use the driver to draw a solid line
+ gdispDrawLine(x0, y0, x1, y1, style->color);
+ return;
+ }
+
+ // Use Bresenham's algorithm modified to draw a stylized line
+ run = 0;
+ if (x1 >= x0) {
+ dx = x1 - x0;
+ addx = 1;
+ } else {
+ dx = x0 - x1;
+ addx = -1;
+ }
+ if (y1 >= y0) {
+ dy = y1 - y0;
+ addy = 1;
+ } else {
+ dy = y0 - y1;
+ addy = -1;
+ }
+
+ if (dx >= dy) {
+ dy *= 2;
+ P = dy - dx;
+ diff = P - dx;
+
+ for(i=0; i<=dx; ++i) {
+ if (run++ >= 0) {
+ if (run >= run_on)
+ run = run_off;
+ gdispDrawPixel(x0, y0, style->color);
+ }
+ if (P < 0) {
+ P += dy;
+ x0 += addx;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ } else {
+ dx *= 2;
+ P = dx - dy;
+ diff = P - dy;
+
+ for(i=0; i<=dy; ++i) {
+ if (run++ >= 0) {
+ if (run >= run_on)
+ run = run_off;
+ gdispDrawPixel(x0, y0, style->color);
+ }
+ if (P < 0) {
+ P += dx;
+ y0 += addy;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ }
+}
+
+GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) {
+ if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject))))
+ return 0;
+ gg->gwin.type = GW_GRAPH;
+ gg->xorigin = gg->yorigin = 0;
+ gg->lastx = gg->lasty = 0;
+ gwinGraphSetStyle(&gg->gwin, &GGraphDefaultStyle);
+ return (GHandle)gg;
+}
+
+void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) {
+ #define gg ((GGraphObject *)gh)
+
+ if (gh->type != GW_GRAPH)
+ return;
+
+ gg->style.point.type = pstyle->point.type;
+ gg->style.point.size = pstyle->point.size;
+ gg->style.point.color = pstyle->point.color;
+ gg->style.line.type = pstyle->line.type;
+ gg->style.line.size = pstyle->line.size;
+ gg->style.line.color = pstyle->line.color;
+ gg->style.xaxis.type = pstyle->xaxis.type;
+ gg->style.xaxis.size = pstyle->xaxis.size;
+ gg->style.xaxis.color = pstyle->xaxis.color;
+ gg->style.yaxis.type = pstyle->yaxis.type;
+ gg->style.yaxis.size = pstyle->yaxis.size;
+ gg->style.yaxis.color = pstyle->yaxis.color;
+ gg->style.xgrid.type = pstyle->xgrid.type;
+ gg->style.xgrid.size = pstyle->xgrid.size;
+ gg->style.xgrid.color = pstyle->xgrid.color;
+ gg->style.xgrid.spacing = pstyle->xgrid.spacing;
+ gg->style.ygrid.type = pstyle->ygrid.type;
+ gg->style.ygrid.size = pstyle->ygrid.size;
+ gg->style.ygrid.color = pstyle->ygrid.color;
+ gg->style.ygrid.spacing = pstyle->ygrid.spacing;
+ gg->style.flags = pstyle->flags;
+
+ #undef gg
+}
+
+void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y) {
+ #define gg ((GGraphObject *)gh)
+
+ if (gh->type != GW_GRAPH)
+ return;
+
+ gg->xorigin = x;
+ gg->yorigin = y;
+
+ #undef gg
+}
+
+void gwinGraphDrawAxis(GHandle gh) {
+ #define gg ((GGraphObject *)gh)
+ coord_t i, xmin, ymin, xmax, ymax;
+
+ if (gh->type != GW_GRAPH)
+ return;
+
+ xmin = -gg->xorigin;
+ xmax = gh->width-gg->xorigin-1;
+ ymin = -gg->yorigin;
+ ymax = gh->height-gg->yorigin-1;
+
+ // x grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle
+ if (gg->style.xgrid.type != GGRAPH_LINE_NONE && gg->style.xgrid.spacing >= 2) {
+ for(i = gg->style.xgrid.spacing; i <= xmax; i += gg->style.xgrid.spacing)
+ lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid);
+ for(i = -gg->style.xgrid.spacing; i >= xmin; i -= gg->style.xgrid.spacing)
+ lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid);
+ }
+
+ // y grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle
+ if (gg->style.ygrid.type != GGRAPH_LINE_NONE && gg->style.ygrid.spacing >= 2) {
+ for(i = gg->style.ygrid.spacing; i <= ymax; i += gg->style.ygrid.spacing)
+ lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid);
+ for(i = -gg->style.ygrid.spacing; i >= ymin; i -= gg->style.ygrid.spacing)
+ lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid);
+ }
+
+ // x axis
+ lineto(gg, xmin, 0, xmax, 0, &gg->style.xaxis);
+ if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS)) {
+ if (xmin > 0 || xmin < -(GGRAPH_ARROW_SIZE+1)) {
+ lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis);
+ lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis);
+ }
+ }
+ if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS)) {
+ if (xmax < 0 || xmax > (GGRAPH_ARROW_SIZE+1)) {
+ lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis);
+ lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis);
+ }
+ }
+
+ // y axis
+ lineto(gg, 0, ymin, 0, ymax, &gg->style.yaxis);
+ if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS)) {
+ if (ymin > 0 || ymin < -(GGRAPH_ARROW_SIZE+1)) {
+ lineto(gg, 0, ymin, GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis);
+ lineto(gg, 0, ymin, -GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis);
+ }
+ }
+ if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS)) {
+ if (ymax < 0 || ymax > (GGRAPH_ARROW_SIZE+1)) {
+ lineto(gg, 0, ymax, GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis);
+ lineto(gg, 0, ymax, -GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis);
+ }
+ }
+
+ #undef gg
+}
+
+void gwinGraphStartSet(GHandle gh) {
+ if (gh->type != GW_GRAPH)
+ return;
+
+ gh->flags &= ~GGRAPH_FLG_CONNECTPOINTS;
+}
+
+void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) {
+ #define gg ((GGraphObject *)gh)
+
+ if (gh->type != GW_GRAPH)
+ return;
+
+ if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) {
+ // Draw the line
+ lineto(gg, gg->lastx, gg->lasty, x, y, &gg->style.line);
+
+ // Redraw the previous point because the line may have overwritten it
+ pointto(gg, gg->lastx, gg->lasty, &gg->style.point);
+
+ } else
+ gh->flags |= GGRAPH_FLG_CONNECTPOINTS;
+
+ // Save this point for next time.
+ gg->lastx = x;
+ gg->lasty = y;
+
+ // Draw this point.
+ pointto(gg, x, y, &gg->style.point);
+
+ #undef gg
+}
+
+void gwinGraphDrawPoints(GHandle gh, const GGraphPoint *points, unsigned count) {
+ #define gg ((GGraphObject *)gh)
+ unsigned i;
+ const GGraphPoint *p;
+
+ if (gh->type != GW_GRAPH)
+ return;
+
+ // Draw the connecting lines
+ for(p = points, i = 0; i < count; p++, i++) {
+ if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) {
+ // Draw the line
+ lineto(gg, gg->lastx, gg->lasty, p->x, p->y, &gg->style.line);
+
+ // Redraw the previous point because the line may have overwritten it
+ if (i == 0)
+ pointto(gg, gg->lastx, gg->lasty, &gg->style.point);
+
+ } else
+ gh->flags |= GGRAPH_FLG_CONNECTPOINTS;
+
+ // Save this point for next time.
+ gg->lastx = p->x;
+ gg->lasty = p->y;
+ }
+
+
+ // Draw the points.
+ for(p = points, i = 0; i < count; p++, i++)
+ pointto(gg, p->x, p->y, &gg->style.point);
+
+ #undef gg
+}
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_GRAPH */
+/** @} */
+
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
new file mode 100644
index 00000000..4eef79ad
--- /dev/null
+++ b/src/gwin/gwin.c
@@ -0,0 +1,544 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+/**
+ * @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 */
+/** @} */
+
diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk
new file mode 100644
index 00000000..3c560f43
--- /dev/null
+++ b/src/gwin/gwin.mk
@@ -0,0 +1,5 @@
+GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
+ $(GFXLIB)/src/gwin/console.c \
+ $(GFXLIB)/src/gwin/button.c \
+ $(GFXLIB)/src/gwin/graph.c
+
diff --git a/src/tdisp/tdisp.c b/src/tdisp/tdisp.c
new file mode 100644
index 00000000..3556e031
--- /dev/null
+++ b/src/tdisp/tdisp.c
@@ -0,0 +1,85 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012
+ Joel Bodenmann aka Tectu
+
+ 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 .
+*/
+
+/**
+ * @file src/tdisp/tdisp.c
+ * @brief TDISP Driver code.
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_TDISP || defined(__DOXYGEN__)
+
+static uint8_t _displaycontrol;
+
+bool_t tdispInit(void) {
+ bool_t ret;
+
+ ret = tdisp_lld_init();
+
+ return ret;
+}
+
+void tdispControl(uint16_t what, void *value) {
+ tdisp_lld_control(what, value);
+}
+
+void tdispClear(void) {
+ tdisp_lld_clear();
+}
+
+void tdispHome(void) {
+ tdisp_lld_home();
+}
+
+void tdispCreateChar(uint8_t address, char *charmap) {
+ tdisp_lld_create_char(address, charmap);
+}
+
+void tdispSetCursor(coord_t col, coord_t row) {
+ tdisp_lld_set_cursor(col, row);
+}
+
+void tdispDrawChar(char c) {
+ tdisp_lld_write_data(c);
+}
+
+void tdispDrawString(char *s) {
+ while(*s)
+ tdispDrawChar(*s++);
+}
+
+void tdispDrawCharLocation(coord_t col, coord_t row, char c) {
+ tdispSetCursor(col, row);
+ tdispDrawChar(c);
+}
+
+void tdispDrawStringLocation(coord_t col, coord_t row, char *s) {
+ tdispSetCursor(col, row);
+ tdispDrawString(s);
+}
+
+#endif /* GFX_USE_TDISP */
+/** @} */
+
diff --git a/src/tdisp/tdisp.mk b/src/tdisp/tdisp.mk
new file mode 100644
index 00000000..a33fa34a
--- /dev/null
+++ b/src/tdisp/tdisp.mk
@@ -0,0 +1,2 @@
+GFXSRC += $(GFXLIB)/src/tdisp/tdisp.c
+