Merge branch 'master' into usbboot
9
.gitmodules
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
22
README.rst
@ -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
|
||||
------------
|
||||
|
@ -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.
|
||||
|
@ -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`.
|
@ -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.
|
@ -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.
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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) },
|
||||
|
@ -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) },
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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*/;
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
1
frozen/Adafruit_CircuitPython_CircuitPlayground
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit a669915237545638c64f89400f368a91c408cd5d
|
1
frozen/Adafruit_CircuitPython_HID
Submodule
@ -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
|
Before Width: | Height: | Size: 415 B |
@ -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.
|
371
logo/adafruit_blinka_angles-back.svg
Normal file
After Width: | Height: | Size: 55 KiB |
416
logo/adafruit_blinka_angles-front.svg
Normal file
After Width: | Height: | Size: 90 KiB |
5876
logo/adafruit_blinka_angles-left.svg
Normal file
After Width: | Height: | Size: 600 KiB |
481
logo/adafruit_blinka_angles-right.svg
Normal file
After Width: | Height: | Size: 75 KiB |
621
logo/adafruit_blinka_computer.svg
Normal file
After Width: | Height: | Size: 86 KiB |
555
logo/adafruit_circuit_python_ourboros_color.svg
Normal file
After Width: | Height: | Size: 107 KiB |
96
logo/adafruit_circuit_python_ouroboros_logo_final.svg
Normal file
After Width: | Height: | Size: 16 KiB |
606
logo/adafruit_circuit_python_sitting_color.svg
Normal file
After Width: | Height: | Size: 165 KiB |
77
logo/adafruit_circuit_python_stacked_lockup_logo_final.svg
Normal file
After Width: | Height: | Size: 9.8 KiB |
636
logo/awesome_circuitpython.svg
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
logo/blinka_colorform-cooking.png
Normal file
After Width: | Height: | Size: 12 KiB |
1085
logo/blinka_colorform-cooking.svg
Normal file
After Width: | Height: | Size: 322 KiB |
886
logo/blinka_colorform-first-birthday.svg
Normal file
After Width: | Height: | Size: 86 KiB |
1022
logo/blinka_colorform-painting.svg
Normal file
After Width: | Height: | Size: 183 KiB |
906
logo/blinka_colorform-reading.svg
Normal file
After Width: | Height: | Size: 114 KiB |
1037
logo/blinka_colorform-singing.svg
Normal file
After Width: | Height: | Size: 309 KiB |
965
logo/blinka_colorform-telescope.svg
Normal file
After Width: | Height: | Size: 98 KiB |
1217
logo/blinka_colorform-test_tubes.svg
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
logo/logo.jpg
Before Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 563 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 172 KiB |
@ -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 |
@ -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
@ -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
|
||||
|
@ -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)\
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
174
ports/atmel-samd/bindings/samd/Clock.c
Normal 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,
|
||||
};
|
77
ports/atmel-samd/bindings/samd/Clock.h
Normal 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
|
72
ports/atmel-samd/bindings/samd/__init__.c
Normal 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,
|
||||
};
|
@ -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
|
||||
|
@ -46,3 +46,5 @@
|
||||
GD25Q16C
|
||||
|
||||
#include "external_flash/external_flash.h"
|
||||
|
||||
#define BOARD_HAS_CRYSTAL 1
|
||||
|
@ -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"
|
||||
|
@ -47,3 +47,5 @@
|
||||
GD25Q16C
|
||||
|
||||
#include "external_flash/external_flash.h"
|
||||
|
||||
#define BOARD_HAS_CRYSTAL 1
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
}
|
@ -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
|
@ -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 }, \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
425
ports/atmel-samd/samd21_clocks.c
Normal 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);
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
86
ports/atmel-samd/samd51_clocks.c
Normal 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);
|
@ -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;
|
||||
}
|
||||
|