Merge branch 'master' into usbboot

This commit is contained in:
hathach 2018-05-15 13:29:25 +07:00
commit 5365e51e39
145 changed files with 19449 additions and 50187 deletions

9
.gitmodules vendored
View File

@ -11,6 +11,9 @@
[submodule "lib/berkeley-db-1.xx"]
path = lib/berkeley-db-1.xx
url = https://github.com/pfalcon/berkeley-db-1.xx
[submodule "lib/uzlib"]
path = lib/uzlib
url = https://github.com/pfalcon/uzlib
[submodule "tools/uf2"]
path = tools/uf2
url = https://github.com/Microsoft/uf2.git
@ -46,3 +49,9 @@
[submodule "ports/atmel-samd/freetouch"]
path = ports/atmel-samd/freetouch
url = https://github.com/adafruit/Adafruit_FreeTouch.git
[submodule "frozen/Adafruit_CircuitPython_CircuitPlayground"]
path = frozen/Adafruit_CircuitPython_CircuitPlayground
url = https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git
[submodule "frozen/Adafruit_CircuitPython_HID"]
path = frozen/Adafruit_CircuitPython_HID
url = https://github.com/adafruit/Adafruit_CircuitPython_HID.git

View File

@ -16,7 +16,6 @@ env:
- TRAVIS_BOARD=itsybitsy_m4_express
- TRAVIS_BOARD=metro_m0_express
- TRAVIS_BOARD=metro_m4_express
- TRAVIS_BOARD=metro_m4_express_revb
- TRAVIS_BOARD=pirkey_m0
- TRAVIS_BOARD=trinket_m0
- TRAVIS_BOARD=gemma_m0

View File

@ -6,13 +6,16 @@ PYTHON = python3
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build/$(MICROPY_PORT)
CPYDIFFDIR = ../tools
CPYDIFF = gen-cpydiff.py
GENRSTDIR = genrst
# path to build the generated docs
BUILDDIR = _build
# path to source files to process
SOURCEDIR = .
# path to conf.py
CONFDIR = .
# Run "make FORCE= ..." to avoid rebuilding from scratch (and risk
# producing incorrect docs).
FORCE = -E
VERBOSE = -v
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
@ -22,9 +25,10 @@ endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
BASEOPTS = -c $(CONFDIR) $(PAPEROPT_$(PAPER)) $(FORCE) $(VERBOSE) $(SPHINXOPTS) $(SOURCEDIR)
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(BASEOPTS)
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
I18NSPHINXOPTS = $(BASEOPTS)
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
@ -52,19 +56,12 @@ help:
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " cpydiff to generate the MicroPython differences from CPython"
clean:
rm -rf $(BUILDDIR)/*
rm -f $(GENRSTDIR)/*
cpydiff:
@echo "Generating MicroPython Differences."
rm -f $(GENRSTDIR)/*
cd $(CPYDIFFDIR) && $(PYTHON) $(CPYDIFF)
html: cpydiff
$(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
@ -117,30 +114,34 @@ epub:
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex: cpydiff
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf: cpydiff
$(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
# seems to be malfunctioning
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja: cpydiff
# seems to be malfunctioning
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
# seems to be malfunctioning
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
# seems to be malfunctioning
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo

View File

@ -31,11 +31,14 @@ Designed for CircuitPython
~~~~~~~~~~~~~~~~~~~~~~~~~~
- `Adafruit CircuitPlayground
Express <https://www.adafruit.com/product/3333>`__
Express <https://www.adafruit.com/product/3333>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart>`__)
- `Adafruit Feather M0
Express <https://www.adafruit.com/product/3403>`__
- `Adafruit Metro M0 Express <https://www.adafruit.com/product/3505>`__
- `Adafruit Gemma M0 <https://www.adafruit.com/product/3501>`__
Express <https://www.adafruit.com/product/3403>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/kattni-circuitpython>`__)
- `Adafruit Metro M0 Express <https://www.adafruit.com/product/3505>`_ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m0-express-designed-for-circuitpython/circuitpython>`__)
- `Adafruit Gemma M0 <https://www.adafruit.com/product/3501>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-gemma-m0/circuitpython>`__)
- `Adafruit ItsyBitsy M0 Express <https://www.adafruit.com/product/3727>`_ (no CircuitPython Guide yet!)
- `Adafruit Trinket M0 <https://www.adafruit.com/product/3500>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/circuitpython>`__)
- `Adafruit Metro M4 <https://www.adafruit.com/product/3382>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m4-express-featuring-atsamd51/overview>`__)
Other
~~~~~
@ -69,8 +72,15 @@ System <https://learn.adafruit.com/>`__ under the `CircuitPython
category <https://learn.adafruit.com/category/circuitpython>`__ and
`MicroPython
category <https://learn.adafruit.com/category/micropython>`__. An API
reference is also available on `Read the
Docs <http://circuitpython.readthedocs.io/en/latest/?>`__.
reference is also available on `Read the Docs
<http://circuitpython.readthedocs.io/en/latest/?>`__. A collection of awesome
resources can be found at `Awesome CircuitPython <https://github.com/adafruit/awesome-circuitpython>`__.
Specifically useful documentation when starting out:
- `Welcome to CircuitPython <https://learn.adafruit.com/welcome-to-circuitpython>`__
- `CircuitPython Essentials <https://learn.adafruit.com/circuitpython-essentials>`__
- `Example Code <https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/master/CircuitPython_Essentials>`__
Contributing
------------

View File

@ -22,6 +22,27 @@ preferably in a virtualenv:
In `circuitpython/`, build the docs:
sphinx-build -v -b html . _build/html
make html
You'll find the index page at `_build/html/index.html`.
### More flexibility
Running `make` by itself will list out the multiple doc generating commands available.
All commands will, by default, run with `-E` (forces a rebuild from scratch of docs) and `-v` (verbosity level 1). This can be customized as desired:
# will turn OFF the force rebuild
make html FORCE=
# will turn OFF the verbosity
make html VERBOSE=
# will turn OFF the force rebuild and make it doubly verbose when running
make html FORCE= VERBOSE="-v -v"
You can also pass other options to sphinx by using `SPHINXOPTS`.
make html SPHINXOPTS="-T"
For more flexibility and customization, take a look at the Makefile for all variables you can pass in and overwrite.

View File

@ -1,9 +1,7 @@
:mod:`ubinascii` -- binary/ASCII conversions
:mod:`binascii` -- binary/ASCII conversions
============================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: ubinascii
.. module:: binascii
:synopsis: binary/ASCII conversions
|see_cpython_module| :mod:`cpython:binascii`.

View File

@ -1,9 +1,9 @@
:mod:`ucollections` -- collection and container types
:mod:`collections` -- collection and container types
=====================================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: ucollections
.. module:: collections
:synopsis: collection and container types
|see_cpython_module| :mod:`cpython:collections`.
@ -24,7 +24,7 @@ Classes
a string with space-separated field named (but this is less efficient).
Example of use::
from ucollections import namedtuple
from collections import namedtuple
MyTuple = namedtuple("MyTuple", ("id", "name"))
t1 = MyTuple(1, "foo")
@ -38,7 +38,7 @@ Classes
added. When ordered dict is iterated over, keys/items are returned in
the order they were added::
from ucollections import OrderedDict
from collections import OrderedDict
# To make benefit of ordered keys, OrderedDict should be initialized
# from sequence of (key, value) pairs.

View File

@ -1,9 +1,9 @@
:mod:`uhashlib` -- hashing algorithms
:mod:`hashlib` -- hashing algorithms
=====================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: uhashlib
.. module:: hashlib
:synopsis: hashing algorithms
|see_cpython_module| :mod:`cpython:hashlib`.
@ -29,15 +29,15 @@ be implemented:
Constructors
------------
.. class:: uhashlib.sha256([data])
.. class:: hashlib.sha256([data])
Create an SHA256 hasher object and optionally feed ``data`` into it.
.. class:: uhashlib.sha1([data])
.. class:: hashlib.sha1([data])
Create an SHA1 hasher object and optionally feed ``data`` into it.
.. class:: uhashlib.md5([data])
.. class:: hashlib.md5([data])
Create an MD5 hasher object and optionally feed ``data`` into it.
@ -55,5 +55,5 @@ Methods
.. method:: hash.hexdigest()
This method is NOT implemented. Use ``ubinascii.hexlify(hash.digest())``
This method is NOT implemented. Use ``binascii.hexlify(hash.digest())``
to achieve a similar effect.

View File

@ -20,10 +20,10 @@ Python standard libraries and micro-libraries
array.rst
gc.rst
sys.rst
ubinascii.rst
ucollections.rst
binascii.rst
collections.rst
uerrno.rst
uhashlib.rst
hashlib.rst
uheapq.rst
uio.rst
ujson.rst

View File

@ -202,7 +202,7 @@ Methods
(ssid, bssid, channel, RSSI, authmode, hidden)
*bssid* is hardware address of an access point, in binary form, returned as
bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form.
bytes object. You can use `binascii.hexlify()` to convert it to ASCII form.
There are five values for authmode:

View File

@ -32,11 +32,20 @@
#include "py/binary.h"
#include "extmod/modubinascii.h"
static void check_not_unicode(const mp_obj_t arg) {
#if MICROPY_CPYTHON_COMPAT
if (MP_OBJ_IS_STR(arg)) {
mp_raise_TypeError("a bytes-like object is required");
}
#endif
}
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
// Second argument is for an extension to allow a separator to be used
// between values.
const char *sep = NULL;
mp_buffer_info_t bufinfo;
check_not_unicode(args[0]);
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
// Code below assumes non-zero buffer length when computing size with
@ -165,6 +174,7 @@ mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
check_not_unicode(data);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
@ -218,10 +228,11 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
#if MICROPY_PY_UBINASCII_CRC32
#include "uzlib/tinf.h"
#include "../../lib/uzlib/src/tinf.h"
mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
check_not_unicode(args[0]);
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0;
crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
@ -233,7 +244,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_c
#if MICROPY_PY_UBINASCII
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) },
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_binascii) },
{ MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) },
{ MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },

View File

@ -36,6 +36,14 @@
#include "lib/axtls/crypto/crypto.h"
#endif
static void check_not_unicode(const mp_obj_t arg) {
#if MICROPY_CPYTHON_COMPAT
if (MP_OBJ_IS_STR(arg)) {
mp_raise_TypeError("a bytes-like object is required");
}
#endif
}
typedef struct _mp_obj_hash_t {
mp_obj_base_t base;
char state[0];
@ -70,6 +78,7 @@ STATIC mp_obj_t sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
#endif
STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
check_not_unicode(arg);
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
@ -80,6 +89,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update);
#if MICROPY_PY_UHASHLIB_SHA1
STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg) {
check_not_unicode(arg);
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
@ -139,7 +149,7 @@ STATIC const mp_obj_type_t sha1_type = {
#endif
STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) },
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
{ MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&sha256_type) },
#if MICROPY_PY_UHASHLIB_SHA1
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&sha1_type) },

View File

@ -33,7 +33,7 @@
#if MICROPY_PY_UZLIB
#include "uzlib/tinf.h"
#include "../../lib/uzlib/src/tinf.h"
#if 0 // print debugging info
#define DEBUG_printf DEBUG_printf
@ -215,10 +215,10 @@ const mp_obj_module_t mp_module_uzlib = {
// Source files #include'd here to make sure they're compiled in
// only if module is enabled by config setting.
#include "uzlib/tinflate.c"
#include "uzlib/tinfzlib.c"
#include "uzlib/tinfgzip.c"
#include "uzlib/adler32.c"
#include "uzlib/crc32.c"
#include "../../lib/uzlib/src/tinflate.c"
#include "../../lib/uzlib/src/tinfzlib.c"
#include "../../lib/uzlib/src/tinfgzip.c"
#include "../../lib/uzlib/src/adler32.c"
#include "../../lib/uzlib/src/crc32.c"
#endif // MICROPY_PY_UZLIB

View File

@ -1,78 +0,0 @@
/*
* Adler-32 checksum
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
/*
* Adler-32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
#define A32_BASE 65521
#define A32_NMAX 5552
uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int s1 = prev_sum & 0xffff;
unsigned int s2 = prev_sum >> 16;
while (length > 0)
{
int k = length < A32_NMAX ? length : A32_NMAX;
int i;
for (i = k / 16; i; --i, buf += 16)
{
s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1;
s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1;
s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1;
s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1;
s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1;
s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1;
s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1;
s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1;
}
for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; }
s1 %= A32_BASE;
s2 %= A32_BASE;
length -= k;
}
return (s2 << 16) | s1;
}

View File

@ -1,63 +0,0 @@
/*
* CRC32 checksum
*
* Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
/*
* CRC32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
static const unsigned int tinf_crc32tab[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344,
0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278,
0xbdbdf21c
};
/* crc is previous value for incremental computation, 0xffffffff initially */
uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int i;
for (i = 0; i < length; ++i)
{
crc ^= buf[i];
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
}
// return value suitable for passing in next time, for final value invert it
return crc/* ^ 0xffffffff*/;
}

View File

@ -1,117 +0,0 @@
/*
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*/
#ifndef TINF_H_INCLUDED
#define TINF_H_INCLUDED
#include <stdint.h>
/* calling convention */
#ifndef TINFCC
#ifdef __WATCOMC__
#define TINFCC __cdecl
#else
#define TINFCC
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* ok status, more data produced */
#define TINF_OK 0
/* end of compressed stream reached */
#define TINF_DONE 1
#define TINF_DATA_ERROR (-3)
#define TINF_CHKSUM_ERROR (-4)
#define TINF_DICT_ERROR (-5)
/* checksum types */
#define TINF_CHKSUM_NONE 0
#define TINF_CHKSUM_ADLER 1
#define TINF_CHKSUM_CRC 2
/* data structures */
typedef struct {
unsigned short table[16]; /* table of code length counts */
unsigned short trans[288]; /* code -> symbol translation table */
} TINF_TREE;
struct TINF_DATA;
typedef struct TINF_DATA {
const unsigned char *source;
/* If source above is NULL, this function will be used to read
next byte from source stream */
unsigned char (*readSource)(struct TINF_DATA *data);
unsigned int tag;
unsigned int bitcount;
/* Buffer start */
unsigned char *destStart;
/* Buffer total size */
unsigned int destSize;
/* Current pointer in buffer */
unsigned char *dest;
/* Remaining bytes in buffer */
unsigned int destRemaining;
/* Accumulating checksum */
unsigned int checksum;
char checksum_type;
int btype;
int bfinal;
unsigned int curlen;
int lzOff;
unsigned char *dict_ring;
unsigned int dict_size;
unsigned int dict_idx;
TINF_TREE ltree; /* dynamic length/symbol tree */
TINF_TREE dtree; /* dynamic distance tree */
} TINF_DATA;
#define TINF_PUT(d, c) \
{ \
*d->dest++ = c; \
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
}
unsigned char TINFCC uzlib_get_byte(TINF_DATA *d);
/* Decompression API */
void TINFCC uzlib_init(void);
void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen);
int TINFCC uzlib_uncompress(TINF_DATA *d);
int TINFCC uzlib_uncompress_chksum(TINF_DATA *d);
int TINFCC uzlib_zlib_parse_header(TINF_DATA *d);
int TINFCC uzlib_gzip_parse_header(TINF_DATA *d);
/* Compression API */
void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen);
/* Checksum API */
/* prev_sum is previous value for incremental computation, 1 initially */
uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
/* crc is previous value for incremental computation, 0xffffffff initially */
uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TINF_H_INCLUDED */

View File

@ -1,110 +0,0 @@
/*
* tinfgzip - tiny gzip decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
#include "tinf.h"
#define FTEXT 1
#define FHCRC 2
#define FEXTRA 4
#define FNAME 8
#define FCOMMENT 16
void tinf_skip_bytes(TINF_DATA *d, int num);
uint16_t tinf_get_uint16(TINF_DATA *d);
void tinf_skip_bytes(TINF_DATA *d, int num)
{
while (num--) uzlib_get_byte(d);
}
uint16_t tinf_get_uint16(TINF_DATA *d)
{
unsigned int v = uzlib_get_byte(d);
v = (uzlib_get_byte(d) << 8) | v;
return v;
}
int uzlib_gzip_parse_header(TINF_DATA *d)
{
unsigned char flg;
/* -- check format -- */
/* check id bytes */
if (uzlib_get_byte(d) != 0x1f || uzlib_get_byte(d) != 0x8b) return TINF_DATA_ERROR;
/* check method is deflate */
if (uzlib_get_byte(d) != 8) return TINF_DATA_ERROR;
/* get flag byte */
flg = uzlib_get_byte(d);
/* check that reserved bits are zero */
if (flg & 0xe0) return TINF_DATA_ERROR;
/* -- find start of compressed data -- */
/* skip rest of base header of 10 bytes */
tinf_skip_bytes(d, 6);
/* skip extra data if present */
if (flg & FEXTRA)
{
unsigned int xlen = tinf_get_uint16(d);
tinf_skip_bytes(d, xlen);
}
/* skip file name if present */
if (flg & FNAME) { while (uzlib_get_byte(d)); }
/* skip file comment if present */
if (flg & FCOMMENT) { while (uzlib_get_byte(d)); }
/* check header crc if present */
if (flg & FHCRC)
{
/*unsigned int hcrc =*/ tinf_get_uint16(d);
// TODO: Check!
// if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
// return TINF_DATA_ERROR;
}
/* initialize for crc32 checksum */
d->checksum_type = TINF_CHKSUM_CRC;
d->checksum = ~0;
return TINF_OK;
}

View File

@ -1,551 +0,0 @@
/*
* tinflate - tiny inflate
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
#include <assert.h>
#include "tinf.h"
uint32_t tinf_get_le_uint32(TINF_DATA *d);
uint32_t tinf_get_be_uint32(TINF_DATA *d);
/* --------------------------------------------------- *
* -- uninitialized global data (static structures) -- *
* --------------------------------------------------- */
#ifdef RUNTIME_BITS_TABLES
/* extra bits and base tables for length codes */
unsigned char length_bits[30];
unsigned short length_base[30];
/* extra bits and base tables for distance codes */
unsigned char dist_bits[30];
unsigned short dist_base[30];
#else
const unsigned char length_bits[30] = {
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4,
5, 5, 5, 5
};
const unsigned short length_base[30] = {
3, 4, 5, 6, 7, 8, 9, 10,
11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115,
131, 163, 195, 227, 258
};
const unsigned char dist_bits[30] = {
0, 0, 0, 0, 1, 1, 2, 2,
3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10,
11, 11, 12, 12, 13, 13
};
const unsigned short dist_base[30] = {
1, 2, 3, 4, 5, 7, 9, 13,
17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073,
4097, 6145, 8193, 12289, 16385, 24577
};
#endif
/* special ordering of code length codes */
const unsigned char clcidx[] = {
16, 17, 18, 0, 8, 7, 9, 6,
10, 5, 11, 4, 12, 3, 13, 2,
14, 1, 15
};
/* ----------------------- *
* -- utility functions -- *
* ----------------------- */
#ifdef RUNTIME_BITS_TABLES
/* build extra bits and base tables */
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
{
int i, sum;
/* build bits table */
for (i = 0; i < delta; ++i) bits[i] = 0;
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta;
/* build base table */
for (sum = first, i = 0; i < 30; ++i)
{
base[i] = sum;
sum += 1 << bits[i];
}
}
#endif
/* build the fixed huffman trees */
static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt)
{
int i;
/* build fixed length tree */
for (i = 0; i < 7; ++i) lt->table[i] = 0;
lt->table[7] = 24;
lt->table[8] = 152;
lt->table[9] = 112;
for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i;
for (i = 0; i < 144; ++i) lt->trans[24 + i] = i;
for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i;
for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i;
/* build fixed distance tree */
for (i = 0; i < 5; ++i) dt->table[i] = 0;
dt->table[5] = 32;
for (i = 0; i < 32; ++i) dt->trans[i] = i;
}
/* given an array of code lengths, build a tree */
static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num)
{
unsigned short offs[16];
unsigned int i, sum;
/* clear code length count table */
for (i = 0; i < 16; ++i) t->table[i] = 0;
/* scan symbol lengths, and sum code length counts */
for (i = 0; i < num; ++i) t->table[lengths[i]]++;
t->table[0] = 0;
/* compute offset table for distribution sort */
for (sum = 0, i = 0; i < 16; ++i)
{
offs[i] = sum;
sum += t->table[i];
}
/* create code->symbol translation table (symbols sorted by code) */
for (i = 0; i < num; ++i)
{
if (lengths[i]) t->trans[offs[lengths[i]]++] = i;
}
}
/* ---------------------- *
* -- decode functions -- *
* ---------------------- */
unsigned char uzlib_get_byte(TINF_DATA *d)
{
if (d->source) {
return *d->source++;
}
return d->readSource(d);
}
uint32_t tinf_get_le_uint32(TINF_DATA *d)
{
uint32_t val = 0;
int i;
for (i = 4; i--;) {
val = val >> 8 | uzlib_get_byte(d) << 24;
}
return val;
}
uint32_t tinf_get_be_uint32(TINF_DATA *d)
{
uint32_t val = 0;
int i;
for (i = 4; i--;) {
val = val << 8 | uzlib_get_byte(d);
}
return val;
}
/* get one bit from source stream */
static int tinf_getbit(TINF_DATA *d)
{
unsigned int bit;
/* check if tag is empty */
if (!d->bitcount--)
{
/* load next tag */
d->tag = uzlib_get_byte(d);
d->bitcount = 7;
}
/* shift bit out of tag */
bit = d->tag & 0x01;
d->tag >>= 1;
return bit;
}
/* read a num bit value from a stream and add base */
static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base)
{
unsigned int val = 0;
/* read num bits */
if (num)
{
unsigned int limit = 1 << (num);
unsigned int mask;
for (mask = 1; mask < limit; mask *= 2)
if (tinf_getbit(d)) val += mask;
}
return val + base;
}
/* given a data stream and a tree, decode a symbol */
static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
{
int sum = 0, cur = 0, len = 0;
/* get more bits while code value is above sum */
do {
cur = 2*cur + tinf_getbit(d);
++len;
sum += t->table[len];
cur -= t->table[len];
} while (cur >= 0);
return t->trans[sum + cur];
}
/* given a data stream, decode dynamic trees from it */
static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
{
unsigned char lengths[288+32];
unsigned int hlit, hdist, hclen;
unsigned int i, num, length;
/* get 5 bits HLIT (257-286) */
hlit = tinf_read_bits(d, 5, 257);
/* get 5 bits HDIST (1-32) */
hdist = tinf_read_bits(d, 5, 1);
/* get 4 bits HCLEN (4-19) */
hclen = tinf_read_bits(d, 4, 4);
for (i = 0; i < 19; ++i) lengths[i] = 0;
/* read code lengths for code length alphabet */
for (i = 0; i < hclen; ++i)
{
/* get 3 bits code length (0-7) */
unsigned int clen = tinf_read_bits(d, 3, 0);
lengths[clcidx[i]] = clen;
}
/* build code length tree, temporarily use length tree */
tinf_build_tree(lt, lengths, 19);
/* decode code lengths for the dynamic trees */
for (num = 0; num < hlit + hdist; )
{
int sym = tinf_decode_symbol(d, lt);
switch (sym)
{
case 16:
/* copy previous code length 3-6 times (read 2 bits) */
{
unsigned char prev = lengths[num - 1];
for (length = tinf_read_bits(d, 2, 3); length; --length)
{
lengths[num++] = prev;
}
}
break;
case 17:
/* repeat code length 0 for 3-10 times (read 3 bits) */
for (length = tinf_read_bits(d, 3, 3); length; --length)
{
lengths[num++] = 0;
}
break;
case 18:
/* repeat code length 0 for 11-138 times (read 7 bits) */
for (length = tinf_read_bits(d, 7, 11); length; --length)
{
lengths[num++] = 0;
}
break;
default:
/* values 0-15 represent the actual code lengths */
lengths[num++] = sym;
break;
}
}
/* build dynamic trees */
tinf_build_tree(lt, lengths, hlit);
tinf_build_tree(dt, lengths + hlit, hdist);
}
/* ----------------------------- *
* -- block inflate functions -- *
* ----------------------------- */
/* given a stream and two trees, inflate a block of data */
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
{
if (d->curlen == 0) {
unsigned int offs;
int dist;
int sym = tinf_decode_symbol(d, lt);
//printf("huff sym: %02x\n", sym);
/* literal byte */
if (sym < 256) {
TINF_PUT(d, sym);
return TINF_OK;
}
/* end of block */
if (sym == 256) {
return TINF_DONE;
}
/* substring from sliding dictionary */
sym -= 257;
/* possibly get more bits from length code */
d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]);
dist = tinf_decode_symbol(d, dt);
/* possibly get more bits from distance code */
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
if (d->dict_ring) {
if (offs > d->dict_size) {
return TINF_DICT_ERROR;
}
d->lzOff = d->dict_idx - offs;
if (d->lzOff < 0) {
d->lzOff += d->dict_size;
}
} else {
d->lzOff = -offs;
}
}
/* copy next byte from dict substring */
if (d->dict_ring) {
TINF_PUT(d, d->dict_ring[d->lzOff]);
if ((unsigned)++d->lzOff == d->dict_size) {
d->lzOff = 0;
}
} else {
d->dest[0] = d->dest[d->lzOff];
d->dest++;
}
d->curlen--;
return TINF_OK;
}
/* inflate an uncompressed block of data */
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
{
if (d->curlen == 0) {
unsigned int length, invlength;
/* get length */
length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
/* get one's complement of length */
invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
/* check length */
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
/* increment length to properly return TINF_DONE below, without
producing data at the same time */
d->curlen = length + 1;
/* make sure we start next block on a byte boundary */
d->bitcount = 0;
}
if (--d->curlen == 0) {
return TINF_DONE;
}
unsigned char c = uzlib_get_byte(d);
TINF_PUT(d, c);
return TINF_OK;
}
/* ---------------------- *
* -- public functions -- *
* ---------------------- */
/* initialize global (static) data */
void uzlib_init(void)
{
#ifdef RUNTIME_BITS_TABLES
/* build extra bits and base tables */
tinf_build_bits_base(length_bits, length_base, 4, 3);
tinf_build_bits_base(dist_bits, dist_base, 2, 1);
/* fix a special case */
length_bits[28] = 0;
length_base[28] = 258;
#endif
}
/* initialize decompression structure */
void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen)
{
d->bitcount = 0;
d->bfinal = 0;
d->btype = -1;
d->dict_size = dictLen;
d->dict_ring = dict;
d->dict_idx = 0;
d->curlen = 0;
}
/* inflate next byte of compressed stream */
int uzlib_uncompress(TINF_DATA *d)
{
do {
int res;
/* start a new block */
if (d->btype == -1) {
next_blk:
/* read final block flag */
d->bfinal = tinf_getbit(d);
/* read block type (2 bits) */
d->btype = tinf_read_bits(d, 2, 0);
//printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal);
if (d->btype == 1) {
/* build fixed huffman trees */
tinf_build_fixed_trees(&d->ltree, &d->dtree);
} else if (d->btype == 2) {
/* decode trees from stream */
tinf_decode_trees(d, &d->ltree, &d->dtree);
}
}
/* process current block */
switch (d->btype)
{
case 0:
/* decompress uncompressed block */
res = tinf_inflate_uncompressed_block(d);
break;
case 1:
case 2:
/* decompress block with fixed/dyanamic huffman trees */
/* trees were decoded previously, so it's the same routine for both */
res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
break;
default:
return TINF_DATA_ERROR;
}
if (res == TINF_DONE && !d->bfinal) {
/* the block has ended (without producing more data), but we
can't return without data, so start procesing next block */
goto next_blk;
}
if (res != TINF_OK) {
return res;
}
} while (--d->destSize);
return TINF_OK;
}
int uzlib_uncompress_chksum(TINF_DATA *d)
{
int res;
unsigned char *data = d->dest;
res = uzlib_uncompress(d);
if (res < 0) return res;
switch (d->checksum_type) {
case TINF_CHKSUM_ADLER:
d->checksum = uzlib_adler32(data, d->dest - data, d->checksum);
break;
case TINF_CHKSUM_CRC:
d->checksum = uzlib_crc32(data, d->dest - data, d->checksum);
break;
}
if (res == TINF_DONE) {
unsigned int val;
switch (d->checksum_type) {
case TINF_CHKSUM_ADLER:
val = tinf_get_be_uint32(d);
if (d->checksum != val) {
return TINF_CHKSUM_ERROR;
}
break;
case TINF_CHKSUM_CRC:
val = tinf_get_le_uint32(d);
if (~d->checksum != val) {
return TINF_CHKSUM_ERROR;
}
// Uncompressed size. TODO: Check
val = tinf_get_le_uint32(d);
break;
}
}
return res;
}

View File

@ -1,66 +0,0 @@
/*
* tinfzlib - tiny zlib decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
#include "tinf.h"
int uzlib_zlib_parse_header(TINF_DATA *d)
{
unsigned char cmf, flg;
/* -- get header bytes -- */
cmf = uzlib_get_byte(d);
flg = uzlib_get_byte(d);
/* -- check format -- */
/* check checksum */
if ((256*cmf + flg) % 31) return TINF_DATA_ERROR;
/* check method is deflate */
if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR;
/* check window size is valid */
if ((cmf >> 4) > 7) return TINF_DATA_ERROR;
/* check there is no preset dictionary */
if (flg & 0x20) return TINF_DATA_ERROR;
/* initialize for adler32 checksum */
d->checksum_type = TINF_CHKSUM_ADLER;
d->checksum = 1;
return cmf >> 4;
}

@ -1 +1 @@
Subproject commit 39f28ed4e0e5a06fc33fd01c1efc8c52c4140f03
Subproject commit de2d0d33cace54532467e411128521dfc8d253c3

@ -0,0 +1 @@
Subproject commit a669915237545638c64f89400f368a91c408cd5d

@ -0,0 +1 @@
Subproject commit 90e4ca931a991718985e655bdcd527c1b0543f55

@ -1 +1 @@
Subproject commit fa00b61d1bde90c3cf9cce74388cb9717058b2be
Subproject commit d5491cded0d12716ceb1111ca4c4431111a22df6

@ -1 +1 @@
Subproject commit 1142f1c7fdc232a46d74dd4f1946a5f462ae2555
Subproject commit e9f50cb6678a1684591ee021b95a3c4b51786fee

@ -1 +1 @@
Subproject commit 2d57c0ba9a09d6d30f0ae2b98aba9567c25e6fb6
Subproject commit 00f4ebca6c740b76c1c464f83d514ac20b0600e1

1
lib/uzlib Submodule

@ -0,0 +1 @@
Subproject commit 27176508e188c0900877e810be34198cd88dcb63

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

View File

@ -1,97 +0,0 @@
The font used for the MicroPython logo is "Exo",
http://www.google.com/fonts/specimen/Exo.
Copyright (c) 2013, Natanael Gama (https://plus.google.com/u/0/+NatanaelGama),
with Reserved Font Name Exo.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 90 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 600 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 107 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 165 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 322 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 183 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 114 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 309 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 98 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 172 KiB

View File

@ -1,523 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="765.09448"
height="779.328"
id="svg2">
<defs
id="defs4">
<symbol
id="*Paper_Space0" />
<symbol
id="*Paper_Space" />
<symbol
id="*Model_Space" />
<pattern
height="8"
id="Hatch"
patternUnits="userSpaceOnUse"
width="8"
x="0"
y="0">
<path
d="M8 4 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3049" />
<path
d="M6 2 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3051" />
<path
d="M4 0 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3053" />
</pattern>
<marker
refX="0"
refY="0"
orient="auto"
id="DistanceX"
style="overflow:visible">
<path
d="M 3,-3 -3,3 M 0,-5 0,5"
id="path3046"
style="stroke:#000000;stroke-width:0.5" />
</marker>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-1595.2072,-3900.1734)"
id="layer1">
<g
transform="translate(1605.7072,3616.6359)"
id="g3058" />
<g
transform="translate(1605.7072,3616.6359)"
id="g3060">
<path
d="m 376.28676,565.33282 a 50.505437,50.505437 0 0 0 2.94079,-22.54604 4.006761,4.006761 0 1 0 -7.97559,0.77878 42.491917,42.491917 0 0 1 -2.47419,18.96875 4.0067627,4.0067627 0 0 0 7.50899,2.79851 z"
id="path3062"
style="fill:none;stroke:#00ff00" />
<path
d="m 310.44438,550.74978 a 59.389614,59.389614 0 0 1 1.23877,-16.00076 4.0067628,4.0067628 0 0 1 7.83278,1.69238 51.376093,51.376093 0 0 0 -1.07162,13.84176 4.0067635,4.0067635 0 0 1 -7.99993,0.46662 z"
id="path3064"
style="fill:none;stroke:#00ff00" />
<path
d="m 392.10618,427.13329 a 12.200345,12.200345 0 0 0 12.0626,-15.93766 22.471543,22.471543 0 0 0 -5.15835,-8.6452 11.14774,11.14774 0 0 0 -16.96297,10.95558 4.0067603,4.0067603 0 0 0 7.93984,-1.08418 3.13422,3.13422 0 0 1 4.03924,-3.41591 14.458023,14.458023 0 0 1 2.51573,4.64997 4.186825,4.186825 0 0 1 -4.13955,5.46937 4.0067602,4.0067602 0 0 0 -0.29654,8.00803 z"
id="path3066"
style="fill:none;stroke:#00ff00" />
<path
d="m 371.77724,411.5205 a 15.711594,15.711594 0 0 0 -0.4822,-3.9744 3.414554,3.414554 0 0 0 -6.42324,-0.56196 8.601878,8.601878 0 0 0 3.73033,11.08591 4.00676,4.00676 0 0 1 -3.83196,7.03793 16.615399,16.615399 0 0 1 -7.20551,-21.41355 11.428075,11.428075 0 0 1 21.49777,1.88081 23.725114,23.725114 0 0 1 0.72814,6.0015 4.0067635,4.0067635 0 0 1 -8.01333,-0.0562 z"
id="path3068"
style="fill:none;stroke:#00ff00" />
<path
d="m 379.3526,301.76746 a 23.936355,23.936355 0 0 0 -9.95309,7.37952 4.0067642,4.0067642 0 1 1 -6.27618,-4.98259 31.949875,31.949875 0 0 1 13.28523,-9.85006 4.0067605,4.0067605 0 0 1 2.94404,7.45313 z"
id="path3070"
style="fill:none;stroke:#00ff00" />
<path
d="m 445.68236,329.11654 a 17.364203,17.364203 0 0 0 -11.77173,-12.76486 4.0067634,4.0067634 0 1 1 2.3854,-7.65026 25.377723,25.377723 0 0 1 17.20435,18.65581 4.0067633,4.0067633 0 0 1 -7.81802,1.75931 z"
id="path3072"
style="fill:none;stroke:#00ff00" />
<path
d="m 573.77832,824.21829 a 231.49358,231.49358 0 0 0 42.29005,-25.76377 97.552014,97.552014 0 0 1 -10.48364,37.94069 29.283353,29.283353 0 0 1 -12.73834,12.73834 208.98141,208.98141 0 0 1 -37.85329,14.91063 102.01883,102.01883 0 0 0 18.78522,-39.82589 z"
id="path3074"
style="fill:none;stroke:#00ff00" />
<path
d="m 409.47237,828.37833 a 223.48006,223.48006 0 0 0 206.73547,-40.24557 97.552014,97.552014 0 0 0 -0.19497,-3.41849 80.161845,80.161845 0 0 0 -11.72761,-36.13952 26.25055,26.25055 0 0 0 -21.76496,-12.45524 215.19714,215.19714 0 0 1 -186.57181,44.02404 217.80817,217.80817 0 0 0 13.52388,48.23478 z"
id="path3076"
style="fill:none;stroke:#00ff00" />
<path
d="m 517.45426,842.3746 a 107.84051,107.84051 0 0 1 -13.06728,29.83277 381.1671,381.1671 0 0 0 15.49202,-1.3351 208.98141,208.98141 0 0 0 21.55961,-3.44895 94.005315,94.005315 0 0 0 22.97314,-39.0461 231.49358,231.49358 0 0 1 -46.95749,13.99738 z"
id="path3078"
style="fill:none;stroke:#00ff00" />
<path
d="m 450.45349,871.92484 a 82.150232,82.150232 0 0 0 12.01617,-26.0055 231.49358,231.49358 0 0 0 46.23144,-2.09169 99.826988,99.826988 0 0 1 -14.33124,28.90521 381.1671,381.1671 0 0 1 -43.91637,-0.80802 z"
id="path3080"
style="fill:none;stroke:#00ff00" />
<path
d="m 413.65999,837.94547 a 231.49358,231.49358 0 0 0 40.66298,7.38175 74.136712,74.136712 0 0 1 -12.82798,25.25052 39.270306,39.270306 0 0 1 -20.00183,-17.43165 217.80817,217.80817 0 0 1 -7.83317,-15.20062 z"
id="path3082"
style="fill:none;stroke:#00ff00" />
<path
d="m 394.76071,771.6117 a 207.18362,207.18362 0 0 0 23.71188,4.47646 73.871194,73.871194 0 0 0 1.94716,-13.81518 232.6189,232.6189 0 0 1 -26.66931,-1.40174 217.80817,217.80817 0 0 0 1.01027,10.74046 z"
id="path3084"
style="fill:none;stroke:#00ff00" />
<path
d="m 426.49583,776.96489 a 207.18362,207.18362 0 0 0 44.08456,-0.76029 79.152083,79.152083 0 0 0 9.83174,-22.10671 232.6189,232.6189 0 0 1 -51.96427,7.99697 81.884715,81.884715 0 0 1 -1.95203,14.87003 z"
id="path3086"
style="fill:none;stroke:#00ff00" />
<path
d="m 489.28386,751.49075 a 87.165603,87.165603 0 0 1 -8.50621,23.18584 207.18362,207.18362 0 0 0 55.05061,-17.86255 77.758554,77.758554 0 0 0 2.10781,-27.07964 232.6189,232.6189 0 0 1 -48.65221,21.75635 z"
id="path3088"
style="fill:none;stroke:#00ff00" />
<path
d="m 393.3415,752.76013 a 217.80817,217.80817 0 0 1 1.1775,-30.55375 283.78976,283.78976 0 0 1 1.37461,-10.69942 202.37681,202.37681 0 0 0 114.74785,-44.62022 l 13.46305,-9.42693 a 30.662014,30.662014 0 0 1 30.54534,-2.67237 43.31958,43.31958 0 0 1 24.50085,32.62626 224.60538,224.60538 0 0 1 -185.8092,65.34643 z"
id="path3090"
style="fill:none;stroke:#00ff00" />
<path
d="m 397.2145,703.38787 a 194.36329,194.36329 0 0 0 108.49341,-42.81743 23.586902,23.586902 0 0 0 7.177,-26.78491 9.918601,9.918601 0 0 0 -9.0861,-6.36216 46.235274,46.235274 0 0 0 -20.07565,4.19848 368.58869,368.58869 0 0 0 -82.20858,51.76929 283.78976,283.78976 0 0 0 -4.30008,19.99673 z"
id="path3092"
style="fill:none;stroke:#00ff00" />
<path
d="m 330.50955,405.93841 a 43.354257,43.354257 0 0 0 -21.50063,22.02808 209.96578,209.96578 0 0 0 -17.42053,85.99371 70.711924,70.711924 0 0 0 11.83735,38.4211 73.780204,73.780204 0 0 0 36.19311,28.46005 56.856184,56.856184 0 0 0 26.52196,2.98592 76.570466,76.570466 0 0 0 22.51248,-6.43214 134.78926,134.78926 0 0 0 31.95362,-20.63291 86.740478,86.740478 0 0 0 29.81077,-62.11513 288.53091,288.53091 0 0 0 -2.17155,-48.33622 33.216431,33.216431 0 0 0 -13.19493,-22.44209 85.769489,85.769489 0 0 1 -11.32318,18.65937 20.678757,20.678757 0 0 1 -29.15081,3.20659 l -12.48299,-10.06693 -5.83399,3.19814 a 20.393506,20.393506 0 0 1 -20.81496,1.9248 43.705101,43.705101 0 0 1 -23.03486,-26.94516 75.590657,75.590657 0 0 1 -1.90086,-7.90718 z"
id="path3094"
style="fill:none;stroke:#00ff00" />
<path
d="m 382.94763,426.06136 16.66009,13.43555 a 12.665237,12.665237 0 0 0 17.85416,-1.96395 77.755969,77.755969 0 0 0 11.39889,-77.33361 16.166727,16.166727 0 0 0 -27.11236,-4.71923 57.567866,57.567866 0 0 0 -9.01787,14.03492 4.00676,4.00676 0 0 1 -7.47927,-2.8312 l 3.66419,-11.92814 a 20.187638,20.187638 0 0 0 -4.10085,-15.3254 13.55444,13.55444 0 0 0 -18.36656,-2.78633 67.577137,67.577137 0 0 0 -26.35813,74.91214 35.691581,35.691581 0 0 0 18.81131,22.00464 12.379986,12.379986 0 0 0 12.99693,-1.44218 l 11.04947,-6.05721 z"
id="path3096"
style="fill:none;stroke:#00ff00" />
<path
d="m 179.88519,850.89001 a 143.93977,143.93977 0 0 0 -60.7871,11.41043 39.086677,39.086677 0 0 1 31.634,-33.28021 75.323314,75.323314 0 0 0 2.87715,2.61567 204.7432,204.7432 0 0 0 26.27595,19.25411 z"
id="path3098"
style="fill:none;stroke:#00ff00" />
<path
d="m 180.7201,841.94194 a 63.377551,63.377551 0 0 1 -1.06614,-14.26533 168.39098,168.39098 0 0 0 36.56014,14.90295 79.890316,79.890316 0 0 0 10.90348,21.32858 196.72968,196.72968 0 0 1 -46.39748,-21.9662 z"
id="path3100"
style="fill:none;stroke:#00ff00" />
<path
d="m 155.0269,736.60456 a 82.876006,82.876006 0 0 0 27.62666,25.09115 130.32087,130.32087 0 0 0 74.55456,16.14168 164.72099,164.72099 0 0 0 15.34776,62.39714 160.37746,160.37746 0 0 1 -136.796,-59.85916 67.309794,67.309794 0 0 1 -0.20129,-8.24674 45.220678,45.220678 0 0 1 19.46831,-35.52407 z"
id="path3102"
style="fill:none;stroke:#00ff00" />
<path
d="m 139.14621,796.42854 a 168.39098,168.39098 0 0 0 32.78872,26.71342 71.391072,71.391072 0 0 0 -0.11078,12.70846 196.72968,196.72968 0 0 1 -12.97919,-10.28113 67.309794,67.309794 0 0 1 -19.69875,-29.14075 z"
id="path3104"
style="fill:none;stroke:#00ff00" />
<path
d="m 341.4891,589.85722 a 55.435829,55.435829 0 0 0 -3.2324,14.50355 71.84369,71.84369 0 0 1 11.19892,-6.75508 18.566982,18.566982 0 0 1 23.47316,6.28961 55.133466,55.133466 0 0 1 9.2031,25.28531 115.24382,115.24382 0 0 1 -6.52826,51.71425 126.76861,126.76861 0 0 0 -6.84034,27.96367 258.78206,258.78206 0 0 0 9.55239,109.18435 88.989436,88.989436 0 0 0 27.4297,41.50727 115.2534,115.2534 0 0 0 7.14653,-5.382 225.82169,225.82169 0 0 1 -26.33907,-132.83166 291.80328,291.80328 0 0 1 25.82839,-92.10092 8852.0265,8852.0265 0 0 0 12.90415,-27.67305 271.41458,271.41458 0 0 0 20.23505,-62.43919 94.753998,94.753998 0 0 1 -19.66016,23.69024 142.80278,142.80278 0 0 1 -33.85334,21.85959 84.583986,84.583986 0 0 1 -24.86854,7.10529 64.869704,64.869704 0 0 1 -25.64928,-1.92123 z"
id="path3106"
style="fill:none;stroke:#00ff00" />
<path
d="m 369.13833,815.32419 a 74.028904,74.028904 0 0 1 -95.89339,5.11915 156.70747,156.70747 0 0 0 7.87587,19.12 72.321745,72.321745 0 0 0 10.15696,15.35524 101.22787,101.22787 0 0 0 67.15775,-1.90467 4.00676,4.00676 0 1 1 2.87252,7.48098 109.24139,109.24139 0 0 1 -57.82815,5.65243 72.321745,72.321745 0 0 0 22.40696,10.97918 68.754331,68.754331 0 0 0 26.53851,2.32182 115.2534,115.2534 0 0 0 46.29388,-15.39035 97.002956,97.002956 0 0 1 -28.05765,-43.64199 266.79558,266.79558 0 0 1 -1.52326,-5.09179 z"
id="path3108"
style="fill:none;stroke:#00ff00" />
<path
d="m 331.35491,621.89163 a 63.83017,63.83017 0 0 0 -6.26256,9.21212 593.88382,593.88382 0 0 0 -3.81437,6.93228 23.165032,23.165032 0 0 0 9.50587,5.45484 4.00676,4.00676 0 0 1 -2.23105,7.69668 31.178552,31.178552 0 0 1 -11.14625,-5.8833 593.88382,593.88382 0 0 0 -6.91493,13.6255 407.95821,407.95821 0 0 1 -4.08498,8.0845 48.659079,48.659079 0 0 0 46.84863,19.18747 4.0067617,4.0067617 0 1 1 1.2638,7.91324 56.672599,56.672599 0 0 1 -52.22496,-19.38464 407.95821,407.95821 0 0 1 -16.52659,27.58179 65.112051,65.112051 0 0 0 52.57372,21.39817 4.0067601,4.0067601 0 1 1 0.51631,7.99687 73.125571,73.125571 0 0 1 -57.61157,-22.48672 105.69968,105.69968 0 0 0 -14.77227,40.38221 82.248315,82.248315 0 0 0 75.51268,24.07677 4.00676,4.00676 0 0 1 1.54551,7.86307 90.261836,90.261836 0 0 1 -78.11221,-21.76739 156.70747,156.70747 0 0 0 3.66136,45.9627 66.015383,66.015383 0 0 0 97.64216,0.62811 266.79558,266.79558 0 0 1 -5.90981,-98.5153 134.78213,134.78213 0 0 1 7.27275,-29.73136 107.2303,107.2303 0 0 0 6.07431,-48.11829 47.119946,47.119946 0 0 0 -7.86545,-21.61014 10.553462,10.553462 0 0 0 -13.34213,-3.57501 63.83017,63.83017 0 0 0 -14.61804,9.78433 55.435829,55.435829 0 0 0 2.04764,10.34614 80.71878,80.71878 0 0 0 10.60797,22.29072 29.900833,29.900833 0 0 1 0,33.65259 4.0067602,4.0067602 0 0 1 -6.62426,-4.50951 21.887312,21.887312 0 0 0 1.95062,-21.10962 31.201566,31.201566 0 0 1 -14.27347,19.66503 4.0067611,4.0067611 0 0 1 -4.14047,-6.86098 23.188046,23.188046 0 0 0 9.62936,-28.26012 88.732301,88.732301 0 0 1 -4.82714,-12.57156 63.449349,63.449349 0 0 1 -1.35018,-5.35119 z"
id="path3110"
style="fill:none;stroke:#00ff00" />
<path
d="m 269.57245,713.65446 a 113.7132,113.7132 0 0 0 -11.4262,37.77549 110.10404,110.10404 0 0 1 -96.97148,-61.264 49.107667,49.107667 0 0 1 17.58582,-15.78918 36.418066,36.418066 0 0 1 25.93358,-3.17223 30.817043,30.817043 0 0 0 2.53011,4.95806 72.633968,72.633968 0 0 0 22.72798,22.72798 103.55567,103.55567 0 0 0 39.62019,14.76388 z"
id="path3112"
style="fill:none;stroke:#00ff00" />
<path
d="m 215.86437,750.95726 a 106.24555,106.24555 0 0 0 1.67841,15.89514 122.30735,122.30735 0 0 1 -30.97555,-12.14953 74.862486,74.862486 0 0 1 -7.75035,-4.98777 64.183337,64.183337 0 0 1 2.26887,-20.3627 118.11756,118.11756 0 0 0 34.77862,21.60486 z"
id="path3114"
style="fill:none;stroke:#00ff00" />
<path
d="m 174.63302,723.11977 a 72.196858,72.196858 0 0 0 -3.81679,19.80765 74.862486,74.862486 0 0 1 -13.79039,-18.41208 28.198881,28.198881 0 0 1 -1.92017,-21.94772 49.107667,49.107667 0 0 1 1.46515,-3.93072 118.11756,118.11756 0 0 0 18.0622,24.48287 z"
id="path3116"
style="fill:none;stroke:#00ff00" />
<path
d="m 273.73824,706.13565 a 95.542154,95.542154 0 0 1 -39.51377,-14.0248 64.620448,64.620448 0 0 1 -20.22046,-20.22046 22.803523,22.803523 0 0 1 26.02263,-33.94491 149.61449,149.61449 0 0 1 55.90254,31.71704 399.94469,399.94469 0 0 1 -19.33967,31.99615 113.7132,113.7132 0 0 0 -2.85127,4.47698 z"
id="path3118"
style="fill:none;stroke:#00ff00" />
<path
d="m 545.05438,752.02278 a 85.772074,85.772074 0 0 0 0.38873,-26.93543 232.6189,232.6189 0 0 0 34.00718,-26.74347 119.25749,119.25749 0 0 1 -9.91732,37.83297 207.18362,207.18362 0 0 1 -24.47859,15.84593 z"
id="path3120"
style="fill:none;stroke:#00ff00" />
<path
d="m 240.84019,867.78115 a 71.876795,71.876795 0 0 1 -15.21004,-22.88963 168.39098,168.39098 0 0 0 50.89266,3.05759 80.335265,80.335265 0 0 0 20.63345,23.4764 154.30544,154.30544 0 0 1 -49.09939,-2.03029 196.72968,196.72968 0 0 1 -7.21668,-1.61407 z"
id="path3122"
style="fill:none;stroke:#00ff00" />
<path
d="m 224.02047,753.88817 a 118.11756,118.11756 0 0 0 33.39064,5.54325 164.72099,164.72099 0 0 0 -0.36757,10.377 122.30735,122.30735 0 0 1 -30.98247,-1.21337 98.23203,98.23203 0 0 1 -2.0406,-14.70688 z"
id="path3124"
style="fill:none;stroke:#00ff00" />
<path
d="m 581.2891,728.10608 a 34.26407,34.26407 0 0 1 29.81506,16.25927 88.175365,88.175365 0 0 1 12.89998,39.75227 105.56553,105.56553 0 0 1 -11.28476,55.92633 37.296873,37.296873 0 0 1 -16.22425,16.22424 216.99493,216.99493 0 0 1 -75.76537,22.57231 389.18062,389.18062 0 0 1 -78.68798,0.40113 47.283826,47.283826 0 0 1 -24.9978,-18.12609 123.26692,123.26692 0 0 1 -63.75725,26.29987 76.767852,76.767852 0 0 1 -29.63164,-2.59243 80.335265,80.335265 0 0 1 -16.39729,-6.79646 162.31896,162.31896 0 0 1 -60.80272,-0.7795 204.7432,204.7432 0 0 1 -48.82219,-16.5864 135.92625,135.92625 0 0 0 -81.12913,11.60923 4.00676,4.00676 0 0 1 -5.7421,-3.49872 47.100197,47.100197 0 0 1 33.74161,-46.48812 75.323314,75.323314 0 0 1 -16.95274,-50.45011 53.234199,53.234199 0 0 1 23.22968,-42.03299 82.876006,82.876006 0 0 1 -0.83023,-1.5231 36.212402,36.212402 0 0 1 -2.46585,-28.18481 57.121187,57.121187 0 0 1 27.515,-32.79109 44.431586,44.431586 0 0 1 27.61588,-4.68162 30.817043,30.817043 0 0 1 39.77667,-32.33039 157.62801,157.62801 0 0 1 57.39495,32.08215 399.94469,399.94469 0 0 0 3.51298,-6.97563 601.89734,601.89734 0 0 1 14.79775,-28.20148 71.84369,71.84369 0 0 1 11.98838,-15.82569 63.449349,63.449349 0 0 1 3.83179,-24.13961 81.793724,81.793724 0 0 1 -37.16337,-30.40815 78.725445,78.725445 0 0 1 -13.17884,-42.77522 217.9793,217.9793 0 0 1 18.0854,-89.27573 51.367777,51.367777 0 0 1 27.79302,-27.10727 75.590657,75.590657 0 0 1 32.44045,-67.61214 21.56796,21.56796 0 0 1 29.22504,4.43363 28.201159,28.201159 0 0 1 5.85316,14.40068 24.180247,24.180247 0 0 1 39.32928,8.34011 85.769489,85.769489 0 0 1 1.73021,58.95357 41.229951,41.229951 0 0 1 18.16135,29.10313 296.54442,296.54442 0 0 1 2.23278,49.6552 279.4281,279.4281 0 0 1 -25.87209,110.0002 8860.04,8860.04 0 0 1 -12.91584,27.69811 283.78976,283.78976 0 0 0 -14.4139,37.46509 376.60221,376.60221 0 0 1 75.15967,-45.76261 54.248794,54.248794 0 0 1 23.55518,-4.92616 17.932121,17.932121 0 0 1 16.42701,11.50232 31.600422,31.600422 0 0 1 1.24923,18.60663 38.675535,38.675535 0 0 1 36.42124,-1.99531 51.333101,51.333101 0 0 1 29.44345,50.99757 127.27101,127.27101 0 0 1 -6.19086,29.58379 z"
id="path3126"
style="fill:none;stroke:#00ff00" />
<path
d="m 8.01352,861.4055 0,50.1886 34.304866,12.48595 20.748018,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.6168 6.564258,2.3892 20.748018,-11.97888 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.924741,8.61681 6.564258,2.38919 20.748018,-11.97887 a 4.0067603,4.0067603 0 0 1 4.006761,6.93991 l -14.924741,8.6168 6.564258,2.3892 20.748017,-11.97888 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.61681 6.56426,2.38919 20.74802,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.6168 6.56426,2.3892 20.74801,-11.97888 a 4.0067635,4.0067635 0 0 1 4.00676,6.93992 l -14.92474,8.6168 6.56426,2.38919 20.74802,-11.97887 a 4.0067603,4.0067603 0 0 1 4.00676,6.93991 l -14.92474,8.6168 6.56426,2.3892 20.74801,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.6168 6.56426,2.38919 20.74802,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.61681 6.56426,2.38919 20.74802,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92475,8.6168 6.56426,2.3892 20.74802,-11.97888 a 4.0067635,4.0067635 0 0 1 4.00676,6.93992 l -14.92474,8.6168 6.56426,2.38919 20.74802,-11.97887 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.6168 6.56425,2.3892 20.74802,-11.97888 a 4.0067635,4.0067635 0 0 1 4.00676,6.93992 l -14.92474,8.6168 6.56426,2.38918 20.74802,-11.97886 a 4.00676,4.00676 0 0 1 4.00676,6.93991 l -14.92474,8.61685 6.56426,2.3891 20.74801,-11.97883 a 4.0067678,4.0067678 0 0 1 4.00676,6.93993 l -14.92474,8.6168 6.56426,2.3892 20.74802,-11.9789 a 4.00676,4.00676 0 0 1 4.00676,6.9399 l -14.92474,8.6168 69.97762,25.4698 0,-50.1886 L 8.01352,861.4055 z"
id="path3128"
style="fill:none;stroke:#00ff00" />
<path
d="m 736.08097,861.4055 0,50.1886 -34.30487,12.48595 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56425,2.3892 -20.74802,-11.97888 a 4.0067603,4.0067603 0 0 0 -4.00676,6.93991 l 14.92474,8.61681 -6.56426,2.38919 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56426,2.3892 -20.74801,-11.97888 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.61681 -6.56426,2.38919 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56426,2.3892 -20.74801,-11.97888 a 4.006766,4.006766 0 0 0 -4.00677,6.93992 l 14.92475,8.6168 -6.56426,2.38919 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56426,2.3892 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56425,2.38919 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.61681 -6.56426,2.38919 -20.74802,-11.97887 a 4.0067603,4.0067603 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56426,2.3892 -20.74801,-11.97888 a 4.0067635,4.0067635 0 0 0 -4.00676,6.93992 l 14.92474,8.6168 -6.56426,2.38919 -20.74802,-11.97887 a 4.00676,4.00676 0 0 0 -4.00676,6.93991 l 14.92474,8.6168 -6.56426,2.3892 -20.74802,-11.97888 a 4.006761,4.006761 0 0 0 -4.00675,6.93992 l 14.92474,8.6168 -6.56426,2.38918 -20.74802,-11.97886 a 4.0067603,4.0067603 0 0 0 -4.00676,6.93991 l 14.92474,8.61685 -6.56426,2.3891 -20.74802,-11.97883 a 4.0067678,4.0067678 0 0 0 -4.00676,6.93993 l 14.92474,8.6168 -6.56425,2.3892 -20.74802,-11.9789 a 4.00676,4.00676 0 0 0 -4.00676,6.9399 l 14.92474,8.6168 -69.97763,25.4698 0,-50.1886 360.02697,-131.0391 z"
id="path3130"
style="fill:none;stroke:#00ff00" />
<path
d="m 0,914.39966 a 4.00676,4.00676 0 0 0 2.636367,3.76513 l 36.060572,13.12497 0,27.22772 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31104 8.380775,3.05036 0,27.22771 a 4.0067605,4.0067605 0 0 0 8.013521,0 l 0,-24.31103 8.380775,3.05035 0,27.22772 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31103 8.380776,3.05035 0,27.22772 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31104 8.380774,3.05035 0,27.22772 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31103 8.38078,3.05035 0,27.22772 a 4.0067605,4.0067605 0 0 0 8.01352,0 l 0,-24.31104 8.38077,3.05036 0,27.22771 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31103 8.38078,3.05035 0,27.22769 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31101 8.38077,3.05036 0,27.22775 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31107 8.38078,3.05035 0,27.22772 a 4.0067605,4.0067605 0 0 0 8.01352,0 l 0,-24.31104 8.38078,3.05036 0,27.22768 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.311 8.38077,3.05035 0,27.22775 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.31106 8.38078,3.05036 0,27.2277 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.311 8.38077,3.0503 0,27.2277 a 4.0067605,4.0067605 0 0 0 8.01352,0 l 0,-24.311 8.38078,3.0504 0,27.2277 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.3111 8.38077,3.0504 0,27.2277 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-24.311 78.05196,28.4086 a 4.00676,4.00676 0 0 0 2.74079,0 l 78.05195,-28.4086 0,24.311 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.2277 8.38078,-3.0504 0,24.3111 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.2277 8.38078,-3.0504 0,24.311 a 4.00676,4.00676 0 0 0 8.01351,0 l 0,-27.2277 8.38078,-3.0503 0,24.311 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.2277 8.38078,-3.05036 0,24.31106 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22775 8.38077,-3.05035 0,24.311 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22768 8.38078,-3.05036 0,24.31104 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 8.38077,-3.05035 0,24.31107 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22775 8.38078,-3.05036 0,24.31101 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22769 8.38077,-3.05035 0,24.31103 a 4.006765,4.006765 0 0 0 8.01353,0 l 0,-27.22771 8.38077,-3.05036 0,24.31104 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 8.38078,-3.05035 0,24.31103 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 8.38077,-3.05035 0,24.31104 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 8.38078,-3.05035 0,24.31103 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 8.38077,-3.05035 0,24.31103 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22771 8.38078,-3.05036 0,24.31104 a 4.00676,4.00676 0 0 0 8.01352,0 l 0,-27.22772 36.06057,-13.12497 a 4.00676,4.00676 0 0 0 2.63637,-3.76513 l 0,-58.7164 a 4.00676,4.00676 0 0 0 -2.31343,-3.63136 L 637.06594,803.22244 a 4.0067602,4.0067602 0 0 0 -3.38666,7.26271 l 95.94824,44.7414 L 372.04724,985.37513 14.466964,855.22655 121.47719,805.32686 a 4.0067602,4.0067602 0 1 0 -3.38666,-7.26271 L 2.31343,852.0519 A 4.00676,4.00676 0 0 0 0,855.68326 l 0,58.7164 z"
id="path3132"
style="fill:none;stroke:#00ff00" />
</g>
<g
transform="translate(1605.7072,3616.6359)"
id="g3210">
<path
d="m 382.52092,430.86458 14.57154,11.75125 a 16.671997,16.671997 0 0 0 23.50249,-2.58528 81.762729,81.762729 0 0 0 11.98627,-81.3186 20.173487,20.173487 0 0 0 -33.84358,-5.87562 61.574626,61.574626 0 0 0 -9.65625,15.02408 l 3.75178,-12.2133 a 24.194398,24.194398 0 0 0 -4.86625,-18.69008 17.5612,17.5612 0 0 0 -23.7958,-3.60998 71.583897,71.583897 0 0 0 -27.92096,79.3538 39.698341,39.698341 0 0 0 20.92309,24.4749 16.386746,16.386746 0 0 0 16.9218,-1.69218 l 8.42587,-4.61899 z"
id="path3212"
style="fill:none;stroke:#0000ff" />
<path
d="m 372.53226,563.93357 a 46.498677,46.498677 0 0 0 2.70749,-20.7574"
id="path3214"
style="fill:none;stroke:#0000ff" />
<path
d="m 315.59954,535.59521 a 55.382854,55.382854 0 0 0 -1.1552,14.92126"
id="path3216"
style="fill:none;stroke:#0000ff" />
<path
d="m 333.7265,400.35197 a 47.361017,47.361017 0 0 0 -28.39168,26.01605 213.97254,213.97254 0 0 0 -17.75297,87.63472 74.718685,74.718685 0 0 0 12.5081,40.59816 77.786964,77.786964 0 0 0 38.15864,30.00562 60.862944,60.862944 0 0 0 28.391,3.19634 80.577226,80.577226 0 0 0 23.69051,-6.76872 138.79602,138.79602 0 0 0 32.90348,-21.24625 90.747238,90.747238 0 0 0 31.18781,-64.98437 292.53766,292.53766 0 0 0 -2.20171,-49.00746 37.223191,37.223191 0 0 0 -19.05684,-27.8772"
id="path3218"
style="fill:none;stroke:#0000ff" />
<path
d="M 341.21132,638.22132 A 27.194806,27.194806 0 0 1 329.9731,671.50499"
id="path3220"
style="fill:none;stroke:#0000ff" />
<path
d="m 339.16702,584.93246 a 59.442589,59.442589 0 0 0 -2.62324,41.16208 84.725541,84.725541 0 0 0 11.13454,23.3972 25.894073,25.894073 0 0 1 0,29.14308"
id="path3222"
style="fill:none;stroke:#0000ff" />
<path
d="M 543.44764,871.08733 A 98.012075,98.012075 0 0 0 570.2837,821.42548"
id="path3224"
style="fill:none;stroke:#0000ff" />
<path
d="m 514.2071,838.88789 a 103.83375,103.83375 0 0 1 -17.74383,37.76773"
id="path3226"
style="fill:none;stroke:#0000ff" />
<path
d="m 421.457,780.4836 a 77.877955,77.877955 0 0 0 3.04257,-22.27427"
id="path3228"
style="fill:none;stroke:#0000ff" />
<path
d="m 472.9134,779.94366 a 83.158843,83.158843 0 0 0 12.90414,-31.57337"
id="path3230"
style="fill:none;stroke:#0000ff" />
<path
d="m 539.22236,759.60757 a 81.765314,81.765314 0 0 0 1.84844,-36.48441"
id="path3232"
style="fill:none;stroke:#0000ff" />
<path
d="m 391.12429,774.81454 a 211.19038,211.19038 0 0 0 189.93266,-42.69491 30.25731,30.25731 0 0 1 26.63776,14.35042 84.168605,84.168605 0 0 1 12.3138,37.94589 101.55877,101.55877 0 0 1 -10.85646,53.80364 33.290113,33.290113 0 0 1 -14.48129,14.48129 212.98817,212.98817 0 0 1 -74.36638,22.15551 385.17386,385.17386 0 0 1 -77.47265,0.43588 43.277066,43.277066 0 0 1 -24.83099,-20.18217 221.81493,221.81493 0 0 1 -27.46482,-133.33866 287.79652,287.79652 0 0 1 25.47373,-90.83627 8856.0333,8856.0333 0 0 0 12.91,-27.68558 275.42134,275.42134 0 0 0 25.50174,-108.44606"
id="path3234"
style="fill:none;stroke:#0000ff" />
<path
d="m 392.25445,423.12927 a 8.193585,8.193585 0 0 0 8.10107,-10.70351 18.464783,18.464783 0 0 0 -3.87707,-6.71529 7.14098,7.14098 0 0 0 -10.46107,7.25345"
id="path3236"
style="fill:none;stroke:#0000ff" />
<path
d="m 366.68615,421.58902 a 12.608639,12.608639 0 0 1 -5.46792,-16.24974 7.421314,7.421314 0 0 1 13.9605,1.22139 19.718354,19.718354 0 0 1 0.60517,4.98795"
id="path3238"
style="fill:none;stroke:#0000ff" />
<path
d="M 389.47225,756.31817 A 228.61214,228.61214 0 0 0 583.37899,688.82115"
id="path3240"
style="fill:none;stroke:#0000ff" />
<path
d="m 459.3636,841.71136 a 78.143472,78.143472 0 0 1 -16.53187,33.5809"
id="path3242"
style="fill:none;stroke:#0000ff" />
<path
d="m 392.42787,707.68071 a 198.37005,198.37005 0 0 0 115.80144,-43.99632 27.593662,27.593662 0 0 0 8.39617,-31.33493 13.925361,13.925361 0 0 0 -12.75656,-8.93223 50.242034,50.242034 0 0 0 -21.81541,4.56232 372.59545,372.59545 0 0 0 -84.1007,53.16609"
id="path3244"
style="fill:none;stroke:#0000ff" />
<path
d="m 508.22931,663.68439 13.57702,-9.50673 a 34.668775,34.668775 0 0 1 34.53685,-3.02158 47.326341,47.326341 0 0 1 27.14527,47.017 123.26425,123.26425 0 0 1 -10.72617,40.58526"
id="path3246"
style="fill:none;stroke:#0000ff" />
<path
d="M 406.48872,831.64439 A 227.48682,227.48682 0 0 0 620.27078,789.98146"
id="path3248"
style="fill:none;stroke:#0000ff" />
<path
d="M 449.59137,328.23689 A 21.370963,21.370963 0 0 0 435.10333,312.52655"
id="path3250"
style="fill:none;stroke:#0000ff" />
<path
d="m 377.88058,298.04089 a 27.943115,27.943115 0 0 0 -11.61916,8.61479"
id="path3252"
style="fill:none;stroke:#0000ff" />
<path
d="m 405.51281,864.5415 a 92.996196,92.996196 0 0 1 -31.02418,-45.31207 262.78882,262.78882 0 0 1 -9.70029,-110.87486 130.77537,130.77537 0 0 1 7.05655,-28.84752 111.23706,111.23706 0 0 0 6.30128,-49.91627 51.126706,51.126706 0 0 0 -8.53427,-23.44772 14.560222,14.560222 0 0 0 -18.40765,-4.93232 67.83693,67.83693 0 0 0 -29.60939,27.93811 597.89058,597.89058 0 0 0 -14.69925,28.01374 403.95145,403.95145 0 0 1 -26.97769,46.72672 109.70644,109.70644 0 0 0 -17.9377,49.28344 160.71423,160.71423 0 0 0 15.54459,88.15775 76.328505,76.328505 0 0 0 47.24616,39.64424 72.761092,72.761092 0 0 0 28.08507,2.45713 119.26016,119.26016 0 0 0 65.1447,-28.32178"
id="path3254"
style="fill:none;stroke:#0000ff" />
<path
d="m 316.38638,638.66914 a 27.171792,27.171792 0 0 0 13.28194,8.67007"
id="path3256"
style="fill:none;stroke:#0000ff" />
<path
d="m 301.72732,667.31527 a 52.665839,52.665839 0 0 0 52.15985,22.84307"
id="path3258"
style="fill:none;stroke:#0000ff" />
<path
d="m 280.75734,702.63171 a 69.118811,69.118811 0 0 0 57.84206,25.07701"
id="path3260"
style="fill:none;stroke:#0000ff" />
<path
d="m 262.24527,750.93628 a 86.255075,86.255075 0 0 0 80.51388,26.67467"
id="path3262"
style="fill:none;stroke:#0000ff" />
<path
d="m 265.41082,807.63634 a 70.022143,70.022143 0 0 0 105.72256,-0.1937"
id="path3264"
style="fill:none;stroke:#0000ff" />
<path
d="m 359.87178,856.7544 a 105.23463,105.23463 0 0 1 -70.88249,1.63225"
id="path3266"
style="fill:none;stroke:#0000ff" />
<path
d="m 307.96308,873.8255 a 158.3122,158.3122 0 0 1 -60.70711,-0.50438 200.73644,200.73644 0 0 1 -91.02887,-44.71853 71.316554,71.316554 0 0 1 -24.67254,-56.62182 49.227439,49.227439 0 0 1 24.65824,-40.8605"
id="path3268"
style="fill:none;stroke:#0000ff" />
<path
d="m 261.07655,773.42067 a 126.31411,126.31411 0 0 1 -76.46616,-15.22138 78.869246,78.869246 0 0 1 -31.12248,-31.80322 32.205641,32.205641 0 0 1 -2.19301,-25.06626 53.114427,53.114427 0 0 1 25.58496,-30.49097 40.424826,40.424826 0 0 1 30.8812,-2.93695"
id="path3270"
style="fill:none;stroke:#0000ff" />
<path
d="m 275.88011,710.39411 a 99.548914,99.548914 0 0 1 -43.79174,-14.89339 68.627208,68.627208 0 0 1 -21.47423,-21.47423 26.810283,26.810283 0 0 1 30.59503,-39.9093 153.62125,153.62125 0 0 1 59.7228,34.69979"
id="path3272"
style="fill:none;stroke:#0000ff" />
<path
d="M 278.74109,843.70013 A 164.38422,164.38422 0 0 1 131.88286,781.93476"
id="path3274"
style="fill:none;stroke:#0000ff" />
<path
d="M 261.75187,755.43438 A 114.1108,114.1108 0 0 1 156.58875,689.88039"
id="path3276"
style="fill:none;stroke:#0000ff" />
<path
d="m 198.87079,856.80555 a 139.93301,139.93301 0 0 0 -84.10393,11.85358 43.093437,43.093437 0 0 1 37.33346,-43.91361"
id="path3278"
style="fill:none;stroke:#0000ff" />
<path
d="m 219.36836,839.27942 a 75.883556,75.883556 0 0 0 19.43078,32.12534"
id="path3280"
style="fill:none;stroke:#0000ff" />
<path
d="m 176.21099,821.06404 a 67.384312,67.384312 0 0 0 0.91717,23.32019"
id="path3282"
style="fill:none;stroke:#0000ff" />
<path
d="m 219.82446,748.19616 a 102.23879,102.23879 0 0 0 2.92741,23.87741"
id="path3284"
style="fill:none;stroke:#0000ff" />
<path
d="M 179.26009,722.11589 A 68.190098,68.190098 0 0 0 174.935,751.80737"
id="path3286"
style="fill:none;stroke:#0000ff" />
<path
d="m 372.04724,989.63904 0,58.71636"
id="path3288"
style="fill:none;stroke:#0000ff" />
<path
d="m 310.98422,1005.0767 -22.36609,12.913 0,30.0333"
id="path3290"
style="fill:none;stroke:#0000ff" />
<path
d="m 65.069784,915.57113 -22.366085,12.91307 0,30.03328"
id="path3292"
style="fill:none;stroke:#0000ff" />
<path
d="m 294.58992,999.10963 -22.36608,12.91307 0,30.0333"
id="path3294"
style="fill:none;stroke:#0000ff" />
<path
d="m 278.19563,993.1426 -22.36609,12.9131 0,30.0332"
id="path3296"
style="fill:none;stroke:#0000ff" />
<path
d="m 261.80133,987.17556 -22.36608,12.91304 0,30.0333"
id="path3298"
style="fill:none;stroke:#0000ff" />
<path
d="m 245.40704,981.20852 -22.36609,12.91307 0,30.03331"
id="path3300"
style="fill:none;stroke:#0000ff" />
<path
d="m 229.01274,975.24149 -22.36608,12.91306 0,30.03325"
id="path3302"
style="fill:none;stroke:#0000ff" />
<path
d="m 212.61845,969.27445 -22.36609,12.91307 0,30.03328"
id="path3304"
style="fill:none;stroke:#0000ff" />
<path
d="m 196.22415,963.30742 -22.36609,12.91306 0,30.03332"
id="path3306"
style="fill:none;stroke:#0000ff" />
<path
d="m 179.82985,957.34038 -22.36608,12.91307 0,30.03325"
id="path3308"
style="fill:none;stroke:#0000ff" />
<path
d="m 163.43556,951.37335 -22.36609,12.91306 0,30.03328"
id="path3310"
style="fill:none;stroke:#0000ff" />
<path
d="m 147.04126,945.40631 -22.36608,12.91307 0,30.03328"
id="path3312"
style="fill:none;stroke:#0000ff" />
<path
d="m 130.64697,939.43927 -22.36609,12.91307 0,30.03328"
id="path3314"
style="fill:none;stroke:#0000ff" />
<path
d="m 114.25267,933.47224 -22.366084,12.91306 0,30.03329"
id="path3316"
style="fill:none;stroke:#0000ff" />
<path
d="m 97.858375,927.5052 -22.366085,12.91307 0,30.03328"
id="path3318"
style="fill:none;stroke:#0000ff" />
<path
d="m 81.46408,921.53817 -22.366085,12.91306 0,30.03328"
id="path3320"
style="fill:none;stroke:#0000ff" />
<path
d="m 433.11027,1005.0767 22.36608,12.913 0,30.0333"
id="path3322"
style="fill:none;stroke:#0000ff" />
<path
d="m 465.89886,993.1426 22.36608,12.9131 0,30.0332"
id="path3324"
style="fill:none;stroke:#0000ff" />
<path
d="m 449.50456,999.10963 22.36609,12.91307 0,30.0333"
id="path3326"
style="fill:none;stroke:#0000ff" />
<path
d="m 515.08175,975.24149 22.36608,12.91306 0,30.03325"
id="path3328"
style="fill:none;stroke:#0000ff" />
<path
d="m 498.68745,981.20852 22.36609,12.91307 0,30.03331"
id="path3330"
style="fill:none;stroke:#0000ff" />
<path
d="m 482.29316,987.17556 22.36608,12.91304 0,30.0333"
id="path3332"
style="fill:none;stroke:#0000ff" />
<path
d="m 547.87034,963.30742 22.36608,12.91306 0,30.03332"
id="path3334"
style="fill:none;stroke:#0000ff" />
<path
d="m 531.47604,969.27445 22.36609,12.91307 0,30.03328"
id="path3336"
style="fill:none;stroke:#0000ff" />
<path
d="m 597.05322,945.40631 22.36609,12.91307 0,30.03328"
id="path3338"
style="fill:none;stroke:#0000ff" />
<path
d="m 564.26463,957.34038 22.36609,12.91307 0,30.03325"
id="path3340"
style="fill:none;stroke:#0000ff" />
<path
d="m 580.65893,951.37335 22.36609,12.91306 0,30.03328"
id="path3342"
style="fill:none;stroke:#0000ff" />
<path
d="m 679.0247,915.57113 22.36609,12.91307 0,30.03328"
id="path3344"
style="fill:none;stroke:#0000ff" />
<path
d="m 613.44752,939.43927 22.36609,12.91307 0,30.03328"
id="path3346"
style="fill:none;stroke:#0000ff" />
<path
d="m 629.84182,933.47224 22.36608,12.91306 0,30.03329"
id="path3348"
style="fill:none;stroke:#0000ff" />
<path
d="m 646.23611,927.5052 22.36609,12.91307 0,30.03328"
id="path3350"
style="fill:none;stroke:#0000ff" />
<path
d="m 662.63041,921.53817 22.36608,12.91306 0,30.03328"
id="path3352"
style="fill:none;stroke:#0000ff" />
<path
d="m 740.08773,855.68326 0,58.7164 L 372.04724,1048.3554 4.00676,914.39966 l 0,-58.7164"
id="path3354"
style="fill:none;stroke:#0000ff" />
<path
d="M 119.78386,801.69551 4.00676,855.68326 372.04724,989.63904 740.08773,855.68326 635.37261,806.85379"
id="path3356"
style="fill:none;stroke:#0000ff" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="765.09967"
height="158.82559"
id="svg2">
<defs
id="defs4">
<symbol
id="*Paper_Space" />
<symbol
id="*Model_Space" />
<pattern
height="8"
id="Hatch"
patternUnits="userSpaceOnUse"
width="8"
x="0"
y="0">
<path
d="M8 4 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3030" />
<path
d="M6 2 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3032" />
<path
d="M4 0 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3034" />
</pattern>
<marker
refX="0"
refY="0"
orient="auto"
id="DistanceX"
style="overflow:visible">
<path
d="M 3,-3 -3,3 M 0,-5 0,5"
id="path3027"
style="stroke:#000000;stroke-width:0.5" />
</marker>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-463.61971,-103.98436)"
id="layer1">
<g
transform="translate(474.11971,-800.05225)"
id="g3038" />
<path
d="m 474.11971,216.99105 8.38645,-95.79752 25.49501,0 15.95818,65.41468 15.86248,-65.41468 25.39886,0 8.91346,95.79752 -18.06677,0 -6.32579,-64.02471 -15.43095,64.02471 -20.41521,0 -16.10201,-64.02471 -5.60688,64.02471 -18.06683,0 0,0 z"
id="path3042"
style="fill:none;stroke:#bebebe" />
<path
d="m 585.06082,216.99105 0,-69.48774 18.35416,0 0,69.48774 -18.35416,0 0,0 z"
id="path3044"
style="fill:none;stroke:#bebebe" />
<path
d="m 584.4376,137.15201 0,-11.54959 a 3.667629,3.667629 0 0 1 0.77873,-2.55179 3.012482,3.012482 0 0 1 2.33617,-0.85049 l 13.75388,0 a 2.665344,2.665344 0 0 1 2.15675,0.85049 3.874957,3.874957 0 0 1 0.71861,2.55179 l 0,11.54959 a 3.170925,3.170925 0 0 1 -0.71861,2.2641 2.844672,2.844672 0 0 1 -2.15675,0.7548 l -13.75388,0 a 3.183373,3.183373 0 0 1 -2.27606,-0.79069 2.91442,2.91442 0 0 1 -0.83884,-2.22821 l 0,0 z"
id="path3046"
style="fill:none;stroke:#bebebe" />
<path
d="m 614.10181,182.15117 a 104.76828,104.76828 0 0 1 0.4073,-9.62042 61.45992,61.45992 0 0 1 1.22222,-7.96728 34.257292,34.257292 0 0 1 2.02456,-6.2896 18.589823,18.589823 0 0 1 2.81556,-4.58861 18.372489,18.372489 0 0 1 7.1404,-5.29557 25.178476,25.178476 0 0 1 9.29684,-1.55745 139.56012,139.56012 0 0 1 17.5877,1.01826 80.33883,80.33883 0 0 1 14.32895,3.05509 l 0,10.97421 a 913.84864,913.84864 0 0 0 -25.74636,0.0659 25.765381,25.765381 0 0 0 -2.98332,0.19783 10.614363,10.614363 0 0 0 -3.33051,1.29399 5.904958,5.904958 0 0 0 -2.63582,3.23482 31.868466,31.868466 0 0 0 -1.36576,6.43958 73.360882,73.360882 0 0 0 -0.45546,8.67975 97.248263,97.248263 0 0 0 0.31162,8.4166 30.406975,30.406975 0 0 0 0.93453,5.64883 13.352632,13.352632 0 0 0 1.53966,3.54027 6.228032,6.228032 0 0 0 2.12638,2.09068 9.932543,9.932543 0 0 0 3.12103,1.0243 26.061579,26.061579 0 0 0 4.52268,0.3415 252.7863,252.7863 0 0 0 21.37366,-0.9105 l 3.49828,-0.2876 0,11.5494 a 31.724353,31.724353 0 0 1 -11.74129,3.6421 158.5758,158.5758 0 0 1 -14.80802,0.8147 l -0.76677,0 a 36.794709,36.794709 0 0 1 -14.74822,-1.7372 18.781067,18.781067 0 0 1 -7.00851,-5.2116 19.357438,19.357438 0 0 1 -2.91432,-4.6785 33.943497,33.943497 0 0 1 -2.0816,-6.31978 60.236572,60.236572 0 0 1 -1.24921,-7.96117 102.18754,102.18754 0 0 1 -0.4162,-9.60257 l 0,0 z"
id="path3048"
style="fill:none;stroke:#bebebe" />
<path
d="m 679.80386,216.99105 0,-69.48774 15.43095,0 2.87536,8.76962 a 37.96926,37.96926 0 0 1 9.88418,-7.0806 23.135088,23.135088 0 0 1 10.0038,-2.36009 49.347494,49.347494 0 0 1 4.75639,0.19169 12.434249,12.434249 0 0 1 2.95909,0.57507 l 0,17.68339 a 99.917807,99.917807 0 0 0 -9.91977,-0.38338 37.215466,37.215466 0 0 0 -5.73876,0.4073 21.894431,21.894431 0 0 0 -4.66069,1.22222 14.160958,14.160958 0 0 0 -3.88165,2.33617 19.705025,19.705025 0 0 0 -3.40259,3.74978 l 0,44.37657 -18.30631,0 0,0 z"
id="path3050"
style="fill:none;stroke:#bebebe" />
<path
d="m 754.27554,165.28239 a 101.69692,101.69692 0 0 0 -2.0126,9.66857 52.999906,52.999906 0 0 0 -0.67107,7.91912 69.045724,69.045724 0 0 0 0.67107,10.97428 16.561755,16.561755 0 0 0 0.94036,3.45043 8.854315,8.854315 0 0 0 1.47954,2.49198 7.551397,7.551397 0 0 0 3.97766,2.53988 27.363959,27.363959 0 0 0 6.03841,0.5272 45.079768,45.079768 0 0 0 5.70257,-0.2636 9.767782,9.767782 0 0 0 3.66696,-1.3179 5.86791,5.86791 0 0 0 2.53952,-3.2587 27.050263,27.050263 0 0 0 1.25749,-5.53508 55.730735,55.730735 0 0 0 0.42019,-7.21251 158.11284,158.11284 0 0 0 -0.31284,-11.78882 30.217313,30.217313 0 0 0 -1.10107,-6.30187 5.911226,5.911226 0 0 0 -2.51499,-3.57004 10.986507,10.986507 0 0 0 -3.58967,-1.47372 21.310199,21.310199 0 0 0 -4.82232,-0.49134 57.038011,57.038011 0 0 0 -4.65456,0.16194 17.096194,17.096194 0 0 0 -3.08484,0.4852 7.14005,7.14005 0 0 0 -3.92981,2.99498 l 0,0 z"
id="path3052"
style="fill:none;stroke:#bebebe" />
<path
d="m 733.28556,183.589 a 92.623124,92.623124 0 0 1 1.03022,-15.09572 34.923348,34.923348 0 0 1 3.25874,-10.35129 16.997543,16.997543 0 0 1 6.15803,-6.70918 27.334986,27.334986 0 0 1 8.92573,-3.45043 58.555226,58.555226 0 0 1 12.30409,-1.15014 64.576878,64.576878 0 0 1 8.27122,0.49134 39.74236,39.74236 0 0 1 6.88921,1.47341 24.998971,24.998971 0 0 1 5.51149,2.4561 17.713605,17.713605 0 0 1 4.12825,3.43847 20.147183,20.147183 0 0 1 3.00878,4.6935 33.054914,33.054914 0 0 1 2.15,6.2209 56.120992,56.120992 0 0 1 1.28816,7.7486 92.689443,92.689443 0 0 1 0.42939,9.27599 93.582889,93.582889 0 0 1 -0.42325,9.252 55.494869,55.494869 0 0 1 -1.2667,7.67662 31.745279,31.745279 0 0 1 -2.11013,6.10108 18.697304,18.697304 0 0 1 -2.95663,4.5258 17.025604,17.025604 0 0 1 -4.09145,3.2707 25.393667,25.393667 0 0 1 -5.51762,2.3362 41.865621,41.865621 0 0 1 -6.94227,1.4018 69.328567,69.328567 0 0 1 -8.36845,0.4672 63.054282,63.054282 0 0 1 -8.23963,-0.5002 39.37126,39.37126 0 0 1 -6.89197,-1.5006 25.293848,25.293848 0 0 1 -5.544,-2.5009 18.401937,18.401937 0 0 1 -4.19634,-3.5014 20.408256,20.408256 0 0 1 -2.97719,-4.5227 30.962036,30.962036 0 0 1 -2.12639,-5.85256 49.71676,49.71676 0 0 1 -1.2762,-7.18239 79.250711,79.250711 0 0 1 -0.42509,-8.5122 l 0,0 z"
id="path3054"
style="fill:none;stroke:#bebebe" />
<path
d="m 848.06104,137.39155 -21.46935,0 0,28.03468 21.37427,0 a 9.641122,9.641122 0 0 0 5.07904,-1.19799 6.289092,6.289092 0 0 0 1.92917,-1.80311 10.492988,10.492988 0 0 0 1.37711,-2.82139 28.324879,28.324879 0 0 0 1.10107,-8.69815 26.4065,26.4065 0 0 0 -0.58581,-5.91236 12.140086,12.140086 0 0 0 -1.76048,-4.22332 7.47549,7.47549 0 0 0 -2.93517,-2.5337 9.405207,9.405207 0 0 0 -4.10985,-0.84466 l 0,0 z"
id="path3070"
style="fill:none;stroke:#ff0000" />
<path
d="m 957.94734,161.35288 0,-10.20776 11.26221,-3.78566 3.01798,-19.36075 15.28924,0 0,19.36075 15.57453,0 0,13.99342 -15.57453,0 0,27.89084 a 42.025479,42.025479 0 0 0 0.35885,5.97244 12.328486,12.328486 0 0 0 1.07653,3.82783 8.288976,8.288976 0 0 0 4.45643,3.95366 211.85149,211.85149 0 0 0 6.12183,2.0487 14.600045,14.600045 0 0 0 2.64989,0.6828 l 0,11.2619 -15.95782,0 a 16.804947,16.804947 0 0 1 -7.44373,-1.5545 13.606965,13.606965 0 0 1 -5.31827,-4.6635 22.537606,22.537606 0 0 1 -3.18973,-7.7724 49.35507,49.35507 0 0 1 -1.0612,-10.88151 l 0,-30.76626 -11.26221,0 0,0 z"
id="path3072"
style="fill:none;stroke:#ff0000" />
<path
d="m 1197.4165,146.30501 a 24.952696,24.952696 0 0 1 9.1,1.52157 16.077531,16.077531 0 0 1 6.4991,4.56469 19.935463,19.935463 0 0 1 3.8982,7.60782 39.066225,39.066225 0 0 1 1.3004,10.65064 l 0,46.34132 -18.3042,0 0,-46.58086 a 15.801149,15.801149 0 0 0 -0.4845,-4.1304 7.859179,7.859179 0 0 0 -1.4446,-2.95019 5.977282,5.977282 0 0 0 -2.4138,-1.77 8.891394,8.891394 0 0 0 -3.3738,-0.5901 25.71484,25.71484 0 0 0 -8.9373,1.36576 29.528311,29.528311 0 0 0 -7.8364,4.67234 l 0,49.98345 -18.3072,0 0,-69.48774 14.6667,0 3.6405,7.42778 a 71.772372,71.772372 0 0 1 8.5663,-5.43911 24.453688,24.453688 0 0 1 6.6248,-2.5159 31.484828,31.484828 0 0 1 6.8058,-0.67107 l 0,0 z"
id="path3074"
style="fill:none;stroke:#ff0000" />
<path
d="m 882.47028,147.50331 19.21508,0 12.07804,48.68928 a 6.616536,6.616536 0 0 0 2.23895,3.70202 6.560409,6.560409 0 0 0 4.13438,1.23404 2.645525,2.645525 0 0 0 0.52754,0.1437 l 13.89681,-53.76904 19.11999,0 -24.10395,91.48424 -9.53546,13.3224 -13.13312,0 9.82377,-35.3189 a 22.713351,22.713351 0 0 1 -7.27505,-1.1052 17.518915,17.518915 0 0 1 -5.86726,-3.3157 20.440644,20.440644 0 0 1 -4.4595,-5.5261 32.678904,32.678904 0 0 1 -3.05171,-7.73647 l -13.60851,-51.80427 0,0 z"
id="path3076"
style="fill:none;stroke:#ff0000" />
<path
d="m 1011.86,216.99105 0,-102.50669 18.163,0 0,40.44673 a 72.12737,72.12737 0 0 1 8.5172,-5.39126 25.732974,25.732974 0 0 1 6.6739,-2.56375 33.530661,33.530661 0 0 1 6.95,-0.67107 24.944515,24.944515 0 0 1 9.0968,1.52157 16.082612,16.082612 0 0 1 6.5022,4.56469 19.935463,19.935463 0 0 1 3.8982,7.60782 39.066225,39.066225 0 0 1 1.3004,10.65064 l 0,46.34132 -18.3072,0 0,-46.58086 a 15.799795,15.799795 0 0 0 -0.4815,-4.1304 7.862409,7.862409 0 0 0 -1.4477,-2.95019 5.972344,5.972344 0 0 0 -2.4107,-1.77 8.899237,8.899237 0 0 0 -3.3768,-0.5901 25.71484,25.71484 0 0 0 -8.9374,1.36576 29.519786,29.519786 0 0 0 -7.8332,4.67234 l 0,49.98345 -18.3072,0 0,0 z"
id="path3078"
style="fill:none;stroke:#ff0000" />
<path
d="m 1082.7855,183.589 a 92.623252,92.623252 0 0 1 1.0305,-15.09572 34.921866,34.921866 0 0 1 3.2572,-10.35129 16.998317,16.998317 0 0 1 6.1587,-6.70918 27.333351,27.333351 0 0 1 8.9251,-3.45043 58.559567,58.559567 0 0 1 12.305,-1.15014 64.58165,64.58165 0 0 1 8.2718,0.49134 39.738976,39.738976 0 0 1 6.8886,1.47341 24.998971,24.998971 0 0 1 5.5115,2.4561 17.713605,17.713605 0 0 1 4.1283,3.43847 20.147183,20.147183 0 0 1 3.0088,4.6935 33.054914,33.054914 0 0 1 2.15,6.2209 56.120992,56.120992 0 0 1 1.2881,7.7486 92.689443,92.689443 0 0 1 0.4294,9.27599 93.581477,93.581477 0 0 1 -0.4202,9.252 55.498435,55.498435 0 0 1 -1.2697,7.67662 31.745279,31.745279 0 0 1 -2.1102,6.10108 18.697304,18.697304 0 0 1 -2.9566,4.5258 17.025604,17.025604 0 0 1 -4.0914,3.2707 25.393667,25.393667 0 0 1 -5.5177,2.3362 41.856735,41.856735 0 0 1 -6.9407,1.4018 69.341232,69.341232 0 0 1 -8.37,0.4672 63.04259,63.04259 0 0 1 -8.2381,-0.5002 39.369587,39.369587 0 0 1 -6.8917,-1.5006 25.298499,25.298499 0 0 1 -5.5452,-2.5009 18.400351,18.400351 0 0 1 -4.1957,-3.5014 20.410163,20.410163 0 0 1 -2.9781,-4.5227 30.960474,30.960474 0 0 1 -2.1255,-5.85256 49.716395,49.716395 0 0 1 -1.2759,-7.18239 79.251281,79.251281 0 0 1 -0.4263,-8.5122 l 0,0 z"
id="path3080"
style="fill:none;stroke:#ff0000" />
<path
d="m 1103.7764,165.28239 a 101.69564,101.69564 0 0 0 -2.012,9.66857 53.000252,53.000252 0 0 0 -0.6717,7.91912 69.045959,69.045959 0 0 0 0.6717,10.97428 16.559516,16.559516 0 0 0 0.9385,3.45043 8.857186,8.857186 0 0 0 1.4814,2.49198 7.547675,7.547675 0 0 0 3.9749,2.53988 27.366717,27.366717 0 0 0 6.039,0.5272 45.096704,45.096704 0 0 0 5.7048,-0.2636 9.763441,9.763441 0 0 0 3.6651,-1.3179 5.86791,5.86791 0 0 0 2.5395,-3.2587 27.050263,27.050263 0 0 0 1.2575,-5.53508 55.730735,55.730735 0 0 0 0.4202,-7.21251 158.11284,158.11284 0 0 0 -0.3129,-11.78882 30.217313,30.217313 0 0 0 -1.101,-6.30187 5.911226,5.911226 0 0 0 -2.515,-3.57004 10.983294,10.983294 0 0 0 -3.5885,-1.47372 21.319589,21.319589 0 0 0 -4.8244,-0.49134 57.015487,57.015487 0 0 0 -4.6528,0.16194 17.099511,17.099511 0 0 0 -3.0854,0.4852 7.138992,7.138992 0 0 0 -3.9289,2.99498 l 0,0 z"
id="path3082"
style="fill:none;stroke:#ff0000" />
<path
d="m 808.23539,216.99105 0,-95.79752 41.2641,0 a 34.14365,34.14365 0 0 1 12.2774,1.98899 19.541659,19.541659 0 0 1 8.37612,5.96633 23.907413,23.907413 0 0 1 4.41962,8.9975 48.211674,48.211674 0 0 1 1.47525,12.61539 51.335387,51.335387 0 0 1 -1.77276,14.40103 37.898378,37.898378 0 0 1 -1.96598,5.31336 19.829803,19.829803 0 0 1 -2.34936,3.91172 16.201726,16.201726 0 0 1 -6.46841,4.88796 26.614618,26.614618 0 0 1 -11.40636,2.39628 143.35618,143.35618 0 0 1 -14.75865,-1.19799 519.68963,519.68963 0 0 1 -7.78724,-0.95876 24.527385,24.527385 0 0 1 -2.94743,-0.47907 l 0,37.95478 -18.3563,0 0,0 z"
id="path3084"
style="fill:none;stroke:#ff0000" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

89
main.c
View File

@ -30,6 +30,7 @@
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "genhdr/mpversion.h"
#include "py/nlr.h"
#include "py/compile.h"
#include "py/frozenmod.h"
@ -99,19 +100,27 @@ void reset_mp(void) {
}
#define STRING_LIST(...) {__VA_ARGS__, ""}
bool maybe_run_list(const char ** filenames, pyexec_result_t* exec_result) {
// Look for the first file that exists in the list of filenames, using mp_import_stat().
// Return its index. If no file found, return -1.
const char* first_existing_file_in_list(const char ** filenames) {
for (int i = 0; filenames[i] != (char*)""; i++) {
mp_import_stat_t stat = mp_import_stat(filenames[i]);
if (stat != MP_IMPORT_STAT_FILE) {
continue;
if (stat == MP_IMPORT_STAT_FILE) {
return filenames[i];
}
serial_write(filenames[i]);
serial_write(MSG_OUTPUT_SUFFIX);
pyexec_file(filenames[i], exec_result);
return true;
}
return false;
return NULL;
}
bool maybe_run_list(const char ** filenames, pyexec_result_t* exec_result) {
const char* filename = first_existing_file_in_list(filenames);
if (filename == NULL) {
return false;
}
mp_hal_stdout_tx_str(filename);
mp_hal_stdout_tx_str(MSG_OUTPUT_SUFFIX);
pyexec_file(filename, exec_result);
return true;
}
bool start_mp(safe_mode_t safe_mode) {
@ -261,27 +270,67 @@ int __attribute__((used)) main(void) {
// If not in safe mode, run boot before initing USB and capture output in a
// file.
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
static const char *boot_py_filenames[] = STRING_LIST("settings.txt", "settings.py", "boot.py", "boot.txt");
new_status_color(BOOT_RUNNING);
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// Since USB isn't up yet we can cheat and let ourselves write the boot
// output file.
filesystem_writable_by_python(true);
FIL file_pointer;
boot_output_file = &file_pointer;
f_open(&((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs,
boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
filesystem_writable_by_python(false);
// Get the base filesystem.
FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
bool have_boot_py = first_existing_file_in_list(boot_py_filenames) != NULL;
bool skip_boot_output = false;
// If there's no boot.py file that might write some changing output,
// read the existing copy of CIRCUITPY_BOOT_OUTPUT_FILE and see if its contents
// match the version info we would print anyway. If so, skip writing CIRCUITPY_BOOT_OUTPUT_FILE.
// This saves wear and tear on the flash and also prevents filesystem damage if power is lost
// during the write, which may happen due to bobbling the power connector or weak power.
if (!have_boot_py && f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
char file_contents[512];
UINT chars_read = 0;
f_read(boot_output_file, file_contents, 512, &chars_read);
f_close(boot_output_file);
skip_boot_output =
// + 2 accounts for \r\n.
chars_read == strlen(MICROPY_FULL_VERSION_INFO) + 2 &&
strncmp(file_contents, MICROPY_FULL_VERSION_INFO, strlen(MICROPY_FULL_VERSION_INFO)) == 0;
}
if (!skip_boot_output) {
// Wait 1.5 seconds before opening CIRCUITPY_BOOT_OUTPUT_FILE for write,
// in case power is momentary or will fail shortly due to, say a low, battery.
mp_hal_delay_ms(1500);
// USB isn't up, so we can write the file.
filesystem_writable_by_python(true);
f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
// Switch the filesystem back to non-writable by Python now instead of later,
// since boot.py might change it back to writable.
filesystem_writable_by_python(false);
// Write version info to boot_out.txt.
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
mp_hal_stdout_tx_str("\r\n");
}
#endif
// TODO(tannewt): Re-add support for flashing boot error output.
static const char *filenames[] = STRING_LIST("settings.txt", "settings.py", "boot.py", "boot.txt");
bool found_boot = maybe_run_list(filenames, NULL);
bool found_boot = maybe_run_list(boot_py_filenames, NULL);
(void) found_boot;
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
f_close(boot_output_file);
filesystem_flush();
boot_output_file = NULL;
if (!skip_boot_output) {
f_close(boot_output_file);
filesystem_flush();
boot_output_file = NULL;
}
#endif
// Reset to remove any state that boot.py setup. It should only be used to

View File

@ -1,3 +1,7 @@
# Set default python interpreters
PYTHON2 ?= $(which python2 || which python2.7)
PYTHON3 ?= python3
# Select the board to build for: if not given on the command line,
# then default to PYBV10.
BOARD ?= metro_m0_express
@ -225,6 +229,7 @@ SRC_C = \
audio_dma.c \
background.c \
clocks.c \
$(CHIP_FAMILY)_clocks.c \
events.c \
fatfs_port.c \
flash_api.c \
@ -238,6 +243,8 @@ SRC_C = \
timers.c \
usb.c \
usb_mass_storage.c \
bindings/samd/__init__.c \
bindings/samd/Clock.c \
boards/$(BOARD)/board.c \
boards/$(BOARD)/pins.c \
lib/oofatfs/ff.c \
@ -299,13 +306,13 @@ SRC_COMMON_HAL = \
usb_hid/Device.c \
audioio/__init__.c \
audioio/AudioOut.c \
# audiobusio/PDMIn.c \
touchio/__init__.c \
# touchio/__init__.c \
touchio/TouchIn.c \
ifeq ($(INTERNAL_LIBM),1)
SRC_LIBM = $(addprefix lib/,\
libm/math.c \
libm/roundf.c \
libm/fmodf.c \
libm/nearbyintf.c \
libm/ef_sqrt.c \
@ -363,16 +370,14 @@ SRC_SHARED_MODULE = \
uheap/__init__.c \
ustack/__init__.c
ifeq ($(CHIP_FAMILY),samd21)
SRC_COMMON_HAL += \
audiobusio/__init__.c \
audiobusio/I2SOut.c
endif
# The smallest SAMD51 packages don't have I2S. Everything else does.
ifneq ($(CHIP_VARIANT),SAMD51G18A)
ifneq ($(CHIP_VARIANT),SAMD51G19A)
SRC_COMMON_HAL += \
audiobusio/__init__.c \
audiobusio/I2SOut.c
audiobusio/I2SOut.c \
audiobusio/PDMIn.c
SRC_C += i2s.c
endif
endif
@ -394,7 +399,7 @@ all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
$(BUILD)/firmware.elf: $(OBJ)
$(STEPECHO) "LINK $@"
$(Q)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
$(Q)$(SIZE) $@ | python3 $(TOP)/tools/build_memory_info.py $(LD_FILE)
$(Q)$(SIZE) $@ | $(PYTHON3) $(TOP)/tools/build_memory_info.py $(LD_FILE)
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(ECHO) "Create $@"
@ -402,7 +407,7 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(ECHO) "Create $@"
python2 $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^
$(PYTHON2) $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^
$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate
@ -410,7 +415,7 @@ $(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: auto
autogen_usb_descriptor.intermediate: tools/gen_usb_descriptor.py Makefile
install -d $(BUILD)/genhdr
python3 tools/gen_usb_descriptor.py \
$(PYTHON3) tools/gen_usb_descriptor.py \
--manufacturer $(USB_MANUFACTURER)\
--product $(USB_PRODUCT)\
--vid $(USB_VID)\

View File

@ -231,3 +231,9 @@ Mass storage
All boards will also show up as a mass storage device. Make sure to eject it
before resetting or disconnecting the board.
Port Specific modules
---------------------
.. toctree::
bindings/samd/__init__

View File

@ -109,7 +109,7 @@
// <i> Indicates whether configuration for OSC32K is enabled or not
// <id> enable_osc32k
#ifndef CONF_OSC32K_CONFIG
#define CONF_OSC32K_CONFIG 0
#define CONF_OSC32K_CONFIG 1
#endif
// <h> 32kHz Internal Oscillator (OSC32K) Control
@ -117,7 +117,7 @@
// <i> Indicates whether Internal 32K Oscillator is enabled or not
// <id> osc32k_arch_enable
#ifndef CONF_OSC32K_ENABLE
#define CONF_OSC32K_ENABLE 0
#define CONF_OSC32K_ENABLE 1
#endif
// <q> On Demand Control
@ -142,7 +142,7 @@
// <i> Enable 32 Khz Output
// <id> osc32k_arch_en32k
#ifndef CONF_OSC32K_EN32K
#define CONF_OSC32K_EN32K 0
#define CONF_OSC32K_EN32K 1
#endif
// <q> Enable 1K

View File

@ -17,7 +17,7 @@
// <i> This defines the clock source for RTC
// <id> rtc_source_oscillator
#ifndef CONF_RTCCTRL_SRC
#define CONF_RTCCTRL_SRC GCLK_GENCTRL_SRC_XOSC32K
#define CONF_RTCCTRL_SRC GCLK_GENCTRL_SRC_OSCULP32K
#endif
// <q> Use 1 kHz output

View File

@ -267,7 +267,6 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
turn_on_event_system();
dma->event_channel = find_sync_event_channel();
init_event_channel_interrupt(dma->event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
find_sync_event_channel();
// We keep the audio_dma_t for internal use and the sample as a root pointer because it
// contains the audiodma structure.
@ -275,11 +274,16 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
MP_STATE_PORT(playing_audio)[dma->dma_channel] = dma->sample;
}
dma->beat_size = 1;
dma->bytes_per_sample = 1;
if (audiosample_bits_per_sample(sample) == 16) {
dma->beat_size = 2;
dma->bytes_per_sample = 2;
} else {
dma->beat_size = 1;
dma->bytes_per_sample = 1;
if (single_channel) {
output_register_address += 1;
}
}
// Transfer both channels at once.
if (!single_channel && audiosample_channel_count(sample) == 2) {
@ -319,6 +323,23 @@ void audio_dma_stop(audio_dma_t* dma) {
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}
void audio_dma_pause(audio_dma_t* dma) {
dma_suspend_channel(dma->dma_channel);
}
void audio_dma_resume(audio_dma_t* dma) {
dma_resume_channel(dma->dma_channel);
}
bool audio_dma_get_paused(audio_dma_t* dma) {
if (dma->dma_channel >= AUDIO_DMA_CHANNEL_COUNT) {
return false;
}
uint32_t status = dma_transfer_status(dma->dma_channel);
return (status & DMAC_CHINTFLAG_SUSP) != 0;
}
void audio_dma_init(audio_dma_t* dma) {
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}
@ -337,11 +358,11 @@ bool audio_dma_get_playing(audio_dma_t* dma) {
return false;
}
uint32_t status = dma_transfer_status(dma->dma_channel);
if ((status & DMAC_CHINTFLAG_TCMPL) != 0) {
if ((status & DMAC_CHINTFLAG_TCMPL) != 0 || (status & DMAC_CHINTFLAG_TERR) != 0) {
audio_dma_stop(dma);
}
return status == 0;
return (status & DMAC_CHINTFLAG_TERR) == 0;
}
// WARN(tannewt): DO NOT print from here. Printing calls background tasks such as this and causes a

View File

@ -64,6 +64,8 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj);
void audio_dma_init(audio_dma_t* dma);
void audio_dma_reset(void);
uint8_t find_free_audio_dma_channel(void);
// This sets everything up but doesn't start the timer.
// Sample is the python object for the sample to play.
// loop is true if we should loop the sample.
@ -83,6 +85,9 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
uint8_t dma_trigger_source);
void audio_dma_stop(audio_dma_t* dma);
bool audio_dma_get_playing(audio_dma_t* dma);
void audio_dma_pause(audio_dma_t* dma);
void audio_dma_resume(audio_dma_t* dma);
bool audio_dma_get_paused(audio_dma_t* dma);
void audio_dma_background(void);

View File

@ -0,0 +1,174 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "clocks.h"
#include "bindings/samd/Clock.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
//| .. currentmodule:: samd
//|
//| :class:`Clock` --- Clock reference
//| ------------------------------------------
//|
//| Identifies a clock on the microcontroller.
//|
//| .. class:: Clock
//|
//| Identifies a clock on the microcontroller. They are fixed by the
//| hardware so they cannot be constructed on demand. Instead, use
//| `samd.clock` to reference the desired clock.
//|
STATIC void samd_clock_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "%q.%q.%s(", MP_QSTR_samd, MP_QSTR_clock, self->name);
if (clock_get_enabled(self->type, self->index)) {
mp_printf(print, "frequency=%u", clock_get_frequency(self->type, self->index));
uint32_t calibration = clock_get_calibration(self->type, self->index);
if (calibration) {
mp_printf(print, ", calibration=%u", calibration);
}
}
mp_printf(print, ")");
}
//| .. attribute:: enabled
//|
//| Is the clock enabled? (read-only)
//|
STATIC mp_obj_t samd_clock_get_enabled(mp_obj_t self_in) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(clock_get_enabled(self->type, self->index));
}
MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_enabled_obj, samd_clock_get_enabled);
const mp_obj_property_t samd_clock_enabled_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&samd_clock_get_enabled_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj,
},
};
//| .. attribute:: parent
//|
//| Clock parent. (read-only)
//|
STATIC mp_obj_t samd_clock_get_parent(mp_obj_t self_in) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint8_t p_type, p_index;
if (!clock_get_parent(self->type, self->index, &p_type, &p_index))
return mp_const_none;
const mp_map_t* samd_map = &samd_clock_globals.map;
for (uint8_t i = 0; i < samd_map->alloc; i++) {
samd_clock_obj_t *iter = samd_map->table[i].value;
if (iter->type == p_type && iter->index == p_index)
return iter;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_parent_obj, samd_clock_get_parent);
const mp_obj_property_t samd_clock_parent_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&samd_clock_get_parent_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj,
},
};
//| .. attribute:: frequency
//|
//| Clock frequency. (read-only)
//|
STATIC mp_obj_t samd_clock_get_frequency(mp_obj_t self_in) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int_from_uint(clock_get_frequency(self->type, self->index));
}
MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_frequency_obj, samd_clock_get_frequency);
const mp_obj_property_t samd_clock_frequency_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&samd_clock_get_frequency_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj,
},
};
//| .. attribute:: calibration
//|
//| Clock calibration. Not all clocks can be calibrated.
//|
STATIC mp_obj_t samd_clock_get_calibration(mp_obj_t self_in) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int_from_uint(clock_get_calibration(self->type, self->index));
}
MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_calibration_obj, samd_clock_get_calibration);
STATIC mp_obj_t samd_clock_set_calibration(mp_obj_t self_in, mp_obj_t calibration) {
samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in);
int ret = clock_set_calibration(self->type, self->index, mp_obj_get_int(calibration));
if (ret == -2)
mp_raise_AttributeError("calibration is read only");
if (ret == -1)
mp_raise_ValueError("calibration is out of range");
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(samd_clock_set_calibration_obj, samd_clock_set_calibration);
const mp_obj_property_t samd_clock_calibration_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&samd_clock_get_calibration_obj,
(mp_obj_t)&samd_clock_set_calibration_obj,
(mp_obj_t)&mp_const_none_obj,
},
};
STATIC const mp_rom_map_elem_t samd_clock_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&samd_clock_enabled_obj) },
{ MP_ROM_QSTR(MP_QSTR_parent), MP_ROM_PTR(&samd_clock_parent_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&samd_clock_frequency_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&samd_clock_calibration_obj) },
};
STATIC MP_DEFINE_CONST_DICT(samd_clock_locals_dict, samd_clock_locals_dict_table);
const mp_obj_type_t samd_clock_type = {
{ &mp_type_type },
.name = MP_QSTR_Clock,
.print = samd_clock_print,
.locals_dict = (mp_obj_t)&samd_clock_locals_dict,
};

View File

@ -0,0 +1,77 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H
#define MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
const char *name;
uint8_t type;
uint8_t index;
} samd_clock_obj_t;
#define CLOCK(_name, _type, _index) \
const samd_clock_obj_t clock_ ## _name = { \
{ &samd_clock_type }, \
.name = #_name, \
.type = _type, \
.index = _index, \
}
#define CLOCK_SOURCE(_name) \
const samd_clock_obj_t clock_ ## _name = { \
{ &samd_clock_type }, \
.name = #_name, \
.type = 0, \
.index = GCLK_SOURCE_ ## _name, \
}
#define CLOCK_GCLK(_name) \
const samd_clock_obj_t clock_ ## _name = { \
{ &samd_clock_type }, \
.name = #_name, \
.type = 1, \
.index = _name ## _GCLK_ID, \
}
#define CLOCK_GCLK_(_name, _extra) \
const samd_clock_obj_t clock_ ## _name ## _ ## _extra = { \
{ &samd_clock_type }, \
.name = #_name "_" #_extra, \
.type = 1, \
.index = _name ## _GCLK_ID_ ## _extra, \
}
#define CLOCK_ENTRY(_name) { MP_ROM_QSTR(MP_QSTR_ ## _name), MP_ROM_PTR(&clock_ ## _name) }
#define CLOCK_ENTRY_(_name, _extra) { MP_ROM_QSTR(MP_QSTR_ ## _name ## _ ## _extra), MP_ROM_PTR(&clock_ ## _name ## _ ## _extra) }
extern const mp_obj_type_t samd_clock_type;
extern const mp_obj_dict_t samd_clock_globals;
#endif // MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H

View File

@ -0,0 +1,72 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#include "py/runtime.h"
#include "bindings/samd/Clock.h"
//| :mod:`samd` --- SAMD implementation settings
//| =================================================
//|
//| .. module:: samd
//| :synopsis: SAMD implementation settings
//| :platform: SAMD21
//|
//| Libraries
//|
//| .. toctree::
//| :maxdepth: 3
//|
//| Clock
//|
//| :mod:`samd.clock` --- samd clock names
//| --------------------------------------------------------
//|
//| .. module:: samd.clock
//| :synopsis: samd clock names
//| :platform: SAMD21
//|
//| References to clocks as named by the microcontroller
//|
const mp_obj_module_t samd_clock_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&samd_clock_globals,
};
STATIC const mp_rom_map_elem_t samd_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_samd) },
{ MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&samd_clock_module) },
};
STATIC MP_DEFINE_CONST_DICT(samd_module_globals, samd_module_globals_table);
const mp_obj_module_t samd_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&samd_module_globals,
};

View File

@ -11,6 +11,8 @@ CHIP_FAMILY = samd21
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor

View File

@ -46,3 +46,5 @@
GD25Q16C
#include "external_flash/external_flash.h"
#define BOARD_HAS_CRYSTAL 1

View File

@ -7,10 +7,12 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)
#define CIRCUITPY_BITBANG_APA102
// These are pins not to reset.
// QSPI Data pins and TX LED
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
// RX LED, QSPI CS, QSPI SCK and NeoPixel pin
// DotStar pins, QSPI CS, and QSPI SCK
#define MICROPY_PORT_B (PORT_PB02 | PORT_PB03 | PORT_PB10 | PORT_PB11)
#define MICROPY_PORT_C (0)
#define MICROPY_PORT_D (0)
@ -25,7 +27,7 @@
#include "external_flash/devices.h"
#define EXTERNAL_FLASH_DEVICE_COUNT 3
#define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C
#define EXTERNAL_FLASH_DEVICE_COUNT 1
#define EXTERNAL_FLASH_DEVICES GD25Q16C
#include "external_flash/external_flash.h"

View File

@ -47,3 +47,5 @@
GD25Q16C
#include "external_flash/external_flash.h"
#define BOARD_HAS_CRYSTAL 1

View File

@ -56,77 +56,6 @@ uint8_t find_free_gclk(uint16_t divisor) {
return 0xff;
}
bool gclk_enabled(uint8_t gclk) {
#ifdef SAMD51
return GCLK->GENCTRL[gclk].bit.GENEN;
#endif
#ifdef SAMD21
common_hal_mcu_disable_interrupts();
// Explicitly do a byte write so the peripheral knows we're just wanting to read the channel
// rather than write to it.
*((uint8_t*) &GCLK->GENCTRL.reg) = gclk;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
bool enabled = GCLK->GENCTRL.bit.GENEN;
common_hal_mcu_enable_interrupts();
return enabled;
#endif
}
void disable_gclk(uint8_t gclk) {
#ifdef SAMD51
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
GCLK->GENCTRL[gclk].bit.GENEN = false;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
#endif
#ifdef SAMD21
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk);
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
#endif
}
void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) {
#ifdef SAMD21
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(peripheral) | GCLK_CLKCTRL_GEN(gclk) | GCLK_CLKCTRL_CLKEN;
#endif
#ifdef SAMD51
GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk);
while(GCLK->SYNCBUSY.reg != 0) {}
#endif
}
void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) {
#ifdef SAMD21
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(peripheral) | GCLK_CLKCTRL_GEN(gclk);
#endif
#ifdef SAMD51
GCLK->PCHCTRL[peripheral].reg = 0;
#endif
}
void enable_clock_generator(uint8_t gclk, uint8_t source, uint16_t divisor) {
#ifdef SAMD21
GCLK->GENDIV.reg = GCLK_GENDIV_ID(gclk) | GCLK_GENDIV_DIV(divisor);
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk) | GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_GENEN;
while (GCLK->STATUS.bit.SYNCBUSY != 0) {}
#endif
#ifdef SAMD51
GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | GCLK_GENCTRL_GENEN;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
#endif
}
void disable_clock_generator(uint8_t gclk) {
#ifdef SAMD21
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk);
while (GCLK->STATUS.bit.SYNCBUSY != 0) {}
#endif
#ifdef SAMD51
GCLK->GENCTRL[gclk].reg = 0;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
#endif
}
void reset_gclks(void) {
// Never reset GCLK0 because its used for the core
#if CONF_GCLK_GEN_1_GENEN == 0

View File

@ -31,6 +31,7 @@
#include <stdint.h>
#include "include/sam.h"
#include "mpconfigboard.h" // for BOARD_HAS_CRYSTAL
#ifdef SAMD51
#define CLOCK_48MHZ GCLK_GENCTRL_SRC_DFLL_Val
@ -44,12 +45,29 @@
uint8_t find_free_gclk(uint16_t divisor);
bool gclk_enabled(uint8_t gclk);
void disable_gclk(uint8_t gclk);
void reset_gclks(void);
void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral);
void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral);
void enable_clock_generator(uint8_t gclk, uint8_t source, uint16_t divisor);
void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor);
void disable_clock_generator(uint8_t gclk);
static inline bool board_has_crystal(void) {
#ifdef BOARD_HAS_CRYSTAL
return BOARD_HAS_CRYSTAL == 1;
#else
return false;
#endif
}
void clock_init(void);
bool clock_get_enabled(uint8_t type, uint8_t index);
bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index);
uint32_t clock_get_frequency(uint8_t type, uint8_t index);
uint32_t clock_get_calibration(uint8_t type, uint8_t index);
int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_CLOCKS_H

View File

@ -34,6 +34,7 @@
#include "py/binary.h"
#include "py/mphal.h"
#include "peripherals.h"
#include "shared-bindings/analogio/AnalogIn.h"
#include "atmel_start_pins.h"
@ -89,57 +90,20 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
// Something else might have used the ADC in a different way,
// so we completely re-initialize it.
// Turn the clocks on.
#ifdef SAMD51
if (self->instance == ADC0) {
hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
} else if (self->instance == ADC1) {
hri_mclk_set_APBDMASK_ADC1_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
}
#endif
#ifdef SAMD21
_pm_enable_bus_clock(PM_BUS_APBC, ADC);
_gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
#endif
struct adc_sync_descriptor adc;
adc_sync_init(&adc, self->instance, (void *)NULL);
adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INTVCC1_Val);
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
samd_peripherals_adc_setup(&adc, self->instance);
// Full scale is 3.3V (VDDANA) = 65535.
// On SAMD21, INTVCC1 is 0.5*VDDANA. On SAMD51, INTVCC1 is 1*VDDANA.
// So on SAMD21 only, divide the input by 2, so full scale will match 0.5*VDDANA.
adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INTVCC1_Val);
#ifdef SAMD21
adc_sync_set_channel_gain(&adc, self->channel, ADC_INPUTCTRL_GAIN_DIV2_Val);
// Load the factory calibration
hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos);
// Bits 7:5
uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
// Bits 4:0
linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity);
#endif
// SAMD51 has a CALIB register but doesn't have documented fuses for them.
#ifdef SAMD51
uint8_t biasrefbuf;
uint8_t biasr2r;
uint8_t biascomp;
if (self->instance == ADC0) {
biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
} else {
biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
}
hri_adc_write_CALIB_BIASREFBUF_bf(self->instance, biasrefbuf);
hri_adc_write_CALIB_BIASR2R_bf(self->instance, biasr2r);
hri_adc_write_CALIB_BIASCOMP_bf(self->instance, biascomp);
#endif
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
adc_sync_enable_channel(&adc, self->channel);

View File

@ -48,7 +48,8 @@
#include "audio_dma.h"
#include "clocks.h"
#include "events.h"
#include "samd21_pins.h"
#include "i2s.h"
#include "pins.h"
#include "shared_dma.h"
#include "timers.h"
@ -155,18 +156,7 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self,
self->clock_unit = ws_clock_unit;
self->serializer = serializer;
// Make sure the I2S peripheral is running so we can see if the resources we need are free.
#ifdef SAMD51
hri_mclk_set_APBDMASK_I2S_bit(MCLK);
// Connect the clock units to the 2mhz clock by default. They can't reset without it.
connect_gclk_to_peripheral(5, I2S_GCLK_ID_0);
connect_gclk_to_peripheral(5, I2S_GCLK_ID_1);
#endif
#ifdef SAMD21
_pm_enable_bus_clock(PM_BUS_APBC, I2S);
#endif
turn_on_i2s();
if (I2S->CTRLA.bit.ENABLE == 0) {
I2S->CTRLA.bit.SWRST = 1;
@ -281,8 +271,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
}
// Configure the I2S peripheral
I2S->CTRLA.bit.ENABLE = 0;
while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
i2s_set_enable(false);
I2S->CLKCTRL[self->clock_unit].reg = clkctrl;
#ifdef SAMD21
@ -296,8 +285,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
enable_clock_generator(self->gclk, CLOCK_48MHZ, divisor);
connect_gclk_to_peripheral(self->gclk, I2S_GCLK_ID_0 + self->clock_unit);
I2S->CTRLA.bit.ENABLE = 1;
while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
i2s_set_enable(true);
#ifdef SAMD21
uint32_t tx_register = (uint32_t) &I2S->DATA[self->serializer].reg;
@ -336,6 +324,26 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
self->playing = true;
}
void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t* self) {
audio_dma_pause(&self->dma);
}
void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t* self) {
// Clear any overrun/underrun errors
#ifdef SAMD21
I2S->INTFLAG.reg = I2S_INTFLAG_TXUR0 << self->serializer;
#endif
#ifdef SAMD51
I2S->INTFLAG.reg = I2S_INTFLAG_TXUR0 | I2S_INTFLAG_TXUR1;
#endif
audio_dma_resume(&self->dma);
}
bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t* self) {
return audio_dma_get_paused(&self->dma);
}
void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) {
audio_dma_stop(&self->dma);

View File

@ -37,8 +37,15 @@
#include "shared-bindings/audiobusio/PDMIn.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "samd21_pins.h"
#include "atmel_start_pins.h"
#include "hal/include/hal_gpio.h"
#include "hal/utils/include/utils.h"
#include "audio_dma.h"
#include "clocks.h"
#include "events.h"
#include "i2s.h"
#include "pins.h"
#include "shared_dma.h"
#include "tick.h"
@ -48,6 +55,14 @@
// MEMS microphones must be clocked at at least 1MHz.
#define MIN_MIC_CLOCK 1000000
#ifdef SAMD21
#define SERCTRL(name) I2S_SERCTRL_ ## name
#endif
#ifdef SAMD51
#define SERCTRL(name) I2S_RXCTRL_ ## name
#endif
void pdmin_reset(void) {
while (I2S->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {}
I2S->INTENCLR.reg = I2S_INTENCLR_MASK;
@ -60,20 +75,33 @@ void pdmin_reset(void) {
void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
const mcu_pin_obj_t* clock_pin,
const mcu_pin_obj_t* data_pin,
uint32_t frequency,
uint32_t sample_rate,
uint8_t bit_depth,
bool mono,
uint8_t oversample) {
self->clock_pin = clock_pin; // PA10, PA20 -> SCK0, PB11 -> SCK1
if (clock_pin == &pin_PA10
#ifdef PIN_PA20
|| clock_pin == &pin_PA20
#ifdef SAMD21
if (clock_pin == &pin_PA10
#ifdef PIN_PA20
|| clock_pin == &pin_PA20
#endif
) {
self->clock_unit = 0;
#ifdef PIN_PB11
} else if (clock_pin == &pin_PB11) {
self->clock_unit = 1;
#endif
#endif
#ifdef SAMD51
if (clock_pin == &pin_PA10 || clock_pin == &pin_PB16) {
self->clock_unit = 0;
} else if (clock_pin == &pin_PB12
#ifdef PIN_PB28
|| data_pin == &pin_PB28) {
#else
) {
self->clock_unit = 0;
#ifdef PIN_PB11
} else if (clock_pin == &pin_PB11) {
self->clock_unit = 1;
#endif
self->clock_unit = 1;
#endif
} else {
mp_raise_ValueError("Invalid clock pin");
@ -81,80 +109,108 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
self->data_pin = data_pin; // PA07, PA19 -> SD0, PA08, PB16 -> SD1
#ifdef SAMD21
if (data_pin == &pin_PA07 || data_pin == &pin_PA19) {
self->serializer = 0;
} else if (data_pin == &pin_PA08
#ifdef PB16
#ifdef PIN_PB16
|| data_pin == &pin_PB16) {
#else
) {
#endif
self->serializer = 1;
#endif
#ifdef SAMD51
if (data_pin == &pin_PB10 || data_pin == &pin_PA22) {
self->serializer = 1;
#endif
} else {
mp_raise_ValueError("Invalid data pin");
}
claim_pin(clock_pin);
claim_pin(data_pin);
if (MP_STATE_VM(audiodma_block_counter) == NULL &&
!allocate_block_counter()) {
mp_raise_RuntimeError("Unable to allocate audio DMA block counter.");
}
if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != OVERSAMPLING) {
mp_raise_NotImplementedError("Only 8 or 16 bit mono with " MP_STRINGIFY(OVERSAMPLING) "x oversampling is supported.");
}
// TODO(tannewt): Use the DPLL to get a more precise sampling rate.
// DFLL -> GCLK (/600 for 8khz, /300 for 16khz and /150 for 32khz) -> DPLL (*(63 + 1)) -> GCLK ( / 10) -> 512khz
turn_on_i2s();
i2s_init(&self->i2s_instance, I2S);
struct i2s_clock_unit_config config_clock_unit;
i2s_clock_unit_get_config_defaults(&config_clock_unit);
config_clock_unit.clock.gclk_src = GCLK_GENERATOR_3;
config_clock_unit.clock.mck_src = I2S_MASTER_CLOCK_SOURCE_GCLK;
config_clock_unit.clock.mck_out_enable = false;
config_clock_unit.clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV;
uint32_t clock_divisor = (uint32_t) roundf( 8000000.0f / frequency / oversample);
config_clock_unit.clock.sck_div = clock_divisor;
float mic_clock_freq = 8000000.0f / clock_divisor;
self->frequency = mic_clock_freq / oversample;
if (mic_clock_freq < MIN_MIC_CLOCK || clock_divisor == 0 || clock_divisor > 255) {
mp_raise_ValueError("sampling frequency out of range");
if (I2S->CTRLA.bit.ENABLE == 0) {
I2S->CTRLA.bit.SWRST = 1;
while (I2S->CTRLA.bit.SWRST == 1) {}
} else {
#ifdef SAMD21
if ((I2S->CTRLA.vec.SEREN & (1 << self->serializer)) != 0) {
mp_raise_RuntimeError("Serializer in use");
}
#endif
#ifdef SAMD51
if (I2S->CTRLA.bit.RXEN == 1) {
mp_raise_RuntimeError("Serializer in use");
}
#endif
}
#ifdef SAMD51
#define GPIO_I2S_FUNCTION GPIO_PIN_FUNCTION_J
#endif
#ifdef SAMD21
#define GPIO_I2S_FUNCTION GPIO_PIN_FUNCTION_G
#endif
assert_pin_free(clock_pin);
assert_pin_free(data_pin);
config_clock_unit.frame.number_slots = 2;
config_clock_unit.frame.slot_size = I2S_SLOT_SIZE_16_BIT;
config_clock_unit.frame.data_delay = I2S_DATA_DELAY_0;
uint32_t clock_divisor = (uint32_t) roundf( 48000000.0f / sample_rate / oversample);
float mic_clock_freq = 48000000.0f / clock_divisor;
self->sample_rate = mic_clock_freq / oversample;
if (mic_clock_freq < MIN_MIC_CLOCK || clock_divisor == 0) {
mp_raise_ValueError("sampling rate out of range");
}
// Find a free GCLK to generate the MCLK signal.
uint8_t gclk = find_free_gclk(clock_divisor);
if (gclk > GCLK_GEN_NUM) {
mp_raise_RuntimeError("Unable to find free GCLK");
}
self->gclk = gclk;
config_clock_unit.frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_SLOT;
enable_clock_generator(self->gclk, CLOCK_48MHZ, clock_divisor);
connect_gclk_to_peripheral(self->gclk, I2S_GCLK_ID_0 + self->clock_unit);
config_clock_unit.mck_pin.enable = false;
config_clock_unit.sck_pin.enable = true;
config_clock_unit.sck_pin.gpio = self->clock_pin->pin;
// Mux is always the same.
config_clock_unit.sck_pin.mux = 6L;
config_clock_unit.fs_pin.enable = false;
i2s_clock_unit_set_config(&self->i2s_instance, self->clock_unit, &config_clock_unit);
// Clock unit configuration
struct i2s_serializer_config config_serializer;
i2s_serializer_get_config_defaults(&config_serializer);
config_serializer.clock_unit = self->clock_unit;
config_serializer.mode = I2S_SERIALIZER_PDM2;
config_serializer.data_size = I2S_DATA_SIZE_32BIT;
config_serializer.data_pin.gpio = self->data_pin->pin;
// Mux is always the same.
config_serializer.data_pin.mux = 6L;
config_serializer.data_pin.enable = true;
i2s_serializer_set_config(&self->i2s_instance, self->serializer, &config_serializer);
i2s_enable(&self->i2s_instance);
uint32_t clkctrl = I2S_CLKCTRL_MCKSEL_GCLK |
I2S_CLKCTRL_NBSLOTS(2) |
I2S_CLKCTRL_FSWIDTH_SLOT |
I2S_CLKCTRL_SLOTSIZE_16;
// Serializer configuration
#ifdef SAMD21
uint32_t serctrl = (self->clock_unit << I2S_SERCTRL_CLKSEL_Pos) | SERCTRL(SERMODE_PDM2) | SERCTRL(DATASIZE_32);
#endif
#ifdef SAMD51
uint32_t serctrl = (self->clock_unit << I2S_RXCTRL_CLKSEL_Pos) | SERCTRL(SERMODE_PDM2) | SERCTRL(DATASIZE_32);
#endif
// Configure the I2S peripheral
i2s_set_enable(false);
I2S->CLKCTRL[self->clock_unit].reg = clkctrl;
#ifdef SAMD21
I2S->SERCTRL[self->serializer].reg = serctrl;
#endif
#ifdef SAMD51
I2S->RXCTRL.reg = serctrl;
#endif
i2s_set_enable(true);
// Run the serializer all the time. This eliminates startup delay for the microphone.
i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit);
i2s_serializer_enable(&self->i2s_instance, self->serializer);
i2s_set_clock_unit_enable(self->clock_unit, true);
i2s_set_serializer_enable(self->serializer, true);
claim_pin(clock_pin);
claim_pin(data_pin);
gpio_set_pin_function(self->clock_pin->pin, GPIO_I2S_FUNCTION);
gpio_set_pin_function(self->data_pin->pin, GPIO_I2S_FUNCTION);
self->bytes_per_sample = oversample >> 3;
self->bit_depth = bit_depth;
@ -168,10 +224,15 @@ void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) {
if (common_hal_audiobusio_pdmin_deinited(self)) {
return;
}
i2s_disable(&self->i2s_instance);
i2s_serializer_disable(&self->i2s_instance, self->serializer);
i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit);
i2s_reset(&self->i2s_instance);
i2s_set_serializer_enable(self->serializer, false);
i2s_set_clock_unit_enable(self->clock_unit, false);
i2s_set_enable(false);
disconnect_gclk_from_peripheral(self->gclk, I2S_GCLK_ID_0 + self->clock_unit);
disable_clock_generator(self->gclk);
reset_pin(self->clock_pin->pin);
reset_pin(self->data_pin->pin);
self->clock_pin = mp_const_none;
@ -182,65 +243,67 @@ uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t* self)
return self->bit_depth;
}
uint32_t common_hal_audiobusio_pdmin_get_frequency(audiobusio_pdmin_obj_t* self) {
return self->frequency;
uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t* self) {
return self->sample_rate;
}
static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length,
DmacDescriptor* second_descriptor,
uint8_t words_per_buffer, uint8_t words_per_sample,
uint32_t* first_buffer, uint32_t* second_buffer) {
// Set up the DMA
struct dma_descriptor_config descriptor_config;
dma_descriptor_get_config_defaults(&descriptor_config);
descriptor_config.beat_size = DMA_BEAT_SIZE_WORD;
descriptor_config.step_selection = DMA_STEPSEL_SRC;
descriptor_config.source_address = (uint32_t)&I2S->DATA[self->serializer];
descriptor_config.src_increment_enable = false;
DmacDescriptor* descriptor,
DmacDescriptor* second_descriptor,
uint32_t words_per_buffer, uint8_t words_per_sample,
uint32_t* first_buffer, uint32_t* second_buffer) {
descriptor->BTCTRL.reg = DMAC_BTCTRL_VALID |
DMAC_BTCTRL_BLOCKACT_NOACT |
DMAC_BTCTRL_EVOSEL_BLOCK |
DMAC_BTCTRL_DSTINC |
DMAC_BTCTRL_BEATSIZE_WORD;
// Block transfer count is the number of beats per block (aka descriptor).
// In this case there are two bytes per beat so divide the length by two.
uint16_t block_transfer_count = words_per_buffer;
if (length * words_per_sample < words_per_buffer) {
block_transfer_count = length * words_per_sample;
}
descriptor_config.block_transfer_count = block_transfer_count;
descriptor_config.destination_address = ((uint32_t) first_buffer + sizeof(uint32_t) * block_transfer_count);
descriptor_config.event_output_selection = DMA_EVENT_OUTPUT_BLOCK;
descriptor_config.next_descriptor_address = 0;
descriptor->BTCNT.reg = block_transfer_count;
descriptor->DSTADDR.reg = ((uint32_t) first_buffer + sizeof(uint32_t) * block_transfer_count);
descriptor->DESCADDR.reg = 0;
if (length * words_per_sample > words_per_buffer) {
descriptor_config.next_descriptor_address = ((uint32_t)second_descriptor);
descriptor->DESCADDR.reg = ((uint32_t)second_descriptor);
}
dma_descriptor_create(audio_dma.descriptor, &descriptor_config);
#ifdef SAMD21
descriptor->SRCADDR.reg = (uint32_t)&I2S->DATA[self->serializer];
#endif
#ifdef SAMD51
descriptor->SRCADDR.reg = (uint32_t)&I2S->RXDATA;
#endif
// Do we need more values than will fit in the first buffer?
// If so, set up a second buffer chained to be filled after the first buffer.
if (length * words_per_sample > words_per_buffer) {
block_transfer_count = words_per_buffer;
descriptor_config.next_descriptor_address = ((uint32_t)audio_dma.descriptor);
second_descriptor->DESCADDR.reg = ((uint32_t)descriptor);
if (length * words_per_sample < 2 * words_per_buffer) {
// Length needed is more than one buffer but less than two.
// Subtract off the size of the first buffer, and what remains is the count we need.
block_transfer_count = length * words_per_sample - words_per_buffer;
descriptor_config.next_descriptor_address = 0;
second_descriptor->DESCADDR.reg = 0;
}
descriptor_config.block_transfer_count = block_transfer_count;
descriptor_config.destination_address = ((uint32_t) second_buffer + sizeof(uint32_t) * block_transfer_count);
dma_descriptor_create(second_descriptor, &descriptor_config);
second_descriptor->DSTADDR.reg = ((uint32_t) second_buffer + sizeof(uint32_t) * block_transfer_count);
second_descriptor->BTCNT.reg = block_transfer_count;
#ifdef SAMD21
second_descriptor->SRCADDR.reg = (uint32_t)&I2S->DATA[self->serializer];
#endif
#ifdef SAMD51
second_descriptor->SRCADDR.reg = (uint32_t)&I2S->RXDATA;
#endif
second_descriptor->BTCTRL.reg = DMAC_BTCTRL_VALID |
DMAC_BTCTRL_BLOCKACT_NOACT |
DMAC_BTCTRL_EVOSEL_BLOCK |
DMAC_BTCTRL_DSTINC |
DMAC_BTCTRL_BEATSIZE_WORD;
}
switch_audiodma_trigger(I2S_DMAC_ID_RX_0 + self->serializer);
}
void start_dma(audiobusio_pdmin_obj_t* self) {
dma_start_transfer_job(&audio_dma);
tc_start_counter(MP_STATE_VM(audiodma_block_counter));
I2S->DATA[1].reg = I2S->DATA[1].reg;
}
void stop_dma(audiobusio_pdmin_obj_t* self) {
// Shutdown the DMA: serializer keeps running.
tc_stop_counter(MP_STATE_VM(audiodma_block_counter));
dma_abort_job(&audio_dma);
}
// a windowed sinc filter for 44 khz, 64 samples
@ -290,20 +353,32 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) {
// output_buffer_length is the number of slots, not the number of bytes.
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
uint16_t* output_buffer, uint32_t output_buffer_length) {
uint8_t dma_channel = find_free_audio_dma_channel();
uint8_t event_channel = find_sync_event_channel();
// We allocate two buffers on the stack to use for double buffering.
const uint8_t samples_per_buffer = SAMPLES_PER_BUFFER;
// For every word we record, we throw away 2 bytes of a phantom second channel.
const uint8_t words_per_sample = self->bytes_per_sample / 2;
const uint8_t words_per_buffer = samples_per_buffer * words_per_sample;
uint8_t words_per_sample = self->bytes_per_sample / 2;
uint32_t words_per_buffer = samples_per_buffer * words_per_sample;
uint32_t first_buffer[words_per_buffer];
uint32_t second_buffer[words_per_buffer];
turn_on_event_system();
COMPILER_ALIGNED(16) DmacDescriptor second_descriptor;
setup_dma(self, output_buffer_length, &second_descriptor, words_per_buffer,
words_per_sample, first_buffer, second_buffer);
setup_dma(self, output_buffer_length, dma_descriptor(dma_channel), &second_descriptor,
words_per_buffer, words_per_sample, first_buffer, second_buffer);
start_dma(self);
uint8_t trigger_source = I2S_DMAC_ID_RX_0;
#ifdef SAMD21
trigger_source += self->serializer;
#endif
dma_configure(dma_channel, trigger_source, true);
init_event_channel_interrupt(event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
dma_enable_channel(dma_channel);
// Record
uint32_t buffers_processed = 0;
@ -311,24 +386,23 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
uint32_t remaining_samples_needed = output_buffer_length;
while (values_output < output_buffer_length) {
if (event_interrupt_overflow(event_channel)) {
// Looks like we aren't keeping up. We shouldn't skip a buffer so stop early.
break;
}
// Wait for the next buffer to fill
uint32_t block_counter;
while ((block_counter = tc_get_count_value(MP_STATE_VM(audiodma_block_counter))) == buffers_processed) {
while (!event_interrupt_active(event_channel)) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
}
if (block_counter != (buffers_processed + 1)) {
// Looks like we aren't keeping up. We shouldn't skip a buffer.
break;
}
// The mic is running all the time, so we don't need to wait the usual 10msec or 100msec
// for it to start up.
// Flip back and forth between processing the first and second buffers.
uint32_t *buffer = first_buffer;
DmacDescriptor* descriptor = audio_dma.descriptor;
DmacDescriptor* descriptor = dma_descriptor(dma_channel);
if (buffers_processed % 2 == 1) {
buffer = second_buffer;
descriptor = &second_descriptor;
@ -375,7 +449,8 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
}
}
stop_dma(self);
disable_event_channel(event_channel);
dma_disable_channel(dma_channel);
return values_output;
}

View File

@ -36,11 +36,12 @@ typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *clock_pin;
const mcu_pin_obj_t *data_pin;
uint32_t frequency;
uint32_t sample_rate;
uint8_t serializer;
uint8_t clock_unit;
uint8_t bytes_per_sample;
uint8_t bit_depth;
uint8_t gclk;
} audiobusio_pdmin_obj_t;
void pdmin_reset(void);

View File

@ -327,6 +327,32 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self,
self->playing = true;
}
void common_hal_audioio_audioout_pause(audioio_audioout_obj_t* self) {
audio_dma_pause(&self->left_dma);
#ifdef SAMD51
audio_dma_pause(&self->right_dma);
#endif
}
void common_hal_audioio_audioout_resume(audioio_audioout_obj_t* self) {
// Clear any overrun/underrun errors
#ifdef SAMD21
DAC->INTFLAG.reg = DAC_INTFLAG_UNDERRUN;
#endif
#ifdef SAMD51
DAC->INTFLAG.reg = DAC_INTFLAG_UNDERRUN0 | DAC_INTFLAG_UNDERRUN1;
#endif
audio_dma_resume(&self->left_dma);
#ifdef SAMD51
audio_dma_resume(&self->right_dma);
#endif
}
bool common_hal_audioio_audioout_get_paused(audioio_audioout_obj_t* self) {
return audio_dma_get_paused(&self->left_dma);
}
void common_hal_audioio_audioout_stop(audioio_audioout_obj_t* self) {
Tc* timer = tc_insts[self->tc_index];
timer->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP;

View File

@ -72,7 +72,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT);
// Turn on "strong" pin driving (more current available). See DRVSTR doc in datasheet.
hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin), pin);
hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin), GPIO_PIN(pin));
self->output = true;
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
@ -158,7 +158,7 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
mp_raise_AttributeError("Cannot get pull while in output mode");
return PULL_NONE;
} else {
if (hri_port_get_PINCFG_PULLEN_bit(PORT, (enum gpio_port)GPIO_PORT(pin), pin) == 0) {
if (hri_port_get_PINCFG_PULLEN_bit(PORT, (enum gpio_port)GPIO_PORT(pin), GPIO_PIN(pin)) == 0) {
return PULL_NONE;
} if (hri_port_get_OUT_reg(PORT, (enum gpio_port)GPIO_PORT(pin), 1U << GPIO_PIN(pin)) > 0) {
return PULL_UP;

View File

@ -63,166 +63,219 @@
#include "common-hal/microcontroller/Processor.h"
#include "peripherals.h"
#include "peripheral_clk_config.h"
// #define ADC_TEMP_SAMPLE_LENGTH 4
// #define INT1V_VALUE_FLOAT 1.0
// #define INT1V_DIVIDER_1000 1000.0
// #define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0
//
// typedef struct nvm_calibration_data_t {
// float tempR; // Production Room temperature
// float tempH; // Production Hot temperature
// float INT1VR; // Room temp 2's complement of the internal 1V reference value
// float INT1VH; // Hot temp 2's complement of the internal 1V reference value
// uint16_t ADCR; // Production Room temperature ADC value
// uint16_t ADCH; // Production Hot temperature ADC value
// float VADCR; // Room temperature ADC voltage
// float VADCH; // Hot temperature ADC voltage
// } nvm_calibration_data_t;
#define ADC_TEMP_SAMPLE_LENGTH 4
#define INT1V_VALUE_FLOAT 1.0
#define INT1V_DIVIDER_1000 1000.0
#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0
// Decimal to fraction conversion. (adapted from ASF sample).
// STATIC float convert_dec_to_frac(uint8_t val) {
// float float_val = (float)val;
// if (val < 10) {
// return (float_val/10.0);
// } else if (val < 100) {
// return (float_val/100.0);
// } else {
// return (float_val/1000.0);
// }
// }
STATIC float convert_dec_to_frac(uint8_t val) {
float float_val = (float)val;
if (val < 10) {
return (float_val/10.0);
} else if (val < 100) {
return (float_val/100.0);
} else {
return (float_val/1000.0);
}
}
// STATIC void configure_adc_temp(struct adc_module *adc_instance) {
// struct adc_config config_adc;
// adc_get_config_defaults(&config_adc);
//
// // The parameters chosen here are from the temperature example in:
// // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
// // That note also recommends in general:
// // "Discard the first conversion result whenever there is a change
// // in ADC configuration like voltage reference / ADC channel change."
//
// config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16;
// config_adc.reference = ADC_REFERENCE_INT1V;
// config_adc.positive_input = ADC_POSITIVE_INPUT_TEMP;
// config_adc.negative_input = ADC_NEGATIVE_INPUT_GND;
// config_adc.sample_length = ADC_TEMP_SAMPLE_LENGTH;
//
// adc_init(adc_instance, ADC, &config_adc);
//
// // Oversample and decimate. A higher samplenum produces a more stable result.
// ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4;
// //ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(4) | ADC_AVGCTRL_SAMPLENUM_16;
// }
// Extract the production calibration data information from NVM (adapted from ASF sample),
// then calculate the temperature
#ifdef SAMD21
STATIC float calculate_temperature(uint16_t raw_value) {
volatile uint32_t val1; /* Temperature Log Row Content first 32 bits */
volatile uint32_t val2; /* Temperature Log Row Content another 32 bits */
uint8_t room_temp_val_int; /* Integer part of room temperature in °C */
uint8_t room_temp_val_dec; /* Decimal part of room temperature in °C */
uint8_t hot_temp_val_int; /* Integer part of hot temperature in °C */
uint8_t hot_temp_val_dec; /* Decimal part of hot temperature in °C */
int8_t room_int1v_val; /* internal 1V reference drift at room temperature */
int8_t hot_int1v_val; /* internal 1V reference drift at hot temperature*/
// Extract the production calibration data information from NVM (adapted from ASF sample).
//
// STATIC void load_calibration_data(nvm_calibration_data_t *cal) {
// volatile uint32_t val1; /* Temperature Log Row Content first 32 bits */
// volatile uint32_t val2; /* Temperature Log Row Content another 32 bits */
// uint8_t room_temp_val_int; /* Integer part of room temperature in °C */
// uint8_t room_temp_val_dec; /* Decimal part of room temperature in °C */
// uint8_t hot_temp_val_int; /* Integer part of hot temperature in °C */
// uint8_t hot_temp_val_dec; /* Decimal part of hot temperature in °C */
// int8_t room_int1v_val; /* internal 1V reference drift at room temperature */
// int8_t hot_int1v_val; /* internal 1V reference drift at hot temperature*/
//
// uint32_t *temp_log_row_ptr = (uint32_t *)NVMCTRL_TEMP_LOG;
//
// val1 = *temp_log_row_ptr;
// temp_log_row_ptr++;
// val2 = *temp_log_row_ptr;
//
// room_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Pos);
// room_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Pos);
//
// hot_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Pos);
// hot_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Pos);
//
// room_int1v_val = (int8_t)((val1 & NVMCTRL_FUSES_ROOM_INT1V_VAL_Msk) >> NVMCTRL_FUSES_ROOM_INT1V_VAL_Pos);
// hot_int1v_val = (int8_t)((val2 & NVMCTRL_FUSES_HOT_INT1V_VAL_Msk) >> NVMCTRL_FUSES_HOT_INT1V_VAL_Pos);
//
// cal->ADCR = (uint16_t)((val2 & NVMCTRL_FUSES_ROOM_ADC_VAL_Msk) >> NVMCTRL_FUSES_ROOM_ADC_VAL_Pos);
//
// cal->ADCH = (uint16_t)((val2 & NVMCTRL_FUSES_HOT_ADC_VAL_Msk) >> NVMCTRL_FUSES_HOT_ADC_VAL_Pos);
//
// cal->tempR = room_temp_val_int + convert_dec_to_frac(room_temp_val_dec);
// cal->tempH = hot_temp_val_int + convert_dec_to_frac(hot_temp_val_dec);
//
// cal->INT1VR = 1 - ((float)room_int1v_val/INT1V_DIVIDER_1000);
// cal->INT1VH = 1 - ((float)hot_int1v_val/INT1V_DIVIDER_1000);
//
// cal->VADCR = ((float)cal->ADCR * cal->INT1VR)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
// cal->VADCH = ((float)cal->ADCH * cal->INT1VH)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
// }
float tempR; // Production Room temperature
float tempH; // Production Hot temperature
float INT1VR; // Room temp 2's complement of the internal 1V reference value
float INT1VH; // Hot temp 2's complement of the internal 1V reference value
uint16_t ADCR; // Production Room temperature ADC value
uint16_t ADCH; // Production Hot temperature ADC value
float VADCR; // Room temperature ADC voltage
float VADCH; // Hot temperature ADC voltage
/*
* Calculate fine temperature using Equation1 and Equation
* 1b as mentioned in data sheet section "Temperature Sensor Characteristics"
* of Electrical Characteristics. (adapted from ASF sample code).
*/
// STATIC float calculate_temperature(uint16_t raw_code, nvm_calibration_data_t *cal)
// {
// float VADC; /* Voltage calculation using ADC result for Coarse Temp calculation */
// float VADCM; /* Voltage calculation using ADC result for Fine Temp calculation. */
// float INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */
//
// VADC = ((float)raw_code * INT1V_VALUE_FLOAT)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
//
// // Hopefully compiler will remove common subepxressions here.
//
// /* Coarse Temp Calculation by assume INT1V=1V for this ADC conversion */
// float coarse_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADC - cal->VADCR));
//
// /* Calculation to find the real INT1V value during the ADC conversion */
// INT1VM = cal->INT1VR + (((cal->INT1VH - cal->INT1VR) * (coarse_temp - cal->tempR))/(cal->tempH - cal->tempR));
//
// VADCM = ((float)raw_code * INT1VM)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
//
// /* Fine Temp Calculation by replace INT1V=1V by INT1V = INT1Vm for ADC conversion */
// float fine_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADCM - cal->VADCR));
//
// return fine_temp;
// }
uint32_t *temp_log_row_ptr = (uint32_t *)NVMCTRL_TEMP_LOG;
val1 = *temp_log_row_ptr;
temp_log_row_ptr++;
val2 = *temp_log_row_ptr;
room_temp_val_int = (uint8_t)((val1 & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos);
room_temp_val_dec = (uint8_t)((val1 & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos);
hot_temp_val_int = (uint8_t)((val1 & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos);
hot_temp_val_dec = (uint8_t)((val1 & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos);
room_int1v_val = (int8_t)((val1 & FUSES_ROOM_INT1V_VAL_Msk) >> FUSES_ROOM_INT1V_VAL_Pos);
hot_int1v_val = (int8_t)((val2 & FUSES_HOT_INT1V_VAL_Msk) >> FUSES_HOT_INT1V_VAL_Pos);
ADCR = (uint16_t)((val2 & FUSES_ROOM_ADC_VAL_Msk) >> FUSES_ROOM_ADC_VAL_Pos);
ADCH = (uint16_t)((val2 & FUSES_HOT_ADC_VAL_Msk) >> FUSES_HOT_ADC_VAL_Pos);
tempR = room_temp_val_int + convert_dec_to_frac(room_temp_val_dec);
tempH = hot_temp_val_int + convert_dec_to_frac(hot_temp_val_dec);
INT1VR = 1 - ((float)room_int1v_val/INT1V_DIVIDER_1000);
INT1VH = 1 - ((float)hot_int1v_val/INT1V_DIVIDER_1000);
VADCR = ((float)ADCR * INT1VR)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
VADCH = ((float)ADCH * INT1VH)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
float VADC; /* Voltage calculation using ADC result for Coarse Temp calculation */
float VADCM; /* Voltage calculation using ADC result for Fine Temp calculation. */
float INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */
VADC = ((float)raw_value * INT1V_VALUE_FLOAT)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
// Hopefully compiler will remove common subepxressions here.
// calculate fine temperature using Equation1 and Equation
// 1b as mentioned in data sheet section "Temperature Sensor Characteristics"
// of Electrical Characteristics. (adapted from ASF sample code).
// Coarse Temp Calculation by assume INT1V=1V for this ADC conversion
float coarse_temp = tempR + (((tempH - tempR)/(VADCH - VADCR)) * (VADC - VADCR));
// Calculation to find the real INT1V value during the ADC conversion
INT1VM = INT1VR + (((INT1VH - INT1VR) * (coarse_temp - tempR))/(tempH - tempR));
VADCM = ((float)raw_value * INT1VM)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
// Fine Temp Calculation by replace INT1V=1V by INT1V = INT1Vm for ADC conversion
float fine_temp = tempR + (((tempH - tempR)/(VADCH - VADCR)) * (VADCM - VADCR));
return fine_temp;
}
#endif // SAMD21
#ifdef SAMD51
STATIC float calculate_temperature(uint16_t TP, uint16_t TC) {
uint32_t TLI = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos;
uint32_t TLD = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos;
float TL = TLI + convert_dec_to_frac(TLD);
uint32_t THI = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos;
uint32_t THD = (*(uint32_t *)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos;
float TH = THI + convert_dec_to_frac(THD);
uint16_t VPL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_PTAT_ADDR & FUSES_ROOM_ADC_VAL_PTAT_Msk) >> FUSES_ROOM_ADC_VAL_PTAT_Pos;
uint16_t VPH = (*(uint32_t *)FUSES_HOT_ADC_VAL_PTAT_ADDR & FUSES_HOT_ADC_VAL_PTAT_Msk) >> FUSES_HOT_ADC_VAL_PTAT_Pos;
uint16_t VCL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_CTAT_ADDR & FUSES_ROOM_ADC_VAL_CTAT_Msk) >> FUSES_ROOM_ADC_VAL_CTAT_Pos;
uint16_t VCH = (*(uint32_t *)FUSES_HOT_ADC_VAL_CTAT_ADDR & FUSES_HOT_ADC_VAL_CTAT_Msk) >> FUSES_HOT_ADC_VAL_CTAT_Pos;
// From SAMD51 datasheet: section 45.6.3.1 (page 1327).
return (TL*VPH*TC - VPL*TH*TC - TL*VCH*TP + TH*VCL*TP) / (VCL*TP - VCH*TP - VPL*TC + VPH*TC);
}
#endif // SAMD51
// External interface.
//
float common_hal_mcu_processor_get_temperature(void) {
// struct adc_module adc_instance_struct;
//
// system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE);
// configure_adc_temp(&adc_instance_struct);
// nvm_calibration_data_t nvm_calibration_data;
// load_calibration_data(&nvm_calibration_data);
//
// adc_enable(&adc_instance_struct);
//
// uint16_t data;
// enum status_code status;
//
// // Read twice and discard first result, as recommended in section 14 of
// // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
// // "Discard the first conversion result whenever there is a change in ADC configuration
// // like voltage reference / ADC channel change"
// // Empirical observation shows the first reading is quite different than subsequent ones.
//
// adc_start_conversion(&adc_instance_struct);
// do {
// status = adc_read(&adc_instance_struct, &data);
// } while (status == STATUS_BUSY);
//
// adc_start_conversion(&adc_instance_struct);
// do {
// status = adc_read(&adc_instance_struct, &data);
// } while (status == STATUS_BUSY);
//
// // Disable so that someone else can use the adc with different settings.
// adc_disable(&adc_instance_struct);
// return calculate_temperature(data, &nvm_calibration_data);
return 0;
struct adc_sync_descriptor adc;
static Adc* adc_insts[] = ADC_INSTS;
samd_peripherals_adc_setup(&adc, adc_insts[0]);
#ifdef SAMD21
// The parameters chosen here are from the temperature example in:
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
// That note also recommends in general:
// "Discard the first conversion result whenever there is a change
// in ADC configuration like voltage reference / ADC channel change."
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INT1V_Val);
// Channel passed in adc_sync_enable_channel is actually ignored (!).
adc_sync_enable_channel(&adc, ADC_INPUTCTRL_MUXPOS_TEMP_Val);
adc_sync_set_inputs(&adc,
ADC_INPUTCTRL_MUXPOS_TEMP_Val, // pos_input
ADC_INPUTCTRL_MUXNEG_GND_Val, // neg_input
ADC_INPUTCTRL_MUXPOS_TEMP_Val); // channel channel (this arg is ignored (!))
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
hri_adc_write_CTRLB_PRESCALER_bf(adc.device.hw, ADC_CTRLB_PRESCALER_DIV32_Val);
hri_adc_write_SAMPCTRL_SAMPLEN_bf(adc.device.hw, ADC_TEMP_SAMPLE_LENGTH);
hri_sysctrl_set_VREF_TSEN_bit(SYSCTRL);
// Oversample and decimate. A higher samplenum produces a more stable result.
hri_adc_write_AVGCTRL_SAMPLENUM_bf(adc.device.hw, ADC_AVGCTRL_SAMPLENUM_4_Val);
hri_adc_write_AVGCTRL_ADJRES_bf(adc.device.hw, 2);
volatile uint16_t value;
// Read twice and discard first result, as recommended in section 14 of
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
// "Discard the first conversion result whenever there is a change in ADC configuration
// like voltage reference / ADC channel change"
// Empirical observation shows the first reading is quite different than subsequent ones.
// The channel listed in adc_sync_read_channel is actually ignored(!).
// Must be set as above with adc_sync_set_inputs.
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_TEMP_Val, ((uint8_t*) &value), 2);
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_TEMP_Val, ((uint8_t*) &value), 2);
adc_sync_deinit(&adc);
return calculate_temperature(value);
#endif // SAMD21
#ifdef SAMD51
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
// Reference voltage choice is a guess. It's not specified in the datasheet that I can see.
// INTVCC1 seems to read a little high.
// INTREF doesn't work: ADC hangs BUSY.
adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INTVCC0_Val);
// If ONDEMAND=1, we don't need to use the VREF.TSSEL bit to choose PTAT and CTAT.
hri_supc_set_VREF_ONDEMAND_bit(SUPC);
hri_supc_set_VREF_TSEN_bit(SUPC);
// Channel passed in adc_sync_enable_channel is actually ignored (!).
adc_sync_enable_channel(&adc, ADC_INPUTCTRL_MUXPOS_PTAT_Val);
adc_sync_set_inputs(&adc,
ADC_INPUTCTRL_MUXPOS_PTAT_Val, // pos_input
ADC_INPUTCTRL_MUXNEG_GND_Val, // neg_input
ADC_INPUTCTRL_MUXPOS_PTAT_Val); // channel (this arg is ignored (!))
// Read both temperature sensors.
volatile uint16_t ptat;
volatile uint16_t ctat;
// The channel listed in adc_sync_read_channel is actually ignored(!).
// Must be set as above with adc_sync_set_inputs.
// Read twice for stability (necessary?)
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_PTAT_Val, ((uint8_t*) &ptat), 2);
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_PTAT_Val, ((uint8_t*) &ptat), 2);
adc_sync_set_inputs(&adc,
ADC_INPUTCTRL_MUXPOS_CTAT_Val, // pos_input
ADC_INPUTCTRL_MUXNEG_GND_Val, // neg_input
ADC_INPUTCTRL_MUXPOS_CTAT_Val); // channel (this arg is ignored (!))
// Channel passed in adc_sync_enable_channel is actually ignored (!).
adc_sync_enable_channel(&adc, ADC_INPUTCTRL_MUXPOS_CTAT_Val);
// The channel listed in adc_sync_read_channel is actually ignored(!).
// Must be set as above with adc_sync_set_inputs.
// Read twice for stability (necessary?)
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_CTAT_Val, ((uint8_t*) &ctat), 2);
adc_sync_read_channel(&adc, ADC_INPUTCTRL_MUXPOS_CTAT_Val, ((uint8_t*) &ctat), 2);
hri_supc_set_VREF_ONDEMAND_bit(SUPC);
adc_sync_deinit(&adc);
return calculate_temperature(ptat, ctat);
#endif // SAMD51
}

View File

@ -151,6 +151,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
// one output so we start with the TCs to see if they work.
int8_t direction = -1;
uint8_t start = NUM_TIMERS_PER_PIN - 1;
bool found = false;
if (variable_frequency) {
direction = 1;
start = 0;
@ -162,6 +163,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
continue;
}
if (t->is_tc) {
found = true;
Tc* tc = tc_insts[t->index];
if (tc->COUNT16.CTRLA.bit.ENABLE == 0 && t->wave_output == 1) {
timer = t;
@ -177,7 +179,11 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
}
if (timer == NULL) {
mp_raise_RuntimeError("All timers in use");
if (found) {
mp_raise_ValueError("All timers for this pin are in use");
} else {
mp_raise_RuntimeError("All timers in use");
}
return;
}

View File

@ -283,12 +283,9 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
if (trigger_duration > 0) {
gpio_set_pin_pull_mode(self->pin, GPIO_PULL_OFF);
gpio_set_pin_direction(self->pin, GPIO_DIRECTION_OUT);
common_hal_mcu_disable_interrupts();
gpio_set_pin_level(self->pin, !self->idle_state);
common_hal_mcu_delay_us(trigger_duration);
common_hal_mcu_delay_us((uint32_t)trigger_duration);
gpio_set_pin_level(self->pin, self->idle_state);
common_hal_mcu_enable_interrupts();
}
// Reconfigure the pin and make sure its set to detect the first edge.

View File

@ -64,6 +64,12 @@ void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
}
void common_hal_rtc_set_time(timeutils_struct_time_t *tm) {
// Reset prescaler to increase initial precision. Otherwise we can be up to 1 second off already.
uint32_t freqcorr = hri_rtcmode0_read_FREQCORR_reg(calendar.device.hw);
calendar_deinit(&calendar);
rtc_init();
hri_rtcmode0_write_FREQCORR_reg(calendar.device.hw, freqcorr);
struct calendar_date date = {
.year = tm->tm_year,
.month = tm->tm_mon,

View File

@ -35,12 +35,27 @@
#include "genhdr/autogen_usb_descriptor.h"
// Buffers are report size + 1 to include the Report ID prefix byte if needed.
#ifdef USB_HID_REPORT_LENGTH_KEYBOARD
static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD + 1];
#endif
#ifdef USB_HID_REPORT_ID_MOUSE
static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE + 1];
#endif
#ifdef USB_HID_REPORT_ID_CONSUMER
static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER + 1];
#endif
#ifdef USB_HID_REPORT_ID_SYS_CONTROL
static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL + 1];
#endif
#ifdef USB_HID_REPORT_ID_GAMEPAD
static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD + 1];
#endif
#ifdef USB_HID_REPORT_ID_DIGITIZER
static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER + 1];
#endif
usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
#ifdef USB_HID_REPORT_LENGTH_KEYBOARD
{
.base = { .type = &usb_hid_device_type },
.report_buffer = keyboard_report_buffer,
@ -50,6 +65,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
.usage_page = 0x01,
.usage = 0x06,
},
#endif
#ifdef USB_HID_REPORT_ID_MOUSE
{
.base = { .type = &usb_hid_device_type },
.report_buffer = mouse_report_buffer,
@ -59,6 +76,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
.usage_page = 0x01,
.usage = 0x02,
},
#endif
#ifdef USB_HID_REPORT_ID_CONSUMER
{
.base = { .type = &usb_hid_device_type },
.report_buffer = consumer_report_buffer,
@ -68,6 +87,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
.usage_page = 0x0C,
.usage = 0x01,
},
#endif
#ifdef USB_HID_REPORT_ID_SYS_CONTROL
{
.base = { .type = &usb_hid_device_type },
.report_buffer = sys_control_report_buffer,
@ -77,6 +98,29 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
.usage_page = 0x01,
.usage = 0x80,
},
#endif
#ifdef USB_HID_REPORT_ID_GAMEPAD
{
.base = { .type = &usb_hid_device_type },
.report_buffer = gamepad_report_buffer,
.endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_GAMEPAD,
.report_length = USB_HID_REPORT_LENGTH_GAMEPAD,
.usage_page = 0x01,
.usage = 0x05,
},
#endif
#ifdef USB_HID_REPORT_ID_DIGITIZER
{
.base = { .type = &usb_hid_device_type },
.report_buffer = digitizer_report_buffer,
.endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_DIGITIZER,
.report_length = USB_HID_REPORT_LENGTH_DIGITIZER,
.usage_page = 0x0D,
.usage = 0x02,
},
#endif
};
@ -86,9 +130,23 @@ mp_obj_tuple_t common_hal_usb_hid_devices = {
},
.len = USB_HID_NUM_DEVICES,
.items = {
#if USB_HID_NUM_DEVICES >= 1
(mp_obj_t) &usb_hid_devices[0],
#endif
#if USB_HID_NUM_DEVICES >= 2
(mp_obj_t) &usb_hid_devices[1],
#endif
#if USB_HID_NUM_DEVICES >= 3
(mp_obj_t) &usb_hid_devices[2],
#endif
#if USB_HID_NUM_DEVICES >= 4
(mp_obj_t) &usb_hid_devices[3],
#endif
#if USB_HID_NUM_DEVICES >= 5
(mp_obj_t) &usb_hid_devices[4],
#endif
#if USB_HID_NUM_DEVICES >= 6
(mp_obj_t) &usb_hid_devices[5],
#endif
}
};

View File

@ -91,7 +91,7 @@ uint8_t find_async_event_channel(void) {
#define EVSYS_SYNCH_NUM EVSYS_CHANNELS
#endif
uint8_t find_sync_event_channel(void) {
int8_t channel;
uint8_t channel;
for (channel = 0; channel < EVSYS_SYNCH_NUM; channel++) {
if (channel_free(channel)) {
break;
@ -145,6 +145,8 @@ void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generat
EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) |
EVSYS_CHANNEL_PATH_SYNCHRONOUS |
EVSYS_CHANNEL_EDGSEL_RISING_EDGE;
EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
EVSYS->Channel[channel].CHINTENSET.reg = EVSYS_CHINTENSET_EVD | EVSYS_CHINTENSET_OVR;
#endif
#ifdef SAMD21
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) |
@ -187,8 +189,25 @@ bool event_interrupt_active(uint8_t channel) {
// Only clear if we know its active, otherwise there is the possibility it becomes after we
// check but before we clear.
if (active) {
EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD;
EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
}
#endif
return active;
}
bool event_interrupt_overflow(uint8_t channel) {
bool overflow = false;
#ifdef SAMD21
if (channel > 7) {
uint8_t value = 1 << (channel - 7);
overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVRp8(value)) != 0;
} else {
uint8_t value = 1 << channel;
overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVR(value)) != 0;
}
#endif
#ifdef SAMD51
overflow = EVSYS->Channel[channel].CHINTFLAG.bit.OVR;
#endif
return overflow;
}

View File

@ -42,5 +42,6 @@ void connect_event_user_to_channel(uint8_t user, uint8_t channel);
void init_async_event_channel(uint8_t channel, uint8_t generator);
void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generator);
bool event_interrupt_active(uint8_t channel);
bool event_interrupt_overflow(uint8_t channel);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_EVENTS_H

View File

@ -32,6 +32,7 @@
#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL
#include "external_flash/common_commands.h"
#include "peripherals.h"
#include "shared_dma.h"
#include "atmel_start_pins.h"
@ -55,6 +56,8 @@ bool spi_flash_command(uint8_t command) {
}
bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) {
samd_peripherals_disable_and_clear_cache();
QSPI->INSTRCTRL.bit.INSTR = command;
QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI |
@ -63,6 +66,11 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
QSPI_INSTRFRAME_INSTREN |
QSPI_INSTRFRAME_DATAEN;
// Dummy read of INSTRFRAME needed to synchronize.
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
// and Example 4, page 998, section 37.6.8.5.
(volatile uint32_t) QSPI->INSTRFRAME.reg;
memcpy(response, (uint8_t *) QSPI_AHB, length);
QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER;
@ -71,20 +79,28 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
samd_peripherals_enable_cache();
return true;
}
bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
samd_peripherals_disable_and_clear_cache();
QSPI->INSTRCTRL.bit.INSTR = command;
QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI |
QSPI_INSTRFRAME_ADDRLEN_24BITS |
QSPI_INSTRFRAME_TFRTYPE_WRITE |
QSPI_INSTRFRAME_INSTREN;
QSPI_INSTRFRAME_INSTREN |
(data != NULL ? QSPI_INSTRFRAME_DATAEN : 0);
// Dummy read of INSTRFRAME needed to synchronize.
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
// and Example 4, page 998, section 37.6.8.5.
(volatile uint32_t) QSPI->INSTRFRAME.reg;
if (data != NULL) {
QSPI->INSTRFRAME.bit.DATAEN = true;
memcpy((uint8_t *) QSPI_AHB, data, length);
}
@ -94,6 +110,8 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
samd_peripherals_enable_cache();
return true;
}
@ -117,6 +135,8 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address) {
}
bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
samd_peripherals_disable_and_clear_cache();
QSPI->INSTRCTRL.bit.INSTR = CMD_PAGE_PROGRAM;
uint32_t mode = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI;
@ -137,10 +157,14 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
samd_peripherals_enable_cache();
return true;
}
bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
samd_peripherals_disable_and_clear_cache();
#ifdef EXTERNAL_FLASH_QSPI_DUAL
QSPI->INSTRCTRL.bit.INSTR = CMD_DUAL_READ;
uint32_t mode = QSPI_INSTRFRAME_WIDTH_DUAL_OUTPUT;
@ -167,6 +191,8 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
samd_peripherals_enable_cache();
return true;
}
@ -183,7 +209,7 @@ void spi_flash_init(void) {
// QSPI->BAUD.bit.BAUD = 32;
// Super fast, may be unreliable when Saleae is connected to high speed lines.
QSPI->BAUD.bit.BAUD = 2;
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY |
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | // Serial memory mode (map to QSPI_AHB)
QSPI_CTRLB_DATALEN_8BITS |
QSPI_CTRLB_CSMODE_LASTXFER;

84
ports/atmel-samd/i2s.c Normal file
View File

@ -0,0 +1,84 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "i2s.h"
#include "clocks.h"
#include "hpl/gclk/hpl_gclk_base.h"
#ifdef SAMD21
#include "hpl/pm/hpl_pm_base.h"
#endif
void turn_on_i2s(void) {
// Make sure the I2S peripheral is running so we can see if the resources we need are free.
#ifdef SAMD51
hri_mclk_set_APBDMASK_I2S_bit(MCLK);
// Connect the clock units to the 2mhz clock by default. They can't reset without it.
connect_gclk_to_peripheral(5, I2S_GCLK_ID_0);
connect_gclk_to_peripheral(5, I2S_GCLK_ID_1);
#endif
#ifdef SAMD21
_pm_enable_bus_clock(PM_BUS_APBC, I2S);
#endif
}
void i2s_set_enable(bool enable) {
while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
I2S->CTRLA.bit.ENABLE = enable;
while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
}
void i2s_set_clock_unit_enable(uint8_t clock_unit, bool enable) {
while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
I2S->CTRLA.vec.CKEN = 1 << clock_unit;
while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
}
void i2s_set_serializer_enable(uint8_t serializer, bool enable) {
#ifdef SAMD21
while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
if (enable) {
I2S->CTRLA.vec.SEREN = 1 << serializer;
} else {
I2S->CTRLA.vec.SEREN &= ~(1 << serializer);
}
while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
#endif
#ifdef SAMD51
if (serializer == 0) {
while (I2S->SYNCBUSY.bit.TXEN == 1) {}
I2S->CTRLA.bit.TXEN = enable;
while (I2S->SYNCBUSY.bit.TXEN == 1) {}
} else {
while (I2S->SYNCBUSY.bit.RXEN == 1) {}
I2S->CTRLA.bit.RXEN = enable;
while (I2S->SYNCBUSY.bit.RXEN == 1) {}
}
#endif
}

View File

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2017 by Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -24,13 +24,18 @@
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_I2S_H
#define MICROPY_INCLUDED_ATMEL_SAMD_I2S_H
#include <stdbool.h>
#include <stdint.h>
#include "include/sam.h"
void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
void turn_on_i2s(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
void i2s_set_enable(bool enable);
void i2s_set_clock_unit_enable(uint8_t clock, bool enable);
void i2s_set_serializer_enable(uint8_t serializer, bool enable);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_I2S_H

View File

@ -167,6 +167,7 @@ extern const struct _mp_obj_module_t math_module;
extern const struct _mp_obj_module_t os_module;
extern const struct _mp_obj_module_t random_module;
extern const struct _mp_obj_module_t rtc_module;
extern const struct _mp_obj_module_t samd_module;
extern const struct _mp_obj_module_t storage_module;
extern const struct _mp_obj_module_t struct_module;
extern const struct _mp_obj_module_t time_module;
@ -236,6 +237,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_rtc), (mp_obj_t)&rtc_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_samd),(mp_obj_t)&samd_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \

View File

@ -45,6 +45,13 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
gpio_toggle_pin_level(MICROPY_HW_LED_TX);
#endif
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
if (boot_output_file != NULL) {
UINT bytes_written = 0;
f_write(boot_output_file, str, len, &bytes_written);
}
#endif
usb_write(str, len);
}

View File

@ -42,4 +42,3 @@ uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate)
uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value) {
return PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY / (2 * (baud_reg_value + 1));
}

View File

@ -44,4 +44,4 @@ Sercom* sercom_insts[SERCOM_INST_NUM];
#include "samd51_peripherals.h"
#endif
#endif // MICROPY_INCLUDED_ATMEL_SAMD_PINS_H
#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H

View File

@ -0,0 +1,425 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "clocks.h"
#include "hpl_gclk_config.h"
#include "bindings/samd/Clock.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "py/runtime.h"
bool gclk_enabled(uint8_t gclk) {
common_hal_mcu_disable_interrupts();
// Explicitly do a byte write so the peripheral knows we're just wanting to read the channel
// rather than write to it.
*((uint8_t*) &GCLK->GENCTRL.reg) = gclk;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
bool enabled = GCLK->GENCTRL.bit.GENEN;
common_hal_mcu_enable_interrupts();
return enabled;
}
void disable_gclk(uint8_t gclk) {
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk);
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
}
void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) {
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(peripheral) | GCLK_CLKCTRL_GEN(gclk) | GCLK_CLKCTRL_CLKEN;
}
void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) {
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(peripheral) | GCLK_CLKCTRL_GEN(gclk);
}
void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) {
uint32_t divsel = 0;
if (gclk == 2 && divisor > 31) {
divsel = GCLK_GENCTRL_DIVSEL;
for (int i = 15; i > 4; i++) {
if (divisor & (1 << i)) {
divisor = i - 1;
break;
}
}
}
GCLK->GENDIV.reg = GCLK_GENDIV_ID(gclk) | GCLK_GENDIV_DIV(divisor);
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk) | GCLK_GENCTRL_SRC(source) | divsel | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN;
while (GCLK->STATUS.bit.SYNCBUSY != 0) {}
}
void disable_clock_generator(uint8_t gclk) {
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk);
while (GCLK->STATUS.bit.SYNCBUSY != 0) {}
}
static void init_clock_source_osc8m(void) {
// Preserve CALIB and FRANGE
SYSCTRL->OSC8M.bit.ONDEMAND = 0;
SYSCTRL->OSC8M.bit.PRESC = 3;
SYSCTRL->OSC8M.bit.ENABLE = 1;
while (!SYSCTRL->PCLKSR.bit.OSC8MRDY) {}
}
static void init_clock_source_osc32k(void) {
uint32_t calib = (*((uint32_t *)FUSES_OSC32K_CAL_ADDR) & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos;
SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) |
SYSCTRL_OSC32K_EN32K |
SYSCTRL_OSC32K_ENABLE;
while (!SYSCTRL->PCLKSR.bit.OSC32KRDY) {}
}
static void init_clock_source_xosc32k(void) {
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_EN32K |
SYSCTRL_XOSC32K_XTALEN |
SYSCTRL_XOSC32K_ENABLE;
while (!SYSCTRL->PCLKSR.bit.XOSC32KRDY) {}
}
static void init_clock_source_dfll48m(void) {
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) |
SYSCTRL_DFLLMUL_FSTEP(1) |
SYSCTRL_DFLLMUL_MUL(48000);
uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos;
if (coarse == 0x3f)
coarse = 0x1f;
SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) |
SYSCTRL_DFLLVAL_FINE(512);
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS |
SYSCTRL_DFLLCTRL_USBCRM |
SYSCTRL_DFLLCTRL_MODE |
SYSCTRL_DFLLCTRL_ENABLE;
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
while (GCLK->STATUS.bit.SYNCBUSY) {}
}
void clock_init(void)
{
init_clock_source_osc8m();
if (board_has_crystal())
init_clock_source_xosc32k();
else
init_clock_source_osc32k();
enable_clock_generator(0, GCLK_GENCTRL_SRC_DFLL48M_Val, 1);
enable_clock_generator(1, GCLK_GENCTRL_SRC_DFLL48M_Val, 150);
init_clock_source_dfll48m();
if (board_has_crystal())
enable_clock_generator(2, GCLK_GENCTRL_SRC_XOSC32K_Val, 32);
else
enable_clock_generator(2, GCLK_GENCTRL_SRC_OSC32K_Val, 32);
}
static bool clk_enabled(uint8_t clk) {
common_hal_mcu_disable_interrupts();
*((uint8_t*) &GCLK->CLKCTRL.reg) = clk;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
bool enabled = GCLK->CLKCTRL.bit.CLKEN;
common_hal_mcu_enable_interrupts();
return enabled;
}
static uint8_t clk_get_generator(uint8_t clk) {
common_hal_mcu_disable_interrupts();
*((uint8_t*) &GCLK->CLKCTRL.reg) = clk;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
uint8_t gen = GCLK->CLKCTRL.bit.GEN;
common_hal_mcu_enable_interrupts();
return gen;
}
static uint8_t generator_get_source(uint8_t gen) {
common_hal_mcu_disable_interrupts();
*((uint8_t*) &GCLK->GENCTRL.reg) = gen;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
uint8_t src = GCLK->GENCTRL.bit.SRC;
common_hal_mcu_enable_interrupts();
return src;
}
static bool osc_enabled(uint8_t index) {
switch (index) {
case GCLK_SOURCE_XOSC:
return SYSCTRL->XOSC.bit.ENABLE;
// TODO: GCLK_SOURCE_GCLKIN
// TODO: GCLK_SOURCE_GCLKGEN1
case GCLK_SOURCE_OSCULP32K:
return true;
case GCLK_SOURCE_OSC32K:
return SYSCTRL->OSC32K.bit.ENABLE;
case GCLK_SOURCE_XOSC32K:
return SYSCTRL->XOSC32K.bit.ENABLE;
case GCLK_SOURCE_OSC8M:
return SYSCTRL->OSC8M.bit.ENABLE;
case GCLK_SOURCE_DFLL48M:
return SYSCTRL->DFLLCTRL.bit.ENABLE;
case GCLK_SOURCE_DPLL96M:
return SYSCTRL->DPLLCTRLA.bit.ENABLE;
};
return false;
}
static uint32_t osc_get_frequency(uint8_t index) {
switch (index) {
case GCLK_SOURCE_XOSC:
return 0; // unknown 0.4-32MHz
// TODO: GCLK_SOURCE_GCLKIN
// TODO: GCLK_SOURCE_GCLKGEN1
case GCLK_SOURCE_OSCULP32K:
case GCLK_SOURCE_OSC32K:
case GCLK_SOURCE_XOSC32K:
return 32768;
case GCLK_SOURCE_OSC8M:
return 8000000;
case GCLK_SOURCE_DFLL48M:
return 48000000;
case GCLK_SOURCE_DPLL96M:
return 96000000;
}
return 0;
}
bool clock_get_enabled(uint8_t type, uint8_t index) {
if (type == 0)
return osc_enabled(index);
if (type == 1)
return clk_enabled(index);
if (type == 2)
return SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
return false;
}
bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) {
if (type == 1 && index <= 0x24 && clk_enabled(index)) {
*p_type = 0;
*p_index = generator_get_source(clk_get_generator(index));
return true;
}
if (type == 2 && index == 0) {
*p_type = 0;
*p_index = generator_get_source(0);
return true;
}
return false;
}
uint32_t clock_get_frequency(uint8_t type, uint8_t index) {
if (type == 0) {
return osc_get_frequency(index);
}
if (type == 1) {
if (!clk_enabled(index))
return 0;
uint8_t gen = clk_get_generator(index);
common_hal_mcu_disable_interrupts();
*((uint8_t*) &GCLK->GENCTRL.reg) = gen;
*((uint8_t*) &GCLK->GENDIV.reg) = gen;
while (GCLK->STATUS.bit.SYNCBUSY == 1) {}
uint8_t src = GCLK->GENCTRL.bit.SRC;
uint32_t div;
if (GCLK->GENCTRL.bit.DIVSEL) {
div = 1 << (GCLK->GENDIV.bit.DIV + 1);
} else {
div = GCLK->GENDIV.bit.DIV;
if (!div)
div = 1;
}
common_hal_mcu_enable_interrupts();
return osc_get_frequency(src) / div;
}
if (type == 2 && index == 0) {
return clock_get_frequency(0, generator_get_source(0)) / SysTick->LOAD;
}
return 0;
}
uint32_t clock_get_calibration(uint8_t type, uint8_t index) {
if (type == 0) {
switch (index) {
case GCLK_SOURCE_OSCULP32K:
return SYSCTRL->OSCULP32K.bit.CALIB;
case GCLK_SOURCE_OSC32K:
return SYSCTRL->OSC32K.bit.CALIB;
case GCLK_SOURCE_OSC8M:
return SYSCTRL->OSC8M.bit.CALIB;
};
}
if (type == 2 && index == 0) {
return SysTick->LOAD + 1;
}
return 0;
}
int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
if (type == 0) {
switch (index) {
case GCLK_SOURCE_OSCULP32K:
if (val > 0x1f)
return -1;
SYSCTRL->OSCULP32K.bit.CALIB = val;
return 0;
case GCLK_SOURCE_OSC32K:
if (val > 0x7f)
return -1;
SYSCTRL->OSC32K.bit.CALIB = val;
return 0;
case GCLK_SOURCE_OSC8M:
if (val > 0xfff)
return -1;
SYSCTRL->OSC8M.bit.CALIB = val;
return 0;
};
}
if (type == 2 && index == 0) {
if (val < 0x1000 || val > 0x1000000)
return -1;
SysTick->LOAD = val - 1;
return 0;
}
return -2; // calibration is read only
}
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_SOURCE(XOSC);
CLOCK_SOURCE(GCLKIN);
CLOCK_SOURCE(GCLKGEN1);
CLOCK_SOURCE(OSCULP32K);
#endif
CLOCK_SOURCE(OSC32K);
CLOCK_SOURCE(XOSC32K);
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_SOURCE(OSC8M);
CLOCK_SOURCE(DFLL48M);
CLOCK_SOURCE(DPLL96M);
CLOCK_GCLK_(SYSCTRL, DFLL48);
CLOCK_GCLK_(SYSCTRL, FDPLL);
CLOCK_GCLK_(SYSCTRL, FDPLL32K);
CLOCK_GCLK(WDT);
#endif
CLOCK_GCLK(RTC);
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_GCLK(EIC);
CLOCK_GCLK(USB);
CLOCK_GCLK_(EVSYS, 0);
CLOCK_GCLK_(EVSYS, 1);
CLOCK_GCLK_(EVSYS, 2);
CLOCK_GCLK_(EVSYS, 3);
CLOCK_GCLK_(EVSYS, 4);
CLOCK_GCLK_(EVSYS, 5);
CLOCK_GCLK_(EVSYS, 6);
CLOCK_GCLK_(EVSYS, 7);
CLOCK_GCLK_(EVSYS, 8);
CLOCK_GCLK_(EVSYS, 9);
CLOCK_GCLK_(EVSYS, 10);
CLOCK_GCLK_(EVSYS, 11);
CLOCK(SERCOMx_SLOW, 1, 19);
CLOCK_GCLK_(SERCOM0, CORE);
CLOCK_GCLK_(SERCOM1, CORE);
CLOCK_GCLK_(SERCOM2, CORE);
CLOCK_GCLK_(SERCOM3, CORE);
CLOCK_GCLK_(SERCOM4, CORE);
CLOCK_GCLK_(SERCOM5, CORE);
CLOCK(TCC0_TCC1, 1, 26);
CLOCK(TCC2_TCC3, 1, 27);
CLOCK(TC4_TC5, 1, 28);
CLOCK(TC6_TC7, 1, 29);
CLOCK_GCLK(ADC);
CLOCK_GCLK_(AC, DIG);
CLOCK_GCLK_(AC, ANA);
CLOCK_GCLK(DAC);
CLOCK_GCLK(PTC);
CLOCK_GCLK_(I2S, 0);
CLOCK_GCLK_(I2S, 1);
CLOCK(SYSTICK, 2, 0);
#endif
STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = {
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_ENTRY(XOSC),
CLOCK_ENTRY(GCLKIN),
CLOCK_ENTRY(GCLKGEN1),
CLOCK_ENTRY(OSCULP32K),
#endif
CLOCK_ENTRY(OSC32K),
CLOCK_ENTRY(XOSC32K),
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_ENTRY(OSC8M),
CLOCK_ENTRY(DFLL48M),
CLOCK_ENTRY(DPLL96M),
CLOCK_ENTRY_(SYSCTRL, DFLL48),
CLOCK_ENTRY_(SYSCTRL, FDPLL),
CLOCK_ENTRY_(SYSCTRL, FDPLL32K),
CLOCK_ENTRY(WDT),
#endif
CLOCK_ENTRY(RTC),
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_ENTRY(EIC),
CLOCK_ENTRY(USB),
CLOCK_ENTRY_(EVSYS, 0),
CLOCK_ENTRY_(EVSYS, 1),
CLOCK_ENTRY_(EVSYS, 2),
CLOCK_ENTRY_(EVSYS, 3),
CLOCK_ENTRY_(EVSYS, 4),
CLOCK_ENTRY_(EVSYS, 5),
CLOCK_ENTRY_(EVSYS, 6),
CLOCK_ENTRY_(EVSYS, 7),
CLOCK_ENTRY_(EVSYS, 8),
CLOCK_ENTRY_(EVSYS, 9),
CLOCK_ENTRY_(EVSYS, 10),
CLOCK_ENTRY_(EVSYS, 11),
CLOCK_ENTRY(SERCOMx_SLOW),
CLOCK_ENTRY_(SERCOM0, CORE),
CLOCK_ENTRY_(SERCOM1, CORE),
CLOCK_ENTRY_(SERCOM2, CORE),
CLOCK_ENTRY_(SERCOM3, CORE),
CLOCK_ENTRY_(SERCOM4, CORE),
CLOCK_ENTRY_(SERCOM5, CORE),
CLOCK_ENTRY(TCC0_TCC1),
CLOCK_ENTRY(TCC2_TCC3),
CLOCK_ENTRY(TC4_TC5),
CLOCK_ENTRY(TC6_TC7),
CLOCK_ENTRY(ADC),
CLOCK_ENTRY_(AC, DIG),
CLOCK_ENTRY_(AC, ANA),
CLOCK_ENTRY(DAC),
CLOCK_ENTRY(PTC),
CLOCK_ENTRY_(I2S, 0),
CLOCK_ENTRY_(I2S, 1),
CLOCK_ENTRY(SYSTICK),
#endif
};
MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);

View File

@ -24,9 +24,11 @@
* THE SOFTWARE.
*/
#include "hal/include/hal_adc_sync.h"
#include "hpl/gclk/hpl_gclk_base.h"
#include "hpl/pm/hpl_pm_base.h"
// The clock initializer values are rather random, so we need to put them in
// tables for lookup. We can't compute them.
@ -91,3 +93,21 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1 || clock_pad == 3;
}
// Do initialization and calibration setup needed for any use of the ADC.
// The reference and resolution should be set by the caller.
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
// Turn the clocks on.
_pm_enable_bus_clock(PM_BUS_APBC, ADC);
_gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
adc_sync_init(adc, instance, (void *)NULL);
// Load the factory calibration
hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos);
// Bits 7:5
uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
// Bits 4:0
linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity);
}

View File

@ -28,9 +28,11 @@
#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
#include "include/sam.h"
#include "hal/include/hal_adc_sync.h"
void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H

View File

@ -0,0 +1,86 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "clocks.h"
#include "hpl_gclk_config.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "py/runtime.h"
bool gclk_enabled(uint8_t gclk) {
return GCLK->GENCTRL[gclk].bit.GENEN;
}
void disable_gclk(uint8_t gclk) {
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
GCLK->GENCTRL[gclk].bit.GENEN = false;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
}
void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) {
GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk);
while(GCLK->SYNCBUSY.reg != 0) {}
}
void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) {
GCLK->PCHCTRL[peripheral].reg = 0;
}
void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) {
GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | GCLK_GENCTRL_GENEN;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
}
void disable_clock_generator(uint8_t gclk) {
GCLK->GENCTRL[gclk].reg = 0;
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
}
bool clock_get_enabled(uint8_t type, uint8_t index) {
return false;
}
bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) {
return false;
}
uint32_t clock_get_frequency(uint8_t type, uint8_t index) {
return 0;
}
uint32_t clock_get_calibration(uint8_t type, uint8_t index) {
return 0;
}
int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
return -2;
}
STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = {
};
MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "hal/include/hal_adc_sync.h"
#include "hpl/gclk/hpl_gclk_base.h"
#include "hri/hri_mclk_d51.h"
@ -130,3 +131,47 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1;
}
// Do initialization and calibration setup needed for any use of the ADC.
// The reference and resolution should be set by the caller.
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
// Turn the clocks on.
if (instance == ADC0) {
hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
} else if (instance == ADC1) {
hri_mclk_set_APBDMASK_ADC1_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
}
adc_sync_init(adc, instance, (void *)NULL);
// SAMD51 has a CALIB register but doesn't have documented fuses for them.
uint8_t biasrefbuf;
uint8_t biasr2r;
uint8_t biascomp;
if (instance == ADC0) {
biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
} else {
biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
}
hri_adc_write_CALIB_BIASREFBUF_bf(instance, biasrefbuf);
hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r);
hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp);
}
// Turn off cache and invalidate all data in it.
void samd_peripherals_disable_and_clear_cache(void) {
CMCC->CTRL.bit.CEN = 0;
while (CMCC->SR.bit.CSTS) {}
CMCC->MAINT0.bit.INVALL = 1;
}
// Enable cache
void samd_peripherals_enable_cache(void) {
CMCC->CTRL.bit.CEN = 1;
}

Some files were not shown because too many files have changed in this diff Show More