kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
Squashed commit of the following:
commitmasterfcaf88779d
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sun Jan 7 12:22:16 2024 +0000 (read partition table; preparation for future file system upload script) commit9c7491d389
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sat Jan 6 23:51:44 2024 +0000 better license info on external libraries commit12ede0e81d
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Mon Dec 18 19:12:36 2023 +0100 esp32 version update commit1687117bec
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Dec 12 19:36:47 2023 +0000 tentative fix of M20 misclassification as M10 (untested) commitff5aec544e
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Dec 12 19:27:23 2023 +0000 tentative fix of M20 misclassification as M10 (untested) commit2b88e072ac
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sun Dec 10 16:11:51 2023 +0000 reduce image size with platformio builds, make it (almost) same as for Arduino builds commit8ee071de35
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sun Dec 3 22:45:44 2023 +0000 T-Beam 1.2: charge battery fix commit681f436767
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sun Dec 3 16:00:13 2023 +0000 newer library versions commit6551fa0b5d
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Fri Nov 10 09:43:02 2023 +0000 chasemapper: id format with type, as in auto_rx commite5c2e2db77
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Aug 29 20:15:53 2023 +0000 more explanation in About tabw commitaec4d39867
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Aug 29 01:00:53 2023 +0000 fix travis build / wget issue with github commitd7026abb7b
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Aug 29 00:22:48 2023 +0000 fix bug in eph config editor commit6c98891b63
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Mon Aug 28 12:35:06 2023 +0000 AXP2101: add missing irq handler commitc1231a11d4
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Mon Aug 28 12:02:36 2023 +0000 bugfix (APX2101 related) commit86263a7ad1
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Mon Aug 28 10:13:39 2023 +0000 fix commit35156948cb
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Mon Aug 28 10:07:09 2023 +0000 yet another fix for ftp eph commit3ddbebf2fc
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sat Aug 26 23:33:33 2023 +0000 untested axp2101 support commit60e97d917b
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sat Aug 26 17:19:38 2023 +0000 pmu reorg, preparing for axp2101 commit082b6ccdf5
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Tue Aug 22 22:28:37 2023 +0000 fix posInfo bug; aprs timeout convert seconds to ms commitdeec0d362f
Author: Hansi, dl9rdz <dl9rdz@darc.de> Date: Sun Jul 9 12:10:53 2023 +0200 (sync with master) some code reorganization, preliminary SD card code (not active) APRS timeout added
rodzic
6cf330b143
commit
5ce1d36b97
20
.travis.yml
20
.travis.yml
|
@ -1,3 +1,9 @@
|
|||
# safelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- devel
|
||||
|
||||
language: c
|
||||
dist: focal
|
||||
os: linux
|
||||
|
@ -17,20 +23,20 @@ before_install:
|
|||
- tar xf arduino-1.8.16-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.16 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
- wget https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip
|
||||
- wget --secure-protocol=TLSv1_2 https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip
|
||||
- unzip master.zip
|
||||
- rm master.zip
|
||||
- sudo mv ESPAsyncWebServer-master /usr/local/share/arduino/libraries/ESPAsyncWebServer
|
||||
- wget https://github.com/me-no-dev/AsyncTCP/archive/master.zip
|
||||
- wget --secure-protocol=TLSv1_2 https://github.com/me-no-dev/AsyncTCP/archive/master.zip
|
||||
- unzip master.zip
|
||||
- rm master.zip
|
||||
- sudo mv AsyncTCP-master /usr/local/share/arduino/libraries/AsyncTCP
|
||||
- wget https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/download/1.0/ESP32FS-1.0.zip
|
||||
- wget https://github.com/lewisxhe/AXP202X_Library/archive/refs/tags/V1.1.3.zip
|
||||
- wget --secure-protocol=TLSv1_2 https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/download/1.0/ESP32FS-1.0.zip
|
||||
- wget --secure-protocol=TLSv1_2 https://github.com/lewisxhe/AXP202X_Library/archive/refs/tags/V1.1.3.zip
|
||||
- unzip V1.1.3.zip
|
||||
- sudo mv AXP202X_Library-1.1.3 /usr/local/share/arduino/libraries/
|
||||
|
||||
- wget https://github.com/dx168b/async-mqtt-client/archive/master.zip
|
||||
- wget --secure-protocol=TLSv1_2 https://github.com/dx168b/async-mqtt-client/archive/master.zip
|
||||
- unzip master.zip
|
||||
- rm master.zip
|
||||
- sudo mv async-mqtt-client-master /usr/local/share/arduino/libraries/
|
||||
|
@ -53,9 +59,9 @@ install:
|
|||
- arduino --pref "build.path=$PWD/build" --save-prefs
|
||||
- arduino --install-boards esp32:esp32:1.0.6 --save-prefs
|
||||
- ln -s $PWD/libraries/SondeLib /usr/local/share/arduino/libraries/SondeLib
|
||||
- arduino --install-library "U8g2:2.29.11"
|
||||
- arduino --install-library "U8g2:2.34.22"
|
||||
- arduino --install-library "MicroNMEA"
|
||||
- arduino --install-library "GFX Library for Arduino:1.1.5"
|
||||
- arduino --install-library "GFX Library for Arduino:1.2.9"
|
||||
script:
|
||||
- arduino --board esp32:esp32:t-beam --verify $PWD/RX_FSK/RX_FSK.ino
|
||||
- ESPPATH=`arduino --get-pref runtime.tools.xtensa-esp32-elf-gcc.path`
|
||||
|
|
|
@ -1,11 +1,51 @@
|
|||
GPL License Exceptions:
|
||||
GPL License Exceptions
|
||||
|
||||
- The SX1278FSK library is based on
|
||||
Code in the repository:
|
||||
|
||||
- The SX1278FSK library (src/SX1278FSK.cpp) is based on
|
||||
https://github.com/pdelmo/lora_shield_arduino.git
|
||||
and licensed under
|
||||
GNU Lesser General Public License, version 2.1 (SPDX short identifier: LGPL-2.1)
|
||||
|
||||
- Leaflet sidebar v2 plugin is (c) 2013 Tobias Bieniek based on
|
||||
https://github.com/Turbo87/sidebar-v2/
|
||||
and licensed under
|
||||
MIT License
|
||||
- General purpose Reed-Solomon decoder for 8-bit symbols or less
|
||||
Copyright 2003 Phil Karn, KA9Q
|
||||
May be used under the terms of the GNU Lesser General Public License (LGPL) - lgpl-2.1.txt
|
||||
|
||||
- some of the decoder code is more or less loosly inspired by
|
||||
* oe5dxl aprs toolchain (http://oe5dxl.hamspirit.at:8025), licensed under GNU GPL (gpl-3.0.txt)
|
||||
* Zilogs RS decoder (https://github.com/rs1729/RS), licensed under GNU GPL (gpl-3.0.txt)
|
||||
|
||||
- Fonts in src/fonts (FreeMono*, FreeSans*, Picopixel) taken from Adafruit-GFX-Library
|
||||
licensed under BSD License
|
||||
Font src/fonts/Terminal11x16.h taken from https://github.com/Nkawu/TFT_22_ILI9225/
|
||||
licensed under GPL-3.0
|
||||
|
||||
External libraries used by the project:
|
||||
|
||||
- Espressif 32: development platform for PlatformIO
|
||||
https://github.com/platformio/platform-espressif32
|
||||
licensed under Apache-2.0 licsense - apache.txt
|
||||
|
||||
- U8glib library for monochrome displays, version 2
|
||||
https://github.com/olikraus/u8g2
|
||||
licensed under the new-bsd license (two-clause bsd license) - LICENSE-u8g2.txt
|
||||
|
||||
- MicroNMEA - A compact Arduino library to parse NMEA sentences
|
||||
https://github.com/stevemarple/MicroNMEA
|
||||
licsensed under LGPL-2.1 license - lgpl-2.1.txt
|
||||
|
||||
- ESPAsyncWebServer
|
||||
see https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/src/ESPAsyncWebServer.h#L7-L19
|
||||
licsensed under LGPL-2.1 license - lgpl-2.1.txt
|
||||
|
||||
- Arduino GFX developing for various color displays
|
||||
https://github.com/moononournation/Arduino_GFX
|
||||
licensed under BSD License - LICENSE-Arduino_GFX.txt
|
||||
|
||||
- asynchronous MQTT client implementation
|
||||
https://github.com/dx168b/async-mqtt-client
|
||||
licensed under MIT license - LICENSE-mqtt.txt
|
||||
|
||||
- Time library for Arduino
|
||||
https://github.com/PaulStoffregen/Time
|
||||
licensed under LGPL-2.1 licsense - lgpl-2.1txt
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012 Adafruit Industries. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marvin Roger
|
||||
|
||||
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.
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
The U8g2lib code (https://github.com/olikraus/u8g2) is licensed under the terms of
|
||||
the new-bsd license (two-clause bsd license).
|
||||
See also: http://www.opensource.org/licenses/bsd-license.php
|
||||
|
||||
Fonts are licensed under different conditions.
|
||||
See
|
||||
https://github.com/olikraus/u8g2/wiki/fntgrp
|
||||
for detailed information on the licensing conditions for each font.
|
||||
|
||||
The example code in sys/raspi_gpio/hal will use the bcm2835 lib from Mike McCauley
|
||||
which is licensed under GPL V3: http://www.airspayce.com/mikem/bcm2835/
|
||||
|
||||
============ X11 Fonts COUR, HELV, NCEN, TIM, SYMB ============
|
||||
|
||||
For fonts derived from the following files, the license below applies.
|
||||
COURB08.BDF COURB10.BDF COURB12.BDF COURB14.BDF COURB18.BDF
|
||||
COURB24.BDF COURR08.BDF COURR10.BDF COURR12.BDF COURR14.BDF
|
||||
COURR18.BDF COURR24.BDF HELVB08.BDF HELVB10.BDF HELVB12.BDF HELVB14.BDF
|
||||
HELVB18.BDF HELVB24.BDF HELVR08.BDF HELVR10.BDF HELVR12.BDF HELVR14.BDF
|
||||
HELVR18.BDF HELVR24.BDF NCENB08.BDF NCENB10.BDF NCENB12.BDF
|
||||
NCENB14.BDF NCENB18.BDF NCENB24.BDF NCENR08.BDF NCENR10.BDF
|
||||
NCENR12.BDF NCENR14.BDF NCENR18.BDF NCENR24.BDF SYMB08.BDF SYMB10.BDF
|
||||
SYMB12.BDF SYMB14.BDF SYMB18.BDF SYMB24.BDF TIMB08.BDF TIMB10.BDF
|
||||
TIMB12.BDF TIMB14.BDF TIMB18.BDF TIMB24.BDF TIMR08.BDF TIMR10.BDF
|
||||
TIMR12.BDF TIMR14.BDF TIMR18.BDF TIMR24.BDF
|
||||
|
||||
Copyright 1984-1989, 1994 Adobe Systems Incorporated.
|
||||
Copyright 1988, 1994 Digital Equipment Corporation.
|
||||
|
||||
Adobe is a trademark of Adobe Systems Incorporated which may be
|
||||
registered in certain jurisdictions.
|
||||
Permission to use these trademarks is hereby granted only in
|
||||
association with the images described in this file.
|
||||
|
||||
Permission to use, copy, modify, distribute and sell this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notices appear in all
|
||||
copies and that both those copyright notices and this permission
|
||||
notice appear in supporting documentation, and that the names of
|
||||
Adobe Systems and Digital Equipment Corporation not be used in
|
||||
advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission. Adobe Systems and
|
||||
Digital Equipment Corporation make no representations about the
|
||||
suitability of this software for any purpose. It is provided "as
|
||||
is" without express or implied warranty.
|
||||
|
||||
|
||||
============ BSD License for U8g2lib Code ============
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
Plik diff jest za duży
Load Diff
|
@ -42,6 +42,7 @@ var cfgs = [
|
|||
[ "axudp.port", "AXUDP port"],
|
||||
[ "axudp.highrate", "Rate limit"],
|
||||
[ "tcp.active", "APRS TCP active"],
|
||||
[ "tcp.timeout", "APRS TCP timeout [s] (0=off, 25=on)"],
|
||||
[ "tcp.host", "APRS TCP host"],
|
||||
[ "tcp.port", "APRS TCP port"],
|
||||
[ "tcp.highrate", "Rate limit"],
|
||||
|
|
|
@ -15,6 +15,7 @@ document.addEventListener("DOMContentLoaded", function(){
|
|||
fetch('live.json')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.gps===undefined) { data.gps={} };
|
||||
console.log(data.gps.lat, data.gps.lon, data.sonde.ser);
|
||||
if( (data.sonde.ser||'')=='' && !(data.gps.lat===undefined) ) {
|
||||
urlarg = maps[maptype][2](data.gps.lat, data.gps.lon);
|
||||
|
|
|
@ -2,12 +2,17 @@
|
|||
// Configuration flags for including/excluding fuctionality from the compiled binary
|
||||
// set flag to 0 for exclude/1 for include
|
||||
|
||||
/* data feed to sondehubv2 */
|
||||
/* needs about 4k4 code, 200b data, 200b stack, 200b heap */
|
||||
// Selection of data output connectors to be included in firmware
|
||||
// APRS includes AXUDP (e.g. for aprsmap) and APRS-IS (TCP) (e.g. for wettersonde.net, radiosondy.info)
|
||||
#define FEATURE_SONDEHUB 1
|
||||
|
||||
#define FEATURE_CHASEMAPPER 1
|
||||
#define FEATURE_MQTT 1
|
||||
#define FEATURE_SDCARD 0
|
||||
#define FEATURE_APRS 1
|
||||
|
||||
|
||||
// Additional optional components
|
||||
#define FEATURE_RS92 1
|
||||
|
||||
/* Most recent version support fonts in a dedicated flash parition "fonts".
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef _CHASEMAPPER_H
|
||||
#define _CHASEMAPPER_H
|
||||
|
||||
#include "Sonde.h"
|
||||
//#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <time.h>
|
||||
class Chasemapper {
|
||||
public:
|
||||
static int send(WiFiUDP &udb, SondeInfo *si);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2,10 +2,10 @@
|
|||
#include <U8x8lib.h>
|
||||
#include <U8g2lib.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <axp20x.h>
|
||||
#include <MicroNMEA.h>
|
||||
#include "Display.h"
|
||||
#include "Sonde.h"
|
||||
#include "pmu.h"
|
||||
|
||||
int readLine(Stream &stream, char *buffer, int maxlen);
|
||||
|
||||
|
@ -22,8 +22,7 @@ extern const char *version_id;
|
|||
|
||||
extern Sonde sonde;
|
||||
|
||||
extern AXP20X_Class axp;
|
||||
extern bool axp192_found;
|
||||
extern PMU *pmu;
|
||||
extern SemaphoreHandle_t axpSemaphore;
|
||||
|
||||
extern xSemaphoreHandle globalLock;
|
||||
|
@ -33,8 +32,6 @@ extern xSemaphoreHandle globalLock;
|
|||
} while (xSemaphoreTake(globalLock, portMAX_DELAY) != pdPASS)
|
||||
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(globalLock)
|
||||
|
||||
struct GpsPos gpsPos;
|
||||
|
||||
//SPIClass spiDisp(HSPI);
|
||||
|
||||
byte myIP_tiles[8*11];
|
||||
|
@ -1670,13 +1667,14 @@ void Display::drawGPS(DispEntry *de) {
|
|||
void Display::drawBatt(DispEntry *de) {
|
||||
float val;
|
||||
char buf[30];
|
||||
if (!axp192_found) {
|
||||
if (!pmu) {
|
||||
if (sonde.config.batt_adc<0) return;
|
||||
switch (de->extra[0])
|
||||
{
|
||||
case 'V':
|
||||
val = (float)(analogRead(sonde.config.batt_adc)) / 4095 * 2 * 3.3 * 1.1;
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra + 1);
|
||||
Serial.printf("Batt: %s", buf);
|
||||
break;
|
||||
default:
|
||||
*buf = 0;
|
||||
|
@ -1684,51 +1682,67 @@ void Display::drawBatt(DispEntry *de) {
|
|||
rdis->setFont(de->fmt);
|
||||
drawString(de, buf);
|
||||
} else {
|
||||
*buf = 0;
|
||||
xSemaphoreTake( axpSemaphore, portMAX_DELAY );
|
||||
switch(de->extra[0]) {
|
||||
case 'S':
|
||||
if(!axp.isBatteryConnect()) {
|
||||
if(axp.isVBUSPlug()) { strcpy(buf, "U"); }
|
||||
if(!pmu->isBatteryConnected()) {
|
||||
if(pmu->isVbusIn()) { strcpy(buf, "U"); }
|
||||
else { strcpy(buf, "N"); } // no battary
|
||||
}
|
||||
else if (axp.isChargeing()) { strcpy(buf, "C"); } // charging
|
||||
else if (pmu->isCharging()) { strcpy(buf, "C"); } // charging
|
||||
else { strcpy(buf, "B"); } // battery, but not charging
|
||||
Serial.printf("Battery: %s\n", buf);
|
||||
break;
|
||||
case 'V':
|
||||
val = axp.getBattVoltage();
|
||||
val = pmu->getBattVoltage();
|
||||
snprintf(buf, 30, "%.2f%s", val/1000, de->extra+1);
|
||||
Serial.printf("Vbatt: %s\n", buf);
|
||||
break;
|
||||
case 'C':
|
||||
val = axp.getBattChargeCurrent();
|
||||
}
|
||||
if(pmu->type==TYPE_AXP192) {
|
||||
switch(de->extra[0]) {
|
||||
case 'C':
|
||||
val = pmu->getBattChargeCurrent();
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
|
||||
Serial.printf("Icharge: %s\n", buf);
|
||||
break;
|
||||
case 'D':
|
||||
val = axp.getBattDischargeCurrent();
|
||||
case 'D':
|
||||
val = pmu->getBattDischargeCurrent();
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
|
||||
Serial.printf("Idischarge: %s\n", buf);
|
||||
break;
|
||||
case 'U':
|
||||
case 'U':
|
||||
if(sonde.config.type == TYPE_M5_CORE2) {
|
||||
val = axp.getAcinVoltage();
|
||||
val = pmu->getAcinVoltage();
|
||||
} else {
|
||||
val = axp.getVbusVoltage();
|
||||
val = pmu->getVbusVoltage();
|
||||
}
|
||||
snprintf(buf, 30, "%.2f%s", val/1000, de->extra+1);
|
||||
Serial.printf("Vbus: %s\n", buf);
|
||||
break;
|
||||
case 'I':
|
||||
case 'I':
|
||||
if(sonde.config.type == TYPE_M5_CORE2) {
|
||||
val = axp.getAcinCurrent();
|
||||
val = pmu->getAcinCurrent();
|
||||
} else {
|
||||
val = axp.getVbusCurrent();
|
||||
val = pmu->getVbusCurrent();
|
||||
}
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
|
||||
Serial.printf("Ibus: %s\n", buf);
|
||||
break;
|
||||
case 'T':
|
||||
val = axp.getTemp(); // fixed in newer versions of libraray: -144.7 no longer needed here!
|
||||
case 'T':
|
||||
val = pmu->getTemperature();
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
|
||||
Serial.printf("temp: %s\n", buf);
|
||||
break;
|
||||
default:
|
||||
*buf=0;
|
||||
}
|
||||
}
|
||||
} else if (pmu->type == TYPE_AXP2101) {
|
||||
*buf = 0;
|
||||
if(de->extra[0]=='T') {
|
||||
val = pmu->getTemperature();
|
||||
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive( axpSemaphore );
|
||||
rdis->setFont(de->fmt);
|
||||
drawString(de, buf);
|
||||
|
|
|
@ -9,18 +9,7 @@
|
|||
#include <U8x8lib.h>
|
||||
#include <SPIFFS.h>
|
||||
|
||||
struct GpsPos {
|
||||
double lat;
|
||||
double lon;
|
||||
int alt;
|
||||
int course;
|
||||
float speed;
|
||||
int sat;
|
||||
int accuracy;
|
||||
int hdop;
|
||||
int valid;
|
||||
};
|
||||
extern struct GpsPos gpsPos;
|
||||
#include "posinfo.h"
|
||||
|
||||
#define WIDTH_AUTO 9999
|
||||
struct DispEntry {
|
||||
|
|
|
@ -304,6 +304,9 @@ int M10M20::decodeframeM10(uint8_t *data) {
|
|||
Serial.println("Decoding...");
|
||||
//SondeInfo *si = sonde.si();
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
// Set type info to M10
|
||||
memcpy(si->typestr, "M10 ", 5);
|
||||
si->subtype = 1; // subtype 1: M10
|
||||
|
||||
// Its a M10
|
||||
// getid...
|
||||
|
@ -441,7 +444,7 @@ void M10M20::processM10data(uint8_t dt)
|
|||
rxsearching = false;
|
||||
rxbitc = 0;
|
||||
rxp = 0;
|
||||
isM20 = false;
|
||||
//isM20 = false;
|
||||
headerDetected = 1;
|
||||
#if 1
|
||||
int rssi=sx1278.getRSSI();
|
||||
|
@ -463,17 +466,17 @@ void M10M20::processM10data(uint8_t dt)
|
|||
// 64 9F 20 => M10
|
||||
// 64 49 0x => M10 (?) -- not used here
|
||||
// 45 20 7x => M20
|
||||
if(rxp==2 && dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; }
|
||||
if(rxp==2) {
|
||||
// Update: change type only if valid type information in received data
|
||||
if(dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; }
|
||||
else if(/*dataptr[0]==0x64 &&*/ dataptr[1]==0x9F) { isM20 = false; }
|
||||
}
|
||||
if(isM20) {
|
||||
memcpy(sonde.si()->d.typestr, "M20 ", 5);
|
||||
sonde.si()->d.subtype = 2;
|
||||
if(rxp>=M20_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeM20(dataptr);
|
||||
}
|
||||
} else {
|
||||
memcpy(sonde.si()->d.typestr, "M10 ", 5);
|
||||
sonde.si()->d.subtype = 1;
|
||||
if(rxp>=M10_FRAMELEN) {
|
||||
rxsearching = true;
|
||||
haveNewFrame = decodeframeM10(dataptr);
|
||||
|
@ -578,6 +581,8 @@ int M10M20::decodeframeM20(uint8_t *data) {
|
|||
|
||||
Serial.println("Decoding...");
|
||||
// Its a M20
|
||||
memcpy(si->typestr, "M20 ", 5);
|
||||
si->subtype = 2; // subtype 2: M20
|
||||
// getid...
|
||||
// TODO: Adjust ID calculation and serial number reconstruction
|
||||
char ids[11]={'M','E','0','0','0','0','0','0','0','0','0'};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_RS92
|
||||
|
||||
/* RS92 decoder functions */
|
||||
#include "RS92.h"
|
||||
|
@ -587,3 +589,4 @@ int RS92::waitRXcomplete() {
|
|||
|
||||
|
||||
RS92 rs92 = RS92();
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,7 @@ const char *sondeTypeStr[NSondeTypes] = { "DFM ", "RS41", "RS92", "Mxx ", "M10 "
|
|||
const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "RS41", "RS92", "M10/M20", "M10 ", "M20 ", "MP3-H1" };
|
||||
const char sondeTypeChar[NSondeTypes] = { 'D', '4', 'R', 'M', 'M', '2', '3' };
|
||||
const char *manufacturer_string[]={"Graw", "Vaisala", "Vaisala", "Meteomodem", "Meteomodem", "Meteomodem", "Meteo-Radiy"};
|
||||
const char *DEFEPH="gssc.esa.int/gnss/data/daily/%1$04d/brdc/brdc%2$03d0.%3$02dn.gz";
|
||||
|
||||
int fingerprintValue[]={ 17, 31, 64, 4, 55, 48, 23, 128+23, 119, 128+119, -1 };
|
||||
const char *fingerprintText[]={
|
||||
|
@ -258,7 +259,7 @@ void Sonde::defaultConfig() {
|
|||
config.tcpfeed.port = 12345;
|
||||
config.tcpfeed.highrate = 10;
|
||||
config.kisstnc.active = 0;
|
||||
strcpy(config.ephftp,"igs.bkg.bund.de/IGS/BRDC/");
|
||||
strcpy(config.ephftp,DEFEPH);
|
||||
|
||||
config.mqtt.active = 0;
|
||||
strcpy(config.mqtt.id, "rdz_sonde_server");
|
||||
|
@ -278,6 +279,8 @@ void Sonde::checkConfig() {
|
|||
if(config.sondehub.fimaxage>48) config.sondehub.fimaxage = 48;
|
||||
if(config.sondehub.fimaxdist==0) config.sondehub.fimaxdist = 150;
|
||||
if(config.sondehub.fimaxage==0) config.sondehub.fimaxage = 2;
|
||||
// auto upgrade config to new version with format arguments in string
|
||||
if(!strchr(sonde.config.ephftp,'%')) strcpy(sonde.config.ephftp,DEFEPH);
|
||||
}
|
||||
void Sonde::setConfig(const char *cfg) {
|
||||
while(*cfg==' '||*cfg=='\t') cfg++;
|
||||
|
|
|
@ -191,6 +191,7 @@ struct st_feedinfo {
|
|||
int lowrate;
|
||||
int highrate;
|
||||
int lowlimit;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
// maybe extend for external Bluetooth interface?
|
||||
|
@ -281,7 +282,7 @@ typedef struct st_rdzconfig {
|
|||
struct st_dfmconfig dfm;
|
||||
struct st_m10m20config m10m20;
|
||||
struct st_mp3hconfig mp3h;
|
||||
char ephftp[40];
|
||||
char ephftp[80];
|
||||
// data feed configuration
|
||||
// for now, one feed for each type is enough, but might get extended to more?
|
||||
char call[10]; // APRS callsign
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -1,471 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0
|
||||
// original source: https://github.com/Nkawu/TFT22_ILI9225
|
||||
|
||||
#ifndef TFT22_ILI9225_h
|
||||
#define TFT22_ILI9225_h
|
||||
|
||||
#ifdef __STM32F1__
|
||||
#define ARDUINO_STM32_FEATHER
|
||||
#define PROGMEM
|
||||
// if 'SPI_CHANNEL' is not defined, 'SPI' is used, only valid for STM32F1
|
||||
//#define SPI_CHANNEL SPI_2
|
||||
#endif
|
||||
|
||||
#define USE_STRING_CLASS
|
||||
|
||||
#ifdef USE_STRING_CLASS
|
||||
#define STRING String
|
||||
#else
|
||||
#define STRING const char *
|
||||
#endif
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
#include "gfxfont.h"
|
||||
|
||||
#if defined(ARDUINO_STM32_FEATHER) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) || defined(STM32F1)
|
||||
typedef volatile uint32 RwReg;
|
||||
#endif
|
||||
#if defined(ARDUINO_FEATHER52)
|
||||
typedef volatile uint32_t RwReg;
|
||||
#endif
|
||||
|
||||
/* ILI9225 screen size */
|
||||
#define ILI9225_LCD_WIDTH 176
|
||||
#define ILI9225_LCD_HEIGHT 220
|
||||
|
||||
/* ILI9225 LCD Registers */
|
||||
#define ILI9225_DRIVER_OUTPUT_CTRL (0x01u) // Driver Output Control
|
||||
#define ILI9225_LCD_AC_DRIVING_CTRL (0x02u) // LCD AC Driving Control
|
||||
#define ILI9225_ENTRY_MODE (0x03u) // Entry Mode
|
||||
#define ILI9225_DISP_CTRL1 (0x07u) // Display Control 1
|
||||
#define ILI9225_BLANK_PERIOD_CTRL1 (0x08u) // Blank Period Control
|
||||
#define ILI9225_FRAME_CYCLE_CTRL (0x0Bu) // Frame Cycle Control
|
||||
#define ILI9225_INTERFACE_CTRL (0x0Cu) // Interface Control
|
||||
#define ILI9225_OSC_CTRL (0x0Fu) // Osc Control
|
||||
#define ILI9225_POWER_CTRL1 (0x10u) // Power Control 1
|
||||
#define ILI9225_POWER_CTRL2 (0x11u) // Power Control 2
|
||||
#define ILI9225_POWER_CTRL3 (0x12u) // Power Control 3
|
||||
#define ILI9225_POWER_CTRL4 (0x13u) // Power Control 4
|
||||
#define ILI9225_POWER_CTRL5 (0x14u) // Power Control 5
|
||||
#define ILI9225_VCI_RECYCLING (0x15u) // VCI Recycling
|
||||
#define ILI9225_RAM_ADDR_SET1 (0x20u) // Horizontal GRAM Address Set
|
||||
#define ILI9225_RAM_ADDR_SET2 (0x21u) // Vertical GRAM Address Set
|
||||
#define ILI9225_GRAM_DATA_REG (0x22u) // GRAM Data Register
|
||||
#define ILI9225_GATE_SCAN_CTRL (0x30u) // Gate Scan Control Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL1 (0x31u) // Vertical Scroll Control 1 Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL2 (0x32u) // Vertical Scroll Control 2 Register
|
||||
#define ILI9225_VERTICAL_SCROLL_CTRL3 (0x33u) // Vertical Scroll Control 3 Register
|
||||
#define ILI9225_PARTIAL_DRIVING_POS1 (0x34u) // Partial Driving Position 1 Register
|
||||
#define ILI9225_PARTIAL_DRIVING_POS2 (0x35u) // Partial Driving Position 2 Register
|
||||
#define ILI9225_HORIZONTAL_WINDOW_ADDR1 (0x36u) // Horizontal Address Start Position
|
||||
#define ILI9225_HORIZONTAL_WINDOW_ADDR2 (0x37u) // Horizontal Address End Position
|
||||
#define ILI9225_VERTICAL_WINDOW_ADDR1 (0x38u) // Vertical Address Start Position
|
||||
#define ILI9225_VERTICAL_WINDOW_ADDR2 (0x39u) // Vertical Address End Position
|
||||
#define ILI9225_GAMMA_CTRL1 (0x50u) // Gamma Control 1
|
||||
#define ILI9225_GAMMA_CTRL2 (0x51u) // Gamma Control 2
|
||||
#define ILI9225_GAMMA_CTRL3 (0x52u) // Gamma Control 3
|
||||
#define ILI9225_GAMMA_CTRL4 (0x53u) // Gamma Control 4
|
||||
#define ILI9225_GAMMA_CTRL5 (0x54u) // Gamma Control 5
|
||||
#define ILI9225_GAMMA_CTRL6 (0x55u) // Gamma Control 6
|
||||
#define ILI9225_GAMMA_CTRL7 (0x56u) // Gamma Control 7
|
||||
#define ILI9225_GAMMA_CTRL8 (0x57u) // Gamma Control 8
|
||||
#define ILI9225_GAMMA_CTRL9 (0x58u) // Gamma Control 9
|
||||
#define ILI9225_GAMMA_CTRL10 (0x59u) // Gamma Control 10
|
||||
|
||||
#define ILI9225C_INVOFF 0x20
|
||||
#define ILI9225C_INVON 0x21
|
||||
|
||||
// autoincrement modes (register ILI9225_ENTRY_MODE, bit 5..3 )
|
||||
enum autoIncMode_t { R2L_BottomUp, BottomUp_R2L, L2R_BottomUp, BottomUp_L2R, R2L_TopDown, TopDown_R2L, L2R_TopDown, TopDown_L2R };
|
||||
|
||||
/* RGB 16-bit color table definition (RG565) */
|
||||
#define COLOR_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define COLOR_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define COLOR_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define COLOR_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define COLOR_RED 0xF800 /* 255, 0, 0 */
|
||||
#define COLOR_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define COLOR_DARKBLUE 0x0011 /* 0, 0, 139 */
|
||||
#define COLOR_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define COLOR_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define COLOR_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define COLOR_TURQUOISE 0x471A /* 64, 224, 208 */
|
||||
#define COLOR_INDIGO 0x4810 /* 75, 0, 130 */
|
||||
#define COLOR_DARKRED 0x8000 /* 128, 0, 0 */
|
||||
#define COLOR_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define COLOR_GRAY 0x8410 /* 128, 128, 128 */
|
||||
#define COLOR_GREY 0x8410 /* 128, 128, 128 */
|
||||
#define COLOR_SKYBLUE 0x867D /* 135, 206, 235 */
|
||||
#define COLOR_BLUEVIOLET 0x895C /* 138, 43, 226 */
|
||||
#define COLOR_LIGHTGREEN 0x9772 /* 144, 238, 144 */
|
||||
#define COLOR_DARKVIOLET 0x901A /* 148, 0, 211 */
|
||||
#define COLOR_YELLOWGREEN 0x9E66 /* 154, 205, 50 */
|
||||
#define COLOR_BROWN 0xA145 /* 165, 42, 42 */
|
||||
#define COLOR_DARKGRAY 0x7BEF /* 128, 128, 128 */
|
||||
#define COLOR_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define COLOR_SIENNA 0xA285 /* 160, 82, 45 */
|
||||
#define COLOR_LIGHTBLUE 0xAEDC /* 172, 216, 230 */
|
||||
#define COLOR_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define COLOR_SILVER 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTGRAY 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define COLOR_LIGHTCYAN 0xE7FF /* 224, 255, 255 */
|
||||
#define COLOR_VIOLET 0xEC1D /* 238, 130, 238 */
|
||||
#define COLOR_AZUR 0xF7FF /* 240, 255, 255 */
|
||||
#define COLOR_BEIGE 0xF7BB /* 245, 245, 220 */
|
||||
#define COLOR_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define COLOR_TOMATO 0xFB08 /* 255, 99, 71 */
|
||||
#define COLOR_GOLD 0xFEA0 /* 255, 215, 0 */
|
||||
#define COLOR_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define COLOR_SNOW 0xFFDF /* 255, 250, 250 */
|
||||
#define COLOR_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
|
||||
|
||||
/* Font defines */
|
||||
#define FONT_HEADER_SIZE 4 // 1: pixel width of 1 font character, 2: pixel height,
|
||||
#define readFontByte(x) pgm_read_byte(&cfont.font[x])
|
||||
|
||||
extern uint8_t Terminal6x8[];
|
||||
extern uint8_t Terminal11x16[];
|
||||
extern uint8_t Terminal12x16[];
|
||||
extern uint8_t Trebuchet_MS16x21[];
|
||||
|
||||
struct _currentFont
|
||||
{
|
||||
uint8_t* font;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t offset;
|
||||
uint8_t numchars;
|
||||
uint8_t nbrows;
|
||||
bool monoSp;
|
||||
};
|
||||
#define MONOSPACE 1
|
||||
|
||||
#if defined (ARDUINO_STM32_FEATHER)
|
||||
#undef USE_FAST_PINIO
|
||||
#elif defined (__AVR__) || defined(TEENSYDUINO) || defined(ESP8266) || defined(__arm__)
|
||||
#define USE_FAST_PINIO
|
||||
#endif
|
||||
|
||||
/// Main and core class
|
||||
class TFT22_ILI9225 {
|
||||
|
||||
public:
|
||||
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t SDI, int8_t CLK, int8_t LED);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t LED);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t SDI, int8_t CLK, int8_t LED, uint8_t brightness);
|
||||
TFT22_ILI9225(int8_t RST, int8_t RS, int8_t CS, int8_t LED, uint8_t brightness);
|
||||
|
||||
/// Initialization
|
||||
#ifndef ESP32
|
||||
void begin(void);
|
||||
#else
|
||||
void begin(SPIClass &spi=SPI);
|
||||
#endif
|
||||
|
||||
/// Clear the screen
|
||||
void clear(void);
|
||||
|
||||
/// Invert screen
|
||||
/// @param flag true to invert, false for normal screen
|
||||
void invert(boolean flag);
|
||||
|
||||
/// Switch backlight on or off
|
||||
/// @param flag true=on, false=off
|
||||
void setBacklight(boolean flag);
|
||||
|
||||
/// Set backlight brightness
|
||||
/// @param brightness sets backlight brightness 0-255
|
||||
void setBacklightBrightness(uint8_t brightness);
|
||||
|
||||
/// Switch display on or off
|
||||
/// @param flag true=on, false=off
|
||||
void setDisplay(boolean flag);
|
||||
|
||||
/// Set orientation
|
||||
/// @param orientation orientation, 0=portrait, 1=right rotated landscape, 2=reverse portrait, 3=left rotated landscape
|
||||
void setOrientation(uint8_t orientation);
|
||||
|
||||
/// Get orientation
|
||||
/// @return orientation orientation, 0=portrait, 1=right rotated landscape, 2=reverse portrait, 3=left rotated landscape
|
||||
uint8_t getOrientation(void);
|
||||
|
||||
/// Font size, x-axis
|
||||
/// @return horizontal size of current font, in pixels
|
||||
// uint8_t fontX(void);
|
||||
|
||||
/// Font size, y-axis
|
||||
/// @return vertical size of current font, in pixels
|
||||
// uint8_t fontY(void);
|
||||
|
||||
/// Screen size, x-axis
|
||||
/// @return horizontal size of the screen, in pixels
|
||||
/// @note 240 means 240 pixels and thus 0..239 coordinates (decimal)
|
||||
uint16_t maxX(void);
|
||||
|
||||
/// Screen size, y-axis
|
||||
/// @return vertical size of the screen, in pixels
|
||||
/// @note 220 means 220 pixels and thus 0..219 coordinates (decimal)
|
||||
uint16_t maxY(void);
|
||||
|
||||
/// Draw circle
|
||||
/// @param x0 center, point coordinate, x-axis
|
||||
/// @param y0 center, point coordinate, y-axis
|
||||
/// @param radius radius
|
||||
/// @param color 16-bit color
|
||||
void drawCircle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t color);
|
||||
|
||||
/// Draw solid circle
|
||||
/// @param x0 center, point coordinate, x-axis
|
||||
/// @param y0 center, point coordinate, y-axis
|
||||
/// @param radius radius
|
||||
/// @param color 16-bit color
|
||||
void fillCircle(uint8_t x0, uint8_t y0, uint8_t radius, uint16_t color);
|
||||
|
||||
/// Set background color
|
||||
/// @param color background color, default=black
|
||||
void setBackgroundColor(uint16_t color = COLOR_BLACK);
|
||||
|
||||
/// Draw line, rectangle coordinates
|
||||
/// @param x1 start point coordinate, x-axis
|
||||
/// @param y1 start point coordinate, y-axis
|
||||
/// @param x2 end point coordinate, x-axis
|
||||
/// @param y2 end point coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw rectangle, rectangle coordinates
|
||||
/// @param x1 top left coordinate, x-axis
|
||||
/// @param y1 top left coordinate, y-axis
|
||||
/// @param x2 bottom right coordinate, x-axis
|
||||
/// @param y2 bottom right coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw solid rectangle, rectangle coordinates
|
||||
/// @param x1 top left coordinate, x-axis
|
||||
/// @param y1 top left coordinate, y-axis
|
||||
/// @param x2 bottom right coordinate, x-axis
|
||||
/// @param y2 bottom right coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void fillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
|
||||
|
||||
/// Draw pixel
|
||||
/// @param x1 point coordinate, x-axis
|
||||
/// @param y1 point coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawPixel(uint16_t x1, uint16_t y1, uint16_t color);
|
||||
|
||||
/// Draw ASCII Text (pixel coordinates)
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param s text string
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @return x-position behind text
|
||||
uint16_t drawText(uint16_t x, uint16_t y, STRING s, uint16_t color = COLOR_WHITE);
|
||||
|
||||
/// width of an ASCII Text (pixel )
|
||||
/// @param s text string
|
||||
uint16_t getTextWidth( STRING s ) ;
|
||||
|
||||
/// Calculate 16-bit color from 8-bit Red-Green-Blue components
|
||||
/// @param red red component, 0x00..0xff
|
||||
/// @param green green component, 0x00..0xff
|
||||
/// @param blue blue component, 0x00..0xff
|
||||
/// @return 16-bit color
|
||||
uint16_t setColor(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/// Calculate 8-bit Red-Green-Blue components from 16-bit color
|
||||
/// @param rgb 16-bit color
|
||||
/// @param red red component, 0x00..0xff
|
||||
/// @param green green component, 0x00..0xff
|
||||
/// @param blue blue component, 0x00..0xff
|
||||
void splitColor(uint16_t rgb, uint8_t &red, uint8_t &green, uint8_t &blue);
|
||||
|
||||
/// Draw triangle, triangle coordinates
|
||||
/// @param x1 corner 1 coordinate, x-axis
|
||||
/// @param y1 corner 1 coordinate, y-axis
|
||||
/// @param x2 corner 2 coordinate, x-axis
|
||||
/// @param y2 corner 2 coordinate, y-axis
|
||||
/// @param x3 corner 3 coordinate, x-axis
|
||||
/// @param y3 corner 3 coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void drawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color);
|
||||
|
||||
/// Draw solid triangle, triangle coordinates
|
||||
/// @param x1 corner 1 coordinate, x-axis
|
||||
/// @param y1 corner 1 coordinate, y-axis
|
||||
/// @param x2 corner 2 coordinate, x-axis
|
||||
/// @param y2 corner 2 coordinate, y-axis
|
||||
/// @param x3 corner 3 coordinate, x-axis
|
||||
/// @param y3 corner 3 coordinate, y-axis
|
||||
/// @param color 16-bit color
|
||||
void fillTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color);
|
||||
|
||||
/// Set current font
|
||||
/// @param font Font name
|
||||
void setFont(uint8_t* font, bool monoSp=false ); // default = proportional
|
||||
|
||||
/// Get current font
|
||||
_currentFont getFont();
|
||||
|
||||
/// Draw single character (pixel coordinates)
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param ch ASCII character
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @return width of character in display pixels
|
||||
uint16_t drawChar(uint16_t x, uint16_t y, uint16_t ch, uint16_t color = COLOR_WHITE);
|
||||
|
||||
/// width of an ASCII character (pixel )
|
||||
/// @param ch ASCII character
|
||||
uint16_t getCharWidth( uint16_t ch ) ;
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
/// @param color 16-bit color, default=white
|
||||
/// @param bg 16-bit color, background
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap, 2D 16bit color bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
void drawBitmap(uint16_t x, uint16_t y, const uint16_t** bitmap, int16_t w, int16_t h);
|
||||
void drawBitmap(uint16_t x, uint16_t y, uint16_t** bitmap, int16_t w, int16_t h);
|
||||
|
||||
/// Draw bitmap
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param bitmap, 1D 16bit color bitmap
|
||||
/// @param w width
|
||||
/// @param h height
|
||||
void drawBitmap(uint16_t x, uint16_t y, const uint16_t* bitmap, int16_t w, int16_t h);
|
||||
void drawBitmap(uint16_t x, uint16_t y, uint16_t* bitmap, int16_t w, int16_t h);
|
||||
|
||||
/// Set current GFX font
|
||||
/// @param f GFX font name defined in include file
|
||||
void setGFXFont(const GFXfont *f = NULL);
|
||||
|
||||
/// Draw a string with the current GFX font
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param s string to print
|
||||
/// @param color 16-bit color
|
||||
void drawGFXText(int16_t x, int16_t y, STRING s, uint16_t color);
|
||||
|
||||
/// Get the width & height of a text string with the current GFX font
|
||||
/// @param str string to analyze
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param w width in pixels of string
|
||||
/// @param h height in pixels of string
|
||||
void getGFXTextExtent(STRING str, int16_t x, int16_t y, int16_t *w, int16_t *h);
|
||||
|
||||
/// Draw a single character with the current GFX font
|
||||
/// @param x point coordinate, x-axis
|
||||
/// @param y point coordinate, y-axis
|
||||
/// @param c character to draw
|
||||
/// @param color 16-bit color
|
||||
/// @return width of character in display pixels
|
||||
uint16_t drawGFXChar(int16_t x, int16_t y, unsigned char c, uint16_t color);
|
||||
|
||||
uint16_t drawGFXcharBM(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t *bm, int bmwidth, int bmheight);
|
||||
|
||||
void getGFXCharExtent(uint8_t c, int16_t *gw, int16_t *gh, int16_t *xa);
|
||||
|
||||
void setModeFlip(uint16_t m);
|
||||
|
||||
private:
|
||||
|
||||
void _spiWrite(uint8_t v);
|
||||
void _spiWrite16(uint16_t v);
|
||||
void _spiWriteCommand(uint8_t c);
|
||||
void _spiWriteData(uint8_t d);
|
||||
|
||||
void _swap(uint16_t &a, uint16_t &b);
|
||||
void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void _setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, autoIncMode_t mode);
|
||||
void _resetWindow();
|
||||
void _drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h,
|
||||
uint16_t color, uint16_t bg, bool transparent, bool progmem, bool Xbit );
|
||||
void _orientCoordinates(uint16_t &x1, uint16_t &y1);
|
||||
void _writeRegister(uint16_t reg, uint16_t data);
|
||||
void _writeData(uint8_t HI, uint8_t LO);
|
||||
void _writeData16(uint16_t HILO);
|
||||
void _writeCommand(uint8_t HI, uint8_t LO);
|
||||
void _writeCommand16(uint16_t HILO);
|
||||
uint16_t _maxX, _maxY, _bgColor;
|
||||
|
||||
#if defined (__AVR__) || defined(TEENSYDUINO)
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint8_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#elif defined (__arm__)
|
||||
int32_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#elif defined (ESP8266) || defined (ESP32)
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#ifdef USE_FAST_PINIO
|
||||
volatile uint32_t *mosiport, *clkport, *dcport, *rsport, *csport;
|
||||
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#else
|
||||
int8_t _rst, _rs, _cs, _sdi, _clk, _led;
|
||||
#endif
|
||||
|
||||
uint8_t _orientation, _brightness;
|
||||
uint16_t _modeFlip;
|
||||
|
||||
// correspondig modes if orientation changed:
|
||||
const autoIncMode_t modeTab [3][8] = {
|
||||
// { R2L_BottomUp, BottomUp_R2L, L2R_BottomUp, BottomUp_L2R, R2L_TopDown, TopDown_R2L, L2R_TopDown, TopDown_L2R }//
|
||||
/* 90° */ { BottomUp_L2R, L2R_BottomUp, TopDown_L2R, L2R_TopDown, BottomUp_R2L, R2L_BottomUp, TopDown_R2L, R2L_TopDown },
|
||||
/*180° */ { L2R_TopDown , TopDown_L2R, R2L_TopDown, TopDown_R2L, L2R_BottomUp, BottomUp_L2R, R2L_BottomUp, BottomUp_R2L},
|
||||
/*270° */ { TopDown_R2L , R2L_TopDown, BottomUp_R2L, R2L_BottomUp, TopDown_L2R, L2R_TopDown, BottomUp_L2R, L2R_BottomUp}
|
||||
};
|
||||
|
||||
|
||||
bool hwSPI, blState;
|
||||
|
||||
_currentFont cfont;
|
||||
|
||||
#ifdef ESP32
|
||||
SPIClass _spi;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
uint32_t writeFunctionLevel;
|
||||
void startWrite(void);
|
||||
void endWrite(void);
|
||||
|
||||
|
||||
GFXfont *gfxFont;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include "aprs.h"
|
||||
#include "RS41.h"
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
#ifndef _aprs_h
|
||||
#define _aprs_h
|
||||
|
||||
#include "Sonde.h"
|
||||
#include "RS41.h"
|
||||
|
||||
|
||||
#define APRS_MAXLEN 201
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
#include "../features.h"
|
||||
|
||||
#if FEATURE_APRS
|
||||
|
||||
#include "conn-aprs.h"
|
||||
#include "aprs.h"
|
||||
#include "posinfo.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <lwip/dns.h>
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
// KISS over TCP for communicating with APRSdroid
|
||||
static WiFiServer tncserver(14580);
|
||||
static WiFiClient tncclient;
|
||||
|
||||
// APRS over TCP for radiosondy.info etc
|
||||
static int tcpclient = 0;
|
||||
enum { TCS_DISCONNECTED, TCS_DNSLOOKUP, TCS_DNSRESOLVED, TCS_CONNECTING, TCS_LOGIN, TCS_CONNECTED };
|
||||
static uint8_t tcpclient_state = TCS_DISCONNECTED;
|
||||
ip_addr_t tcpclient_ipaddr;
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
|
||||
extern WiFiUDP udp;
|
||||
|
||||
static unsigned long last_in = 0;
|
||||
|
||||
void tcpclient_fsm();
|
||||
|
||||
|
||||
void ConnAPRS::init() {
|
||||
aprs_gencrctab();
|
||||
}
|
||||
|
||||
void ConnAPRS::netsetup() {
|
||||
// Setup for KISS TCP server
|
||||
if(sonde.config.kisstnc.active) {
|
||||
MDNS.addService("kiss-tnc", "tcp", 14580);
|
||||
tncserver.begin();
|
||||
}
|
||||
|
||||
if(sonde.config.tcpfeed.active) {
|
||||
// start the FSM
|
||||
tcpclient_fsm();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnAPRS::updateSonde( SondeInfo *si ) {
|
||||
// prepare data (for UDP and TCP output)
|
||||
char *str = aprs_senddata(si, sonde.config.call, sonde.config.objcall, sonde.config.udpfeed.symbol);
|
||||
|
||||
// Output via AXUDP
|
||||
if(sonde.config.udpfeed.active) {
|
||||
char raw[201];
|
||||
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
|
||||
Serial.println("Sending AXUDP");
|
||||
//Serial.println(raw);
|
||||
udp.beginPacket(sonde.config.udpfeed.host, sonde.config.udpfeed.port);
|
||||
udp.write((const uint8_t *)raw, rawlen);
|
||||
udp.endPacket();
|
||||
}
|
||||
// KISS via TCP (incoming connection, e.g. from APRSdroid
|
||||
if (tncclient.connected()) {
|
||||
Serial.println("Sending position via TCP");
|
||||
char raw[201];
|
||||
int rawlen = aprsstr_mon2kiss(str, raw, APRS_MAXLEN);
|
||||
Serial.print("sending: "); Serial.println(raw);
|
||||
tncclient.write(raw, rawlen);
|
||||
}
|
||||
// APRS via TCP (outgoing connection to aprs-is, e.g. radiosonde.info or wettersonde.net
|
||||
if (sonde.config.tcpfeed.active) {
|
||||
static unsigned long lasttcp = 0;
|
||||
tcpclient_fsm();
|
||||
if(tcpclient_state == TCS_CONNECTED) {
|
||||
unsigned long now = millis();
|
||||
long tts = sonde.config.tcpfeed.highrate * 1000L - (now-lasttcp);
|
||||
Serial.printf("aprs: now-last = %ld\n", (now - lasttcp));
|
||||
if ( tts < 0 ) {
|
||||
strcat(str, "\r\n");
|
||||
Serial.printf("Sending APRS: %s",str);
|
||||
write(tcpclient, str, strlen(str));
|
||||
lasttcp = now;
|
||||
} else {
|
||||
Serial.printf("Sending APRS in %d s\n", (int)(tts/1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define APRS_TIMEOUT 25000
|
||||
|
||||
void ConnAPRS::updateStation( PosInfo *pi ) {
|
||||
// This funciton is called peridocally.
|
||||
|
||||
// We check for stalled connection and possibly close it
|
||||
Serial.printf("last_in - now: %ld\n", millis() - last_in);
|
||||
if ( sonde.config.tcpfeed.timeout > 0) {
|
||||
if ( last_in && ( (millis() - last_in) > sonde.config.tcpfeed.timeout*1000 ) ) {
|
||||
Serial.println("APRS timeout - closing connection");
|
||||
close(tcpclient);
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// If available, read data from tcpclient; then send update (if its time for that)
|
||||
tcpclient_fsm();
|
||||
if(sonde.config.tcpfeed.active) {
|
||||
aprs_station_update();
|
||||
}
|
||||
|
||||
// We check for new connections or new data (tnc port)
|
||||
if (!tncclient.connected()) {
|
||||
tncclient = tncserver.available();
|
||||
if (tncclient.connected()) {
|
||||
Serial.println("new TCP KISS connection");
|
||||
}
|
||||
}
|
||||
if (tncclient.available()) {
|
||||
Serial.print("TCP KISS socket: recevied ");
|
||||
while (tncclient.available()) {
|
||||
Serial.print(tncclient.read()); // Check if we receive anything from from APRSdroid
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnAPRS::aprs_station_update() {
|
||||
int chase = sonde.config.chase;
|
||||
// automatically decided if CHASE or FIXED mode is used (for config AUTO)
|
||||
if (chase == SH_LOC_AUTO) {
|
||||
if (posInfo.chase) chase = SH_LOC_CHASE; else chase = SH_LOC_FIXED;
|
||||
}
|
||||
unsigned long time_now = millis();
|
||||
unsigned long time_delta = time_now - time_last_aprs_update;
|
||||
unsigned long update_time = (chase == SH_LOC_CHASE) ? APRS_MOBILE_STATION_UPDATE_TIME : APRS_STATION_UPDATE_TIME;
|
||||
long tts = update_time - time_delta;
|
||||
Serial.printf("aprs_statio_update due in %d s", (int)(tts/1000));
|
||||
if (tts>0) return;
|
||||
|
||||
float lat, lon;
|
||||
if (chase == SH_LOC_FIXED) {
|
||||
// fixed location
|
||||
lat = sonde.config.rxlat;
|
||||
lon = sonde.config.rxlon;
|
||||
if (isnan(lat) || isnan(lon)) return;
|
||||
} else {
|
||||
if (gpsPos.valid) {
|
||||
lat = gpsPos.lat;
|
||||
lon = gpsPos.lon;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
char *bcn = aprs_send_beacon(sonde.config.call, lat, lon, sonde.config.beaconsym + ((chase == SH_LOC_CHASE) ? 2 : 0), sonde.config.comment);
|
||||
tcpclient_fsm();
|
||||
if(tcpclient_state == TCS_CONNECTED) {
|
||||
strcat(bcn, "\r\n");
|
||||
Serial.printf("APRS TCP BEACON: %s", bcn);
|
||||
write(tcpclient, bcn, strlen(bcn));
|
||||
time_last_aprs_update = time_now;
|
||||
}
|
||||
}
|
||||
|
||||
static void _tcp_dns_found(const char * name, const ip_addr_t *ipaddr, void * arg) {
|
||||
if (ipaddr) {
|
||||
tcpclient_ipaddr = *ipaddr;
|
||||
tcpclient_state = TCS_DNSRESOLVED; // DNS lookup success
|
||||
} else {
|
||||
memset(&tcpclient_ipaddr, 0, sizeof(tcpclient_ipaddr));
|
||||
tcpclient_state = TCS_DISCONNECTED; // DNS lookup failed
|
||||
}
|
||||
}
|
||||
|
||||
void tcpclient_sendlogin() {
|
||||
char buf[128];
|
||||
snprintf(buf, 128, "user %s pass %d vers %s %s\r\n", sonde.config.call, sonde.config.passcode, version_name, version_id);
|
||||
int res = write(tcpclient, buf, strlen(buf));
|
||||
Serial.printf("APRS login: %s, res=%d\n", buf, res);
|
||||
last_in = millis();
|
||||
if(res<=0) {
|
||||
close(tcpclient);
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
void tcpclient_fsm() {
|
||||
if(!sonde.config.tcpfeed.active)
|
||||
return;
|
||||
Serial.printf("TCS: %d\n", tcpclient_state);
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(tcpclient, &fdset);
|
||||
fd_set fdeset;
|
||||
FD_ZERO(&fdeset);
|
||||
FD_SET(tcpclient, &fdeset);
|
||||
|
||||
struct timeval selto = {0};
|
||||
int res;
|
||||
|
||||
switch(tcpclient_state) {
|
||||
case TCS_DISCONNECTED:
|
||||
/* We are disconnected. Try to connect, starting with a DNS lookup */
|
||||
{
|
||||
// Restart timeout
|
||||
last_in = millis();
|
||||
err_t res = dns_gethostbyname( sonde.config.tcpfeed.host, &tcpclient_ipaddr, /*(dns_found_callback)*/_tcp_dns_found, NULL );
|
||||
|
||||
if(res == ERR_OK) { // Returns immediately of host is IP or in cache
|
||||
tcpclient_state = TCS_DNSRESOLVED;
|
||||
/* fall through */
|
||||
} else if(res == ERR_INPROGRESS) {
|
||||
tcpclient_state = TCS_DNSLOOKUP;
|
||||
break;
|
||||
} else { // failed
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case TCS_DNSRESOLVED:
|
||||
{
|
||||
/* We have got the IP address, start the connection */
|
||||
tcpclient = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int flags = fcntl(tcpclient, F_GETFL);
|
||||
if (fcntl(tcpclient, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
Serial.println("Setting O_NONBLOCK failed");
|
||||
}
|
||||
|
||||
struct sockaddr_in sock_info;
|
||||
memset(&sock_info, 0, sizeof(struct sockaddr_in));
|
||||
sock_info.sin_family = AF_INET;
|
||||
sock_info.sin_addr.s_addr = tcpclient_ipaddr.u_addr.ip4.addr;
|
||||
sock_info.sin_port = htons( sonde.config.tcpfeed.port );
|
||||
err_t res = connect(tcpclient, (struct sockaddr *)&sock_info, sizeof(sock_info));
|
||||
if(res) {
|
||||
if (errno == EINPROGRESS) { // Should be the usual case, go to connecting state
|
||||
tcpclient_state = TCS_CONNECTING;
|
||||
} else {
|
||||
close(tcpclient);
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
}
|
||||
} else {
|
||||
tcpclient_state = TCS_CONNECTED;
|
||||
tcpclient_sendlogin();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TCS_CONNECTING:
|
||||
{
|
||||
// Poll to see if we are now connected
|
||||
res = select(tcpclient+1, NULL, &fdset, &fdeset, &selto);
|
||||
if(res<0) {
|
||||
Serial.println("TNS_CONNECTING: select error");
|
||||
goto error;
|
||||
} else if (res==0) { // still pending
|
||||
break;
|
||||
}
|
||||
// Socket has become ready (or something went wrong, check for error first)
|
||||
|
||||
int sockerr;
|
||||
socklen_t len = (socklen_t)sizeof(int);
|
||||
if (getsockopt(tcpclient, SOL_SOCKET, SO_ERROR, (void*)(&sockerr), &len) < 0) {
|
||||
goto error;
|
||||
}
|
||||
Serial.printf("select returing %d. isset:%d iseset:%d sockerr:%d\n", res, FD_ISSET(tcpclient, &fdset), FD_ISSET(tcpclient, &fdeset), sockerr);
|
||||
if(sockerr) {
|
||||
Serial.printf("APRS connect error: %s\n", strerror(sockerr));
|
||||
goto error;
|
||||
}
|
||||
tcpclient_state = TCS_CONNECTED;
|
||||
tcpclient_sendlogin();
|
||||
}
|
||||
break;
|
||||
|
||||
case TCS_CONNECTED:
|
||||
{
|
||||
res = select(tcpclient+1, &fdset, NULL, NULL, &selto);
|
||||
if(res<0) {
|
||||
Serial.println("TCS_CONNECTING: select error");
|
||||
goto error;
|
||||
} else if (res==0) { // still pending
|
||||
break;
|
||||
}
|
||||
// Read data
|
||||
char buf[512+1];
|
||||
res = read(tcpclient, buf, 512);
|
||||
if(res<=0) {
|
||||
close(tcpclient);
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
} else {
|
||||
buf[res] = 0;
|
||||
Serial.printf("tcpclient data (len=%d):", res);
|
||||
Serial.write( (uint8_t *)buf, res );
|
||||
last_in = millis();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCS_DNSLOOKUP:
|
||||
Serial.println("DNS lookup in progress");
|
||||
break; // DNS lookup in progress, do not do anything until callback is called, updating the state
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
close(tcpclient);
|
||||
tcpclient_state = TCS_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ConnAPRS connAPRS;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_APRS
|
||||
|
||||
#ifndef conn_aprs_h
|
||||
#define conn_aprs_h
|
||||
|
||||
#include "conn.h"
|
||||
#include "aprs.h"
|
||||
|
||||
// Times in ms, i.e. station: 10 minutes, mobile: 20 seconds
|
||||
#define APRS_STATION_UPDATE_TIME (10*60*1000)
|
||||
#define APRS_MOBILE_STATION_UPDATE_TIME (20*1000)
|
||||
|
||||
static unsigned long time_last_aprs_update = -APRS_STATION_UPDATE_TIME;
|
||||
|
||||
|
||||
class ConnAPRS : public Conn
|
||||
{
|
||||
public:
|
||||
/* Called once on startup */
|
||||
void init();
|
||||
|
||||
/* Called whenever the network becomes available */
|
||||
void netsetup();
|
||||
|
||||
/* Called approx 1x / second (maybe only if good data is available) */
|
||||
void updateSonde( SondeInfo *si );
|
||||
|
||||
/* Called approx 1x / second* */
|
||||
void updateStation( PosInfo *pi );
|
||||
|
||||
private:
|
||||
void aprs_station_update();
|
||||
};
|
||||
|
||||
extern ConnAPRS connAPRS;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,8 +1,20 @@
|
|||
#include "Chasemapper.h"
|
||||
#include "../features.h"
|
||||
#if FEATURE_CHASEMAPPER
|
||||
|
||||
#include "conn-chasemapper.h"
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
extern const char *sondeTypeStrSH[];
|
||||
extern WiFiUDP udp;
|
||||
|
||||
int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
||||
void ConnChasemapper::init() {
|
||||
}
|
||||
|
||||
void ConnChasemapper::netsetup() {
|
||||
}
|
||||
|
||||
|
||||
void ConnChasemapper::updateSonde(SondeInfo *si) {
|
||||
char buf[1024];
|
||||
struct tm tim;
|
||||
time_t t = si->d.time;
|
||||
|
@ -11,8 +23,16 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
|||
if (TYPE_IS_METEO(realtype)) {
|
||||
realtype = si->d.subtype == 1 ? STYPE_M10 : STYPE_M20;
|
||||
}
|
||||
char prefix[10];
|
||||
if(realtype == STYPE_RS41) {
|
||||
prefix[0] = 0;
|
||||
}
|
||||
else {
|
||||
strncpy(prefix, sondeTypeStrSH[realtype], 10);
|
||||
strcat(prefix, "-");
|
||||
}
|
||||
sprintf(buf, "{ \"type\": \"PAYLOAD_SUMMARY\","
|
||||
"\"callsign\": \"%s\","
|
||||
"\"callsign\": \"%s%s\","
|
||||
"\"latitude\": %.5f,"
|
||||
"\"longitude\": %.5f,"
|
||||
"\"altitude\": %d,"
|
||||
|
@ -21,6 +41,7 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
|||
"\"time\": \"%02d:%02d:%02d\","
|
||||
"\"model\": \"%s\","
|
||||
"\"freq\": \"%.3f MHz\"",
|
||||
prefix,
|
||||
si->d.ser,
|
||||
si->d.lat,
|
||||
si->d.lon,
|
||||
|
@ -38,6 +59,10 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
|||
udp.beginPacket(sonde.config.cm.host, sonde.config.cm.port);
|
||||
udp.write((const uint8_t *)buf, strlen(buf));
|
||||
udp.endPacket();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ConnChasemapper::updateStation(PosInfo *pi) {
|
||||
}
|
||||
|
||||
ConnChasemapper connChasemapper;
|
||||
#endif
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _CHASEMAPPER_H
|
||||
#define _CHASEMAPPER_H
|
||||
|
||||
#include "Sonde.h"
|
||||
#include "conn.h"
|
||||
|
||||
class ConnChasemapper : public Conn {
|
||||
public:
|
||||
void init();
|
||||
void netsetup();
|
||||
void updateSonde( SondeInfo *si );
|
||||
void updateStation( PosInfo *pi );
|
||||
};
|
||||
|
||||
extern ConnChasemapper connChasemapper;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,131 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_MQTT
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "conn-mqtt.h"
|
||||
#include <WiFi.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "json.h"
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
|
||||
/* configuration paramters are in the config, no need to duplicate :-)
|
||||
{"mqtt.active", 0, &sonde.config.mqtt.active},
|
||||
{"mqtt.id", 63, &sonde.config.mqtt.id},
|
||||
{"mqtt.host", 63, &sonde.config.mqtt.host},
|
||||
{"mqtt.port", 0, &sonde.config.mqtt.port},
|
||||
{"mqtt.username", 63, &sonde.config.mqtt.username},
|
||||
{"mqtt.password", 63, &sonde.config.mqtt.password},
|
||||
{"mqtt.prefix", 63, &sonde.config.mqtt.prefix},
|
||||
*/
|
||||
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
|
||||
/* Global initalization (on TTGO startup) */
|
||||
void MQTT::init() {
|
||||
}
|
||||
|
||||
|
||||
// Internal helper function for netsetup
|
||||
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
||||
Serial.print("Message arrived [");
|
||||
Serial.print(topic);
|
||||
Serial.print("] ");
|
||||
for (int i=0;i<length;i++) {
|
||||
Serial.print((char)payload[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
/* Network initialization (as soon as network becomes available) */
|
||||
void MQTT::netsetup() {
|
||||
if (!sonde.config.mqtt.active)
|
||||
return;
|
||||
if (strlen(sonde.config.mqtt.host)==0)
|
||||
return;
|
||||
|
||||
WiFi.hostByName(sonde.config.mqtt.host, this->ip);
|
||||
|
||||
Serial.println("[MQTT] pubsub client");
|
||||
mqttClient.setServer(ip, sonde.config.mqtt.port);
|
||||
snprintf(clientID, 20, "%s%04d", sonde.config.mqtt.id, (int)random(0, 1000));
|
||||
clientID[20] = 0;
|
||||
Serial.print(clientID);
|
||||
mqttClient.setClientId(clientID);
|
||||
if (strlen(sonde.config.mqtt.password) > 0) {
|
||||
mqttClient.setCredentials(sonde.config.mqtt.username, sonde.config.mqtt.password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTT::updateSonde( SondeInfo *si ) {
|
||||
if(!sonde.config.mqtt.active)
|
||||
return;
|
||||
|
||||
if(1 /*connected*/) {
|
||||
Serial.println("Sending sonde info via MQTT");
|
||||
// TODO: Check if si is good / fresh
|
||||
publishPacket(si);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::updateStation( PosInfo *pi ) {
|
||||
if(!sonde.config.mqtt.active)
|
||||
return;
|
||||
|
||||
int now = millis();
|
||||
if ( (lastMqttUptime == 0 || (lastMqttUptime + 60000 < now) || (lastMqttUptime > now))) {
|
||||
publishUptime();
|
||||
lastMqttUptime = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal (private) functions
|
||||
//void MQTT::connectToMqtt() {
|
||||
// Serial.println("Connecting to MQTT...");
|
||||
// mqttClient.connect();
|
||||
//}
|
||||
|
||||
void MQTT::publishUptime()
|
||||
{
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
Serial.println("[MQTT] writing");
|
||||
char payload[256];
|
||||
// maybe TODO: Use dynamic position if GPS is available?
|
||||
// rxlat, rxlon only if not empty
|
||||
snprintf(payload, 256, "{\"uptime\": %lu, \"user\": \"%s\", ", millis(), sonde.config.mqtt.username);
|
||||
if( !isnan(sonde.config.rxlat) && !isnan(sonde.config.rxlon) ) {
|
||||
snprintf(payload, 256, "%s\"rxlat\": %.5f, \"rxlon\": %.5f, ", payload, sonde.config.rxlat, sonde.config.rxlon);
|
||||
}
|
||||
snprintf(payload, 256, "%s\"SW\": \"%s\", \"VER\": \"%s\"}", payload, version_name, version_id);
|
||||
Serial.println(payload);
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", sonde.config.mqtt.prefix, "uptime");
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
||||
|
||||
void MQTT::publishPacket(SondeInfo *si)
|
||||
{
|
||||
SondeData *s = &(si->d);
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
char payload[1024];
|
||||
payload[0] = '{';
|
||||
int n = sonde2json(payload+1, 1023, si);
|
||||
if(n<0) {
|
||||
// ERROR
|
||||
Serial.println("publishPacket: sonde2json failed, string too long");
|
||||
}
|
||||
strcat(payload, "}"); // terminate payload string
|
||||
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", sonde.config.mqtt.prefix, "packet");
|
||||
Serial.print(payload);
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
||||
|
||||
MQTT connMQTT;
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_MQTT
|
||||
|
||||
#ifndef MQTT_h
|
||||
#define MQTT_h
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
#include "Sonde.h"
|
||||
//#include "RS41.h"
|
||||
#include "conn.h"
|
||||
|
||||
class MQTT : public Conn
|
||||
{
|
||||
public:
|
||||
/* Called once on startup */
|
||||
void init();
|
||||
|
||||
/* Called whenever the network becomes available */
|
||||
void netsetup();
|
||||
|
||||
/* Called approx 1x / second (maybe only if good data is available) */
|
||||
virtual void updateSonde( SondeInfo *si );
|
||||
|
||||
/* Called approx 1x / second* */
|
||||
virtual void updateStation( PosInfo *pi );
|
||||
|
||||
|
||||
private:
|
||||
WiFiClient mqttWifiClient;
|
||||
AsyncMqttClient mqttClient;
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
IPAddress ip;
|
||||
//uint16_t port;
|
||||
//const char *username;
|
||||
//const char *password;
|
||||
//const char *prefix;
|
||||
char clientID[21];
|
||||
|
||||
//void init(const char *host, uint16_t port, const char *id, const char *username, const char *password, const char *prefix);
|
||||
void publishPacket(SondeInfo *s);
|
||||
void publishUptime();
|
||||
//void connectToMqtt();
|
||||
|
||||
unsigned long lastMqttUptime = 0;
|
||||
boolean mqttEnabled;
|
||||
};
|
||||
|
||||
extern MQTT connMQTT;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
#include "../features.h"
|
||||
|
||||
#if FEATURE_SDCARD
|
||||
|
||||
#include "conn-sdcard.h"
|
||||
|
||||
// TODO: Move into config
|
||||
#define CS 13
|
||||
#define SYNC_INTERVAL 10
|
||||
|
||||
void ConnSDCard::init() {
|
||||
/* Initialize SD card */
|
||||
initok = SD.begin(CS);
|
||||
Serial.printf("SD card init: %s\n", initok?"OK":"Failed");
|
||||
}
|
||||
|
||||
void ConnSDCard::netsetup() {
|
||||
/* empty function, we don't use any network here */
|
||||
}
|
||||
|
||||
void ConnSDCard::updateSonde( SondeInfo *si ) {
|
||||
if (!initok) return;
|
||||
if (!file) {
|
||||
file = SD.open("/data.csv", FILE_APPEND);
|
||||
}
|
||||
if (!file) {
|
||||
Serial.println("Error opening file");
|
||||
return;
|
||||
}
|
||||
SondeData *sd = &si->d;
|
||||
file.printf("%d,%s,%s,%d,"
|
||||
"%f,%f,%f,%f,%f,%f,%d,%d,"
|
||||
"%d,%d,%d,%d\n",
|
||||
sd->validID, sd->ser, sd->typestr, sd->subtype,
|
||||
sd->lat, sd->lon, sd->alt, sd->vs, sd->hs, sd->dir, sd->sats, sd->validPos,
|
||||
sd->time, sd->frame, sd->vframe, sd->validTime);
|
||||
wcount++;
|
||||
if(wcount >= SYNC_INTERVAL) {
|
||||
file.flush();
|
||||
wcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConnSDCard::updateStation( PosInfo *pi ) {
|
||||
}
|
||||
|
||||
|
||||
ConnSDCard connSDCard;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* conn-sdcard.h
|
||||
* Data exporter to SD card
|
||||
* Copyright (c) 2023 Hansi Reiser, dl9rdz
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef conn_sdcard_h
|
||||
#define conn_sdcard_h
|
||||
|
||||
#include "conn.h"
|
||||
|
||||
//#include "FS.h"
|
||||
#include "SD.h"
|
||||
|
||||
class ConnSDCard : public Conn
|
||||
{
|
||||
public:
|
||||
/* Called once on startup */
|
||||
void init();
|
||||
|
||||
/* Called whenever the network becomes available */
|
||||
void netsetup();
|
||||
|
||||
|
||||
/* Called approx 1x / second (maybe only if good data is available) */
|
||||
virtual void updateSonde( SondeInfo *si );
|
||||
|
||||
/* Called approx 1x / second* */
|
||||
virtual void updateStation( PosInfo *pi );
|
||||
|
||||
|
||||
private:
|
||||
File file;
|
||||
uint8_t initok = 0;
|
||||
uint16_t wcount = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* conn.h
|
||||
* Interface for external data exporters
|
||||
* Copyright (c) 2023 Hansi Reiser, dl9rdz
|
||||
*/
|
||||
|
||||
#ifndef conn_h
|
||||
#define conn_h
|
||||
|
||||
#include "Sonde.h"
|
||||
|
||||
|
||||
// to be moved elsewhere
|
||||
struct PosInfo {
|
||||
public:
|
||||
float lat;
|
||||
float lon;
|
||||
};
|
||||
|
||||
|
||||
/* Interface for all data exporters */
|
||||
class Conn
|
||||
{
|
||||
public:
|
||||
/* Called once on startup */
|
||||
virtual void init();
|
||||
|
||||
/* Called whenever the network becomes available */
|
||||
virtual void netsetup();
|
||||
|
||||
/* Called approx 1x / second (maybe only if good data is available) */
|
||||
virtual void updateSonde( SondeInfo *si );
|
||||
|
||||
/* Called approx 1x / second* */
|
||||
virtual void updateStation( PosInfo *pi );
|
||||
|
||||
};
|
||||
#endif
|
|
@ -1,3 +1,6 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_RS92
|
||||
|
||||
#include "time.h"
|
||||
#include "geteph.h"
|
||||
#include <SPIFFS.h>
|
||||
|
@ -14,7 +17,7 @@ extern WiFiClient client;
|
|||
char outbuf[128];
|
||||
uint8_t ephstate = EPH_NOTUSED;
|
||||
//enum EPHSTATE { EPH_NOTUSED, EPH_PENDING, EPH_TIMEERR, EPH_ERROR, EPH_EPHERROR, EPH_GOOD };
|
||||
const char *ephtxt[] = { "Disabled", "Pending", "Time error", "Fetch error", "Read error", "Good" };
|
||||
const char *ephtxt[] = { "Disabled (no RS92 in QRG list or Wifi mode not 3)", "Pending", "Time error", "Fetch error", "Read error", "Good" };
|
||||
|
||||
uint8_t getreply() {
|
||||
String s = client.readStringUntil('\n');
|
||||
|
@ -83,22 +86,25 @@ void geteph() {
|
|||
Serial.println("cannot open file\n");
|
||||
return;
|
||||
}
|
||||
char host[252];
|
||||
strcpy(host, sonde.config.ephftp);
|
||||
char *buf = strchr(host, '/');
|
||||
if(!buf) { Serial.println("Invalid FTP host config"); return; }
|
||||
*buf = 0;
|
||||
buf++;
|
||||
char host[100];
|
||||
char buf[200];
|
||||
char *ptr = strchr(sonde.config.ephftp, '/');
|
||||
if(!ptr) { Serial.println("Invalid FTP host config"); return; }
|
||||
int hlen = ptr - sonde.config.ephftp;
|
||||
strncpy(host, sonde.config.ephftp, hlen);
|
||||
host[hlen] = 0;
|
||||
snprintf(buf, 200, ptr+1, year, day, year-2000);
|
||||
uint8_t dispw, disph, dispxs, dispys;
|
||||
disp.rdis->getDispSize(&disph, &dispw, &dispxs, &dispys);
|
||||
disp.rdis->clear();
|
||||
disp.rdis->setFont(FONT_SMALL);
|
||||
disp.rdis->drawString(0, 0, host);
|
||||
// fetch rinex from server
|
||||
char *ptr = buf + strlen(buf);
|
||||
snprintf(ptr, 128, "%04d/%03d/brdc%03d0.%02dn.gz", year, day, day, year-2000);
|
||||
// char *ptr = buf + strlen(buf);
|
||||
// snprintf(ptr, 128, "%04d/%03d/brdc%03d0.%02dn.gz", year, day, day, year-2000);
|
||||
// snprintf(ptr, 128, "%04d/brdc/brdc%03d0.%02dn.gz", year, /*day,*/ day, year-2000);
|
||||
Serial.println("running geteph\n");
|
||||
disp.rdis->drawString(0, 1*dispys, ptr+9);
|
||||
disp.rdis->drawString(0, 1*dispys, buf+9);
|
||||
|
||||
if(!client.connect(host, 21)) {
|
||||
Serial.printf("FTP connection to %s failed\n", host);
|
||||
|
@ -236,3 +242,4 @@ void geteph() {
|
|||
file.close();
|
||||
ofile.close();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
#include <Arduino.h>
|
||||
#include "mqtt.h"
|
||||
#include <WiFi.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "RS41.h"
|
||||
#include "json.h"
|
||||
|
||||
extern const char *version_name;
|
||||
extern const char *version_id;
|
||||
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
|
||||
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
||||
Serial.print("Message arrived [");
|
||||
Serial.print(topic);
|
||||
Serial.print("] ");
|
||||
for (int i=0;i<length;i++) {
|
||||
Serial.print((char)payload[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
static char buffer[21];
|
||||
void MQTT::init(const char* host, uint16_t port, const char* id, const char *username, const char *password, const char *prefix)
|
||||
{
|
||||
WiFi.hostByName(host, this->ip);
|
||||
this->port = port;
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->prefix = prefix;
|
||||
|
||||
Serial.println("[MQTT] pubsub client");
|
||||
mqttClient.setServer(ip, port);
|
||||
snprintf(buffer, 20, "%s%04d", id, (int)random(0, 1000));
|
||||
buffer[20] = 0;
|
||||
Serial.print(buffer);
|
||||
mqttClient.setClientId(buffer);
|
||||
if (strlen(password) > 0) {
|
||||
mqttClient.setCredentials(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::connectToMqtt() {
|
||||
Serial.println("Connecting to MQTT...");
|
||||
mqttClient.connect();
|
||||
}
|
||||
|
||||
void MQTT::publishUptime()
|
||||
{
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
Serial.println("[MQTT] writing");
|
||||
char payload[256];
|
||||
// maybe TODO: Use dynamic position if GPS is available?
|
||||
// rxlat, rxlon only if not empty
|
||||
snprintf(payload, 256, "{\"uptime\": %lu, \"user\": \"%s\", ", millis(), username);
|
||||
if( !isnan(sonde.config.rxlat) && !isnan(sonde.config.rxlon) ) {
|
||||
snprintf(payload, 256, "%s\"rxlat\": %.5f, \"rxlon\": %.5f, ", payload, sonde.config.rxlat, sonde.config.rxlon);
|
||||
}
|
||||
snprintf(payload, 256, "%s\"SW\": \"%s\", \"VER\": \"%s\"}", payload, version_name, version_id);
|
||||
Serial.println(payload);
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", this->prefix, "uptime");
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
||||
|
||||
void MQTT::publishPacket(SondeInfo *si)
|
||||
{
|
||||
SondeData *s = &(si->d);
|
||||
mqttClient.connect(); // ensure we've got connection
|
||||
|
||||
char payload[1024];
|
||||
payload[0] = '{';
|
||||
int n = sonde2json(payload+1, 1023, si);
|
||||
if(n<0) {
|
||||
// ERROR
|
||||
Serial.println("publishPacket: sonde2json failed, string too long");
|
||||
}
|
||||
|
||||
#if 0
|
||||
snprintf(payload, 1024, "{"
|
||||
"\"active\": %d,"
|
||||
"\"freq\": %.2f,"
|
||||
"\"id\": \"%s\","
|
||||
"\"ser\": \"%s\","
|
||||
"\"validId\": %d,"
|
||||
"\"launchsite\": \"%s\","
|
||||
"\"lat\": %.5f,"
|
||||
"\"lon\": %.5f,"
|
||||
"\"alt\": %.1f,"
|
||||
"\"vs\": %.1f,"
|
||||
"\"hs\": %.1f,"
|
||||
"\"dir\": %.1f,"
|
||||
"\"sats\": %d,"
|
||||
"\"validPos\": %d,"
|
||||
"\"time\": %u,"
|
||||
"\"frame\": %u,"
|
||||
"\"validTime\": %d,"
|
||||
"\"rssi\": %d,"
|
||||
"\"afc\": %d,"
|
||||
"\"rxStat\": \"%s\","
|
||||
"\"rxStart\": %u,"
|
||||
"\"norxStart\": %u,"
|
||||
"\"viewStart\": %u,"
|
||||
"\"lastState\": %d,"
|
||||
"\"launchKT\": %d,"
|
||||
"\"burstKT\": %d,"
|
||||
"\"countKT\": %d,"
|
||||
"\"crefKT\": %d",
|
||||
(int)si->active,
|
||||
si->freq,
|
||||
s->id,
|
||||
s->ser,
|
||||
(int)s->validID,
|
||||
si->launchsite,
|
||||
s->lat,
|
||||
s->lon,
|
||||
s->alt,
|
||||
s->vs,
|
||||
s->hs,
|
||||
s->dir,
|
||||
s->sats,
|
||||
s->validPos,
|
||||
s->time,
|
||||
s->frame,
|
||||
(int)s->validTime,
|
||||
si->rssi,
|
||||
si->afc,
|
||||
si->rxStat,
|
||||
si->rxStart,
|
||||
si->norxStart,
|
||||
si->viewStart,
|
||||
si->lastState,
|
||||
s->launchKT,
|
||||
s->burstKT,
|
||||
s->countKT,
|
||||
s->crefKT
|
||||
);
|
||||
if ( !isnan( s->temperature ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"temp\": ", s->temperature );
|
||||
}
|
||||
if ( !isnan( s->relativeHumidity ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"humidity\": ", s->relativeHumidity );
|
||||
}
|
||||
if ( !isnan( s->pressure ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"pressure\": ", s->pressure );
|
||||
}
|
||||
if ( !isnan( s->batteryVoltage && s->batteryVoltage > 0 ) ) {
|
||||
snprintf(payload, 1024, "%s%s%.1f", payload, ",\"batt\": ", s->batteryVoltage );
|
||||
}
|
||||
char subtype[11];
|
||||
if ( RS41::getSubtype( subtype, 11, si) == 0 ) {
|
||||
snprintf(payload, 1024, "%s%s%s%s", payload, ",\"subtype\": \"", subtype, "\"" );
|
||||
}
|
||||
snprintf(payload, 1024, "%s%s", payload, "}" ); // terminate payload string
|
||||
#endif
|
||||
strcat(payload, "}"); // terminate payload string
|
||||
|
||||
char topic[128];
|
||||
snprintf(topic, 128, "%s%s", this->prefix, "packet");
|
||||
Serial.print(payload);
|
||||
mqttClient.publish(topic, 1, 1, payload);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef MQTT_h
|
||||
#define MQTT_h
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
#include "Sonde.h"
|
||||
#include "RS41.h"
|
||||
|
||||
class MQTT
|
||||
{
|
||||
public:
|
||||
WiFiClient mqttWifiClient;
|
||||
AsyncMqttClient mqttClient;
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
IPAddress ip;
|
||||
uint16_t port;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *prefix;
|
||||
|
||||
void init(const char *host, uint16_t port, const char *id, const char *username, const char *password, const char *prefix);
|
||||
void publishPacket(SondeInfo *s);
|
||||
void publishUptime();
|
||||
private:
|
||||
void connectToMqtt();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,3 +1,6 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_RS92
|
||||
|
||||
/* SPDX-License-Identifier: GPL-3.0
|
||||
* based on https://github.com/rs1729/RS/blob/master/rs92/nav_gps_vel.c
|
||||
*
|
||||
|
@ -1713,3 +1716,4 @@ int NAV_LinV(int N, SAT_t satv[], double pos_ecef[3],
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,545 @@
|
|||
#include <stdio.h>
|
||||
#include <Wire.h>
|
||||
#include "pmu.h"
|
||||
#include "Sonde.h"
|
||||
|
||||
// 0: cleared; 1: set; 2: do not check, also query state of axp via i2c on each loop
|
||||
uint8_t pmu_irq = 0;
|
||||
#define PMU_IRQ 35
|
||||
|
||||
#define AXP192_VMIN 1800
|
||||
#define AXP192_VSTEP 100
|
||||
|
||||
|
||||
#define AXP192_IC_TYPE (0x03)
|
||||
|
||||
#define AXP192_DC_MIN 700
|
||||
#define AXP192_DC_STEPS 25
|
||||
|
||||
#define AXP192_LDO_MIN (1800)
|
||||
#define AXP192_LDO_STEPS (100)
|
||||
|
||||
#define AXP192_VOLTREG_DC1
|
||||
|
||||
// some registers:
|
||||
#define AXP192_STATUS (0x00)
|
||||
#define AXP192_MODE_CHGSTATUS (0x01)
|
||||
|
||||
// Power voltage control register
|
||||
#define AXP192_DC2OUT_VOL (0x23)
|
||||
#define AXP192_DC1OUT_VOL (0x26)
|
||||
#define AXP192_DC3OUT_VOL (0x27)
|
||||
#define AXP192_LDO23OUT_VOL (0x28)
|
||||
#define AXP192_GPIO0_VOL (0x91)
|
||||
|
||||
// Power enable registers
|
||||
#define AXP192_LDO23_DC123_EXT_CTL (0x12)
|
||||
|
||||
// ADC control
|
||||
#define AXP192_ADC_EN1 (0x82)
|
||||
|
||||
// ADC results
|
||||
#define AXP192_BAT_AVERVOL_H8 (0x78)
|
||||
#define AXP192_BAT_AVERVOL_L4 (0x79)
|
||||
#define AXP192_BAT_AVERCHGCUR_H8 (0x7A)
|
||||
#define AXP192_BAT_AVERCHGCUR_L4 (0x7B)
|
||||
#define AXP192_BAT_AVERCHGCUR_L5 (0x7B)
|
||||
#define AXP192_ACIN_VOL_H8 (0x56)
|
||||
#define AXP192_ACIN_VOL_L4 (0x57)
|
||||
#define AXP192_ACIN_CUR_H8 (0x58)
|
||||
#define AXP192_ACIN_CUR_L4 (0x59)
|
||||
#define AXP192_VBUS_VOL_H8 (0x5A)
|
||||
#define AXP192_VBUS_VOL_L4 (0x5B)
|
||||
#define AXP192_VBUS_CUR_H8 (0x5C)
|
||||
#define AXP192_VBUS_CUR_L4 (0x5D)
|
||||
#define AXP192_INTERNAL_TEMP_H8 (0x5E)
|
||||
#define AXP192_INTERNAL_TEMP_L4 (0x5F)
|
||||
#define AXP192_TS_IN_H8 (0x62)
|
||||
#define AXP192_TS_IN_L4 (0x63)
|
||||
#define AXP192_GPIO0_VOL_ADC_H8 (0x64)
|
||||
#define AXP192_GPIO0_VOL_ADC_L4 (0x65)
|
||||
#define AXP192_GPIO1_VOL_ADC_H8 (0x66)
|
||||
#define AXP192_GPIO1_VOL_ADC_L4 (0x67)
|
||||
#define AXP192_BAT_AVERDISCHGCUR_H8 (0x7C)
|
||||
#define AXP192_BAT_AVERDISCHGCUR_L5 (0x7D)
|
||||
|
||||
|
||||
// Interrupt enable
|
||||
#define AXP192_INTEN1 (0x40)
|
||||
#define AXP192_INTEN2 (0x41)
|
||||
#define AXP192_INTEN3 (0x42)
|
||||
#define AXP192_INTEN4 (0x43)
|
||||
#define AXP192_INTEN5 (0x4A)
|
||||
|
||||
// Int clear.
|
||||
#define AXP192_INTSTS1 (0x44)
|
||||
#define AXP192_INTSTS2 (0x45)
|
||||
#define AXP192_INTSTS3 (0x46)
|
||||
#define AXP192_INTSTS4 (0x47)
|
||||
#define AXP192_INTSTS5 (0x4D)
|
||||
|
||||
extern SemaphoreHandle_t axpSemaphore;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/// High-level functions
|
||||
PMU *PMU::getInstance(TwoWire &wire) {
|
||||
PMU *pmu = NULL;
|
||||
// Check if there is some AXP192 or AXP2101 present
|
||||
uint8_t chipid = readRegisterWire(wire, AXP192_IC_TYPE);
|
||||
// AXP192: 0x03 AXP2101: 0x4A
|
||||
if(chipid==0x03) {
|
||||
pmu = new AXP192PMU(wire);
|
||||
}
|
||||
else if (chipid==0x4A) {
|
||||
pmu = new AXP2101PMU(wire);
|
||||
}
|
||||
return pmu;
|
||||
}
|
||||
|
||||
|
||||
int PMU::readRegisterWire(TwoWire &wire, uint8_t reg) {
|
||||
wire.beginTransmission(AXP192_SLAVE_ADDRESS);
|
||||
wire.write(reg);
|
||||
if (wire.endTransmission() != 0) {
|
||||
return -1;
|
||||
}
|
||||
wire.requestFrom(AXP192_SLAVE_ADDRESS, 1U);
|
||||
return wire.read();
|
||||
}
|
||||
int PMU::readRegister(uint8_t reg) {
|
||||
return readRegisterWire(_wire, reg);
|
||||
}
|
||||
uint16_t PMU::readRegisters_8_4(uint8_t regh, uint8_t regl)
|
||||
{
|
||||
uint8_t hi = readRegister(regh);
|
||||
uint8_t lo = readRegister(regl);
|
||||
return (hi << 4) | (lo & 0x0F);
|
||||
}
|
||||
|
||||
uint16_t PMU::readRegisters_8_5(uint8_t regh, uint8_t regl)
|
||||
{
|
||||
uint8_t hi = readRegister(regh);
|
||||
uint8_t lo = readRegister(regl);
|
||||
return (hi << 5) | (lo & 0x1F);
|
||||
}
|
||||
|
||||
int PMU::writeRegister(uint8_t reg, uint8_t val) {
|
||||
_wire.beginTransmission(AXP192_SLAVE_ADDRESS);
|
||||
_wire.write(reg);
|
||||
_wire.write(val);
|
||||
return (_wire.endTransmission() == 0) ? 0 : -1;
|
||||
}
|
||||
int PMU::getRegisterBit(uint8_t reg, uint8_t bit) {
|
||||
int val = readRegister(reg);
|
||||
if (val == -1) { return -1; }
|
||||
return (val >> bit) & 0x01;
|
||||
}
|
||||
int PMU::setRegisterBit(uint8_t reg, uint8_t bit) {
|
||||
int val = readRegister(reg);
|
||||
if (val == -1) { return -1; }
|
||||
return writeRegister(reg, (val | (1<<bit)));
|
||||
}
|
||||
int PMU::clearRegisterBit(uint8_t reg, uint8_t bit) {
|
||||
int val = readRegister(reg);
|
||||
if (val == -1) { return -1; }
|
||||
return writeRegister(reg, (val & ( ~(1<<bit))));
|
||||
}
|
||||
|
||||
// Returns if there was a keypress, using the following enum defined in RX_FSK.ini:
|
||||
enum KeyPress { KP_NONE = 0, KP_SHORT, KP_DOUBLE, KP_MID, KP_LONG };
|
||||
|
||||
int PMU::handleIRQ() {
|
||||
if (pmu_irq) {
|
||||
Serial.println("PMU_IRQ is set\n");
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
int keypress = -1;
|
||||
xSemaphoreTake( axpSemaphore, portMAX_DELAY );
|
||||
keypress = getIrqKeyStatus();
|
||||
if(keypress) { Serial.printf("Keypress: %d (%s)", keypress, keypress==KP_SHORT?"short":"mid"); }
|
||||
if (pmu_irq != 2) {
|
||||
pmu_irq = 0;
|
||||
}
|
||||
xSemaphoreGive( axpSemaphore );
|
||||
return keypress;
|
||||
}
|
||||
|
||||
int AXP192PMU::init() {
|
||||
// Initialize AXP192, for T-BEAM v1.1 or M5Stack
|
||||
|
||||
// LDO2: LoRa VCC on T-BEAM, PERI_VDD on M5Core2 (LCD)
|
||||
setLDO2(3300);
|
||||
enableLDO2();
|
||||
if(sonde.config.type == TYPE_M5_CORE2) {
|
||||
// Display backlight (LCD_BL) on M5 Core2
|
||||
setDC3(3300);
|
||||
enableDC3();
|
||||
pmu_irq = 2; // IRQ pin not connected on Core2
|
||||
// Set GPIO0 VDO to 3.3V (as is done by original M5Stack software)
|
||||
// (default value 2.8V did not have the expected effect :))
|
||||
setLDOio(3300);
|
||||
// ADC configuration: Enable monitoring of AC [bits 4,5 in enable register]
|
||||
uint8_t val = readRegister(AXP192_ADC_EN1);
|
||||
writeRegister(AXP192_ADC_EN1, val | (1 << 4) | (1 << 5) );
|
||||
} else {
|
||||
// T-Beam specific
|
||||
// GPS power on T-Beam (its the buzzer on M5 Core2, so only enable for T-Beam)
|
||||
enableLDO3();
|
||||
// ADC configuration: Enable monitoring of USB [bits 2,3 in enable register]
|
||||
uint8_t val = readRegister(AXP192_ADC_EN1);
|
||||
writeRegister(AXP192_ADC_EN1, val | (1 << 4) | (1 << 5) );
|
||||
}
|
||||
// Common configuration for T-Beam and M5 Core2
|
||||
// DCDC2: M5Core: Unused, T-Beam: Unused, so set to disabled!! (was enabled in previous versions)
|
||||
enableDC2(false);
|
||||
|
||||
// EXTEN: M5Core2: 5V Boost enable; T-Beam EXTEN
|
||||
enableEXTEN();
|
||||
|
||||
// DCDC1: M5Core: MCU_VDD, T-Beam 1.1: "VCC_2.5V" == 3V3-Pin on pin header on board
|
||||
setDC1(3300);
|
||||
enableDC1();
|
||||
|
||||
// ADC configuration: Enable monitor batt current [bit 6 in eable register]
|
||||
uint8_t val = readRegister(AXP192_ADC_EN1);
|
||||
writeRegister(AXP192_ADC_EN1, val | (1 << 6) );
|
||||
|
||||
if (pmu_irq != 2) {
|
||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
||||
attachInterrupt(PMU_IRQ, [] {
|
||||
pmu_irq = 1;
|
||||
}, FALLING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Helper functions
|
||||
|
||||
int AXP192PMU::getIrqKeyStatus() {
|
||||
int status = readRegister(AXP192_INTSTS3);
|
||||
|
||||
// Also clear IRQ status
|
||||
writeRegister(AXP192_INTSTS1, 0xFF);
|
||||
writeRegister(AXP192_INTSTS2, 0xFF);
|
||||
writeRegister(AXP192_INTSTS3, 0xFF);
|
||||
writeRegister(AXP192_INTSTS4, 0xFF);
|
||||
writeRegister(AXP192_INTSTS5, 0xFF);
|
||||
|
||||
//
|
||||
if ( status & 0x01 ) return KP_MID;
|
||||
if ( status & 0x02 ) return KP_SHORT;
|
||||
return KP_NONE;
|
||||
}
|
||||
|
||||
|
||||
void AXP192PMU::disableAllIRQ() {
|
||||
writeRegister(AXP192_INTEN1, 0);
|
||||
writeRegister(AXP192_INTEN2, 0);
|
||||
writeRegister(AXP192_INTEN3, 0);
|
||||
writeRegister(AXP192_INTEN4, 0);
|
||||
writeRegister(AXP192_INTEN5, 0);
|
||||
}
|
||||
|
||||
void AXP192PMU::_enableIRQ(uint8_t addr, uint8_t mask) {
|
||||
int data = readRegister(addr);
|
||||
writeRegister(addr, data | mask);
|
||||
}
|
||||
|
||||
// we want KP_SHORT and KP_LONG interrupts...
|
||||
// IRQ4, in reg 0x42h, Bit 16+17
|
||||
void AXP192PMU::enableIRQ() {
|
||||
//_enableIRQ( AXP192_INTEN1, mask&0xFF );
|
||||
//_enableIRQ( AXP192_INTEN2, mask>>8 );
|
||||
_enableIRQ( AXP192_INTEN3, 0x03 );
|
||||
//_enableIRQ( AXP192_INTEN4, mask>>24 );
|
||||
//_enableIRQ( AXP192_INTEN5, mask>>32 );
|
||||
}
|
||||
|
||||
// Functions for setting voltage output levels
|
||||
int AXP192PMU::setVoltageReg(uint8_t reg, uint8_t regval) {
|
||||
int val = readRegister(reg);
|
||||
if (val==-1) return -1;
|
||||
val &= 0x80;
|
||||
val |= regval;
|
||||
return writeRegister(reg, val);
|
||||
}
|
||||
|
||||
int AXP192PMU::setDC1(uint16_t millivolt) {
|
||||
return setVoltageReg(AXP192_DC1OUT_VOL, (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
||||
}
|
||||
int AXP192PMU::setDC2(uint16_t millivolt) {
|
||||
return setVoltageReg(AXP192_DC2OUT_VOL, (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
||||
}
|
||||
int AXP192PMU::setDC3(uint16_t millivolt) {
|
||||
return setVoltageReg(AXP192_DC3OUT_VOL , (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
||||
}
|
||||
int AXP192PMU::setLDO2(uint16_t millivolt) {
|
||||
return setVoltageReg(AXP192_LDO23OUT_VOL, (millivolt-AXP192_LDO_MIN)/AXP192_LDO_STEPS);
|
||||
}
|
||||
int AXP192PMU::setLDOio(uint16_t millivolt) {
|
||||
return setVoltageReg(AXP192_GPIO0_VOL, (millivolt-AXP192_LDO_MIN)/AXP192_LDO_STEPS);
|
||||
}
|
||||
|
||||
|
||||
// LDO23_DC123_EXT_CTL
|
||||
// 0:DC-DC1, 1:DC-DC3, 2:LDO2, 3:LDO3, 4:DC-DC2, 6:EXTEN
|
||||
int AXP192PMU::enableDC1(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0);
|
||||
}
|
||||
int AXP192PMU::enableDC3(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1);
|
||||
}
|
||||
int AXP192PMU::enableLDO2(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2);
|
||||
}
|
||||
int AXP192PMU::enableLDO3(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3);
|
||||
}
|
||||
int AXP192PMU::enableDC2(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4);
|
||||
}
|
||||
int AXP192PMU::enableEXTEN(bool onoff) {
|
||||
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6);
|
||||
}
|
||||
|
||||
int AXP192PMU::enableADC(uint8_t channels) {
|
||||
uint8_t val = readRegister(AXP192_ADC_EN1);
|
||||
return writeRegister(AXP192_ADC_EN1, val | channels );
|
||||
}
|
||||
|
||||
int AXP192PMU::isBatteryConnected() {
|
||||
return getRegisterBit(AXP192_MODE_CHGSTATUS, 5);
|
||||
}
|
||||
int AXP192PMU::isVbusIn() {
|
||||
return getRegisterBit(AXP192_STATUS, 5);
|
||||
}
|
||||
int AXP192PMU::isCharging() {
|
||||
return getRegisterBit(AXP192_MODE_CHGSTATUS, 6);
|
||||
}
|
||||
|
||||
#define AXP192_BATT_VOLTAGE_STEP (1.1F)
|
||||
float AXP192PMU::getBattVoltage() {
|
||||
return readRegisters_8_4(AXP192_BAT_AVERVOL_H8, AXP192_BAT_AVERVOL_L4) * AXP192_BATT_VOLTAGE_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_BATT_DISCHARGE_CUR_STEP (0.5F)
|
||||
float AXP192PMU::getBattDischargeCurrent() {
|
||||
return readRegisters_8_5(AXP192_BAT_AVERDISCHGCUR_H8, AXP192_BAT_AVERDISCHGCUR_L5) * AXP192_BATT_DISCHARGE_CUR_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_BATT_CHARGE_CUR_STEP (0.5F)
|
||||
float AXP192PMU::getBattChargeCurrent() {
|
||||
return readRegisters_8_5(AXP192_BAT_AVERCHGCUR_H8, AXP192_BAT_AVERCHGCUR_L5) * AXP192_BATT_CHARGE_CUR_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_ACIN_VOLTAGE_STEP (1.7F)
|
||||
float AXP192PMU::getAcinVoltage() {
|
||||
return readRegisters_8_4(AXP192_ACIN_VOL_H8, AXP192_ACIN_VOL_L4) * AXP192_ACIN_VOLTAGE_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_ACIN_CUR_STEP (0.625F)
|
||||
float AXP192PMU::getAcinCurrent() {
|
||||
return readRegisters_8_4(AXP192_ACIN_CUR_H8, AXP192_ACIN_CUR_L4) * AXP192_ACIN_CUR_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_VBUS_VOLTAGE_STEP (1.7F)
|
||||
float AXP192PMU::getVbusVoltage() {
|
||||
return readRegisters_8_4(AXP192_VBUS_VOL_H8, AXP192_VBUS_VOL_L4) * AXP192_VBUS_VOLTAGE_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_VBUS_CUR_STEP (0.375F)
|
||||
float AXP192PMU::getVbusCurrent() {
|
||||
return readRegisters_8_4(AXP192_VBUS_CUR_H8, AXP192_VBUS_CUR_L4) * AXP192_VBUS_CUR_STEP;
|
||||
}
|
||||
|
||||
#define AXP192_INTERNAL_TEMP_STEP (0.1F)
|
||||
float AXP192PMU::getTemperature() {
|
||||
return readRegisters_8_4(AXP192_INTERNAL_TEMP_H8, AXP192_INTERNAL_TEMP_L4) * AXP192_INTERNAL_TEMP_STEP - 144.7;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
/////// Functions for AXP2101
|
||||
|
||||
// Registers
|
||||
#define AXP2101_CHARGE_GAUGE_WDT_CTRL (0x18)
|
||||
#define AXP2101_BTN_BAT_CHG_VOL_SET (0x6A)
|
||||
#define AXP2101_DC_ONOFF_DVM_CTRL (0x80)
|
||||
#define AXP2101_LDO_ONOFF_CTRL0 (0x90)
|
||||
#define AXP2101_LDO_ONOFF_CTRL1 (0x91)
|
||||
|
||||
#define AXP2101_LDO_VOL1_CTRL (0x93)
|
||||
#define AXP2101_LDO_VOL2_CTRL (0x94)
|
||||
|
||||
#define AXP2101_ADC_CHANNEL_CTRL (0x30)
|
||||
|
||||
// vterm_cfg: Bit 2:0, 4.2V = 011 (3)
|
||||
#define AXP2101_CHG_V_CFG (0x64)
|
||||
// ICC_CFG: Bit 4:0: constant current charge current limit, 25*N mA (N<=8), 200+100*(N-8) (N>8)
|
||||
#define AXP2101_ICC_CFG (0x62)
|
||||
|
||||
// Interrupt enable
|
||||
#define AXP2101_INTEN1 (0x40)
|
||||
#define AXP2101_INTEN2 (0x41)
|
||||
#define AXP2101_INTEN3 (0x42)
|
||||
|
||||
// Interrupt status
|
||||
#define AXP2101_INTSTS1 (0x48)
|
||||
#define AXP2101_INTSTS2 (0x49)
|
||||
#define AXP2101_INTSTS3 (0x4A)
|
||||
|
||||
// Constants
|
||||
#define AXP2101_ALDO_VOL_MIN (500)
|
||||
#define AXP2101_ALDO_VOL_STEPS (100)
|
||||
|
||||
#define AXP2101_BTN_VOL_MIN (2600)
|
||||
#define AXP2101_BTN_VOL_STEPS (100)
|
||||
|
||||
// 200 + 100*(11-8) = 500
|
||||
#define AXP2101_CHG_CUR_500MA (0x0B)
|
||||
#define AXP2101_CHG_VOL_4V2 (3)
|
||||
|
||||
|
||||
// return 0: ok, -1: error
|
||||
int AXP2101PMU::init() {
|
||||
// Initialize AXP2101, for T-BEAM v1.2
|
||||
|
||||
// Hard-coded for now, disable DC2/3/4/5 ALDO1,4 BLDO1/2 DLDO1/2
|
||||
int val = readRegister(AXP2101_DC_ONOFF_DVM_CTRL);
|
||||
writeRegister(AXP2101_DC_ONOFF_DVM_CTRL, val & (~0x1E)); // clear Bit 1,2,3,4 (DC2/3/4/5)
|
||||
|
||||
// clear bit 0 (aldo1), 3 (aldo4), 4,5(bldo1/2), 7 (dldo1)
|
||||
val = readRegister(AXP2101_LDO_ONOFF_CTRL0);
|
||||
writeRegister(AXP2101_LDO_ONOFF_CTRL0, val & (~0xB9));
|
||||
|
||||
// clear bit 0 (dldo2)
|
||||
val = readRegister(AXP2101_LDO_ONOFF_CTRL1);
|
||||
writeRegister(AXP2101_LDO_ONOFF_CTRL1, val & (~0x01));
|
||||
|
||||
// Set PowerVDD to 3100mV (GNSS RTC) -- reg 6A [MS412FE data sheet: charge volt 2.8-3.3; standard value 3.1]
|
||||
val = readRegister(AXP2101_BTN_BAT_CHG_VOL_SET);
|
||||
if (val == -1) return -1;
|
||||
val &= 0xF8;
|
||||
val |= (3100 - AXP2101_BTN_VOL_MIN) / AXP2101_BTN_VOL_STEPS;
|
||||
writeRegister(AXP2101_BTN_BAT_CHG_VOL_SET, val);
|
||||
|
||||
setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2);
|
||||
|
||||
// ESP32 VDD 3300mV
|
||||
// No need to set, automatically open , Don't close it
|
||||
|
||||
// LoRa VDD 3300mV on ALDO2
|
||||
val = readRegister(AXP2101_LDO_VOL1_CTRL);
|
||||
if (val == -1) return -1;
|
||||
val &= 0xE0;
|
||||
val |= (3300 - AXP2101_ALDO_VOL_MIN) / AXP2101_ALDO_VOL_STEPS;
|
||||
writeRegister(AXP2101_LDO_VOL1_CTRL, val);
|
||||
setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 1);
|
||||
|
||||
// GNSS VDD 3300mV on ALDO3
|
||||
val = readRegister(AXP2101_LDO_VOL2_CTRL);
|
||||
if (val == -1) return -1;
|
||||
val &= 0xE0;
|
||||
val |= (3300 - AXP2101_ALDO_VOL_MIN) / AXP2101_ALDO_VOL_STEPS;
|
||||
writeRegister(AXP2101_LDO_VOL2_CTRL, val);
|
||||
setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 2);
|
||||
|
||||
if (pmu_irq != 2) {
|
||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
||||
attachInterrupt(PMU_IRQ, [] {
|
||||
pmu_irq = 1;
|
||||
}, FALLING);
|
||||
}
|
||||
|
||||
// Set charging configuration: 500mA, 4.2V cut off
|
||||
|
||||
// Set constant current charge limit to 500mA (reguster 0x62)
|
||||
// Data sheep (7.3.3.) tells that default value is 1.024 A (which should be fine??)
|
||||
// Data sheet (register table) tells that default value is "{EFUSE,0b,EFUSE}", whatever that is
|
||||
// Let's set this to 500 mA manually to be sure
|
||||
val = readRegister(AXP2101_ICC_CFG);
|
||||
if (val == -1) return -1;
|
||||
val &= 0xE0;
|
||||
writeRegister(AXP2101_ICC_CFG, val | AXP2101_CHG_CUR_500MA);
|
||||
|
||||
#if 0
|
||||
// Set cut-off voltage to 4.2V (register 0x63)
|
||||
// This is the default value, so setting it should not be needed.
|
||||
val = readRegister(AXP2101_CHG_V_CFG);
|
||||
if (val == -1) return -1;
|
||||
val &= 0xFC;
|
||||
writeRegister(AXP2101_CHG_V_CFG, val | AXP2101_CHG_VOL_4V2);
|
||||
#endif
|
||||
|
||||
// Disable TS measurement, enable vsys, vbus, vbat measurement
|
||||
// Disable TS is important for T-Beam 1.2 (no TS thermistor), otherwise it will not charge.
|
||||
writeRegister(AXP2101_ADC_CHANNEL_CTRL, 0x0d);
|
||||
|
||||
// Clear all IRQ
|
||||
getIrqKeyStatus();
|
||||
|
||||
// precharge current (reg 0x61): default value (0101b) should be fine
|
||||
// Termination current (125mA default value) should be fine as well
|
||||
#if 0
|
||||
// Just some debug code
|
||||
Serial.println("All good \n");
|
||||
|
||||
for(int i=0; i<0x80; i++) {
|
||||
val = readRegister(i);
|
||||
Serial.printf("Reg %x: %x (%d)\n", i, val, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AXP2101PMU::disableAllIRQ() {
|
||||
writeRegister(AXP2101_INTEN1, 0);
|
||||
writeRegister(AXP2101_INTEN2, 0);
|
||||
writeRegister(AXP2101_INTEN3, 0);
|
||||
}
|
||||
|
||||
void AXP2101PMU::_enableIRQ(uint8_t addr, uint8_t mask) {
|
||||
int data = readRegister(addr);
|
||||
writeRegister(addr, data | mask);
|
||||
}
|
||||
|
||||
// we want KP_SHORT and KP_LONG interrupts...
|
||||
// IRQen1, in req 0x41h, Bit 2(long)+3(short) (10+11 global)
|
||||
void AXP2101PMU::enableIRQ() {
|
||||
//_enableIRQ( AXP2101_INTEN1, mask&0xFF );
|
||||
_enableIRQ( AXP2101_INTEN2, 0x0C );
|
||||
//_enableIRQ( AXP2101_INTEN3, 0x03 );
|
||||
}
|
||||
|
||||
int AXP2101PMU::getIrqKeyStatus() {
|
||||
int status = readRegister(AXP2101_INTSTS2);
|
||||
|
||||
// Also clear IRQ status
|
||||
writeRegister(AXP2101_INTSTS1, 0xFF);
|
||||
writeRegister(AXP2101_INTSTS2, 0xFF);
|
||||
writeRegister(AXP2101_INTSTS3, 0xFF);
|
||||
|
||||
//
|
||||
if ( status & 0x04 ) return KP_MID;
|
||||
if ( status & 0x08 ) return KP_SHORT;
|
||||
return KP_NONE;
|
||||
}
|
||||
|
||||
int AXP2101PMU::isBatteryConnected() { return -1; }
|
||||
int AXP2101PMU::isVbusIn() { return -1; }
|
||||
int AXP2101PMU::isCharging() { return -1; }
|
||||
float AXP2101PMU::getBattVoltage() { return -1; }
|
||||
float AXP2101PMU::getBattDischargeCurrent() { return -1; }
|
||||
float AXP2101PMU::getBattChargeCurrent() { return -1; }
|
||||
float AXP2101PMU::getAcinVoltage() { return -1; }
|
||||
float AXP2101PMU::getAcinCurrent() { return -1; }
|
||||
float AXP2101PMU::getVbusVoltage() { return -1; }
|
||||
float AXP2101PMU::getVbusCurrent() { return -1; }
|
||||
float AXP2101PMU::getTemperature() { return -1; }
|
||||
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
#include <inttypes.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#define AXP192_SLAVE_ADDRESS 0x34
|
||||
|
||||
enum { TYPE_NONE=-1, TYPE_UNKNOWN=0, TYPE_AXP192, TYPE_AXP2101 };
|
||||
|
||||
class PMU {
|
||||
protected:
|
||||
PMU(TwoWire &wire) : _wire(wire) { };
|
||||
|
||||
public:
|
||||
TwoWire &_wire;
|
||||
static PMU *getInstance(TwoWire &wire);
|
||||
int type;
|
||||
|
||||
static int readRegisterWire(TwoWire &wire, uint8_t reg);
|
||||
int readRegister(uint8_t reg);
|
||||
uint16_t readRegisters_8_4(uint8_t reghi, uint8_t reglo);
|
||||
uint16_t readRegisters_8_5(uint8_t reghi, uint8_t reglo);
|
||||
int writeRegister(uint8_t reg, uint8_t val);
|
||||
int getRegisterBit(uint8_t register, uint8_t bit);
|
||||
int setRegisterBit(uint8_t register, uint8_t bit);
|
||||
int clearRegisterBit(uint8_t register, uint8_t bit);
|
||||
|
||||
int handleIRQ();
|
||||
|
||||
virtual int init();
|
||||
virtual void disableAllIRQ();
|
||||
virtual void enableIRQ();
|
||||
virtual int getIrqKeyStatus();
|
||||
|
||||
virtual int isBatteryConnected();
|
||||
virtual int isVbusIn();
|
||||
virtual int isCharging();
|
||||
virtual float getBattVoltage();
|
||||
virtual float getBattDischargeCurrent();
|
||||
virtual float getBattChargeCurrent();
|
||||
virtual float getAcinVoltage();
|
||||
virtual float getAcinCurrent();
|
||||
virtual float getVbusVoltage();
|
||||
virtual float getVbusCurrent();
|
||||
virtual float getTemperature();
|
||||
};
|
||||
|
||||
/* Interface */
|
||||
class AXP192PMU : public PMU {
|
||||
public:
|
||||
AXP192PMU(TwoWire &wire) : PMU(wire) { type = TYPE_AXP192; };
|
||||
int init();
|
||||
void disableAllIRQ();
|
||||
void enableIRQ();
|
||||
int getIrqKeyStatus();
|
||||
|
||||
int isBatteryConnected();
|
||||
int isVbusIn();
|
||||
int isCharging();
|
||||
float getBattVoltage();
|
||||
float getBattDischargeCurrent();
|
||||
float getBattChargeCurrent();
|
||||
float getAcinVoltage();
|
||||
float getAcinCurrent();
|
||||
float getVbusVoltage();
|
||||
float getVbusCurrent();
|
||||
float getTemperature();
|
||||
|
||||
protected:
|
||||
void _enableIRQ(uint8_t addr, uint8_t mask);
|
||||
|
||||
int setVoltageReg(uint8_t reg, uint8_t regval);
|
||||
int setDC1(uint16_t millivolt);
|
||||
int setDC2(uint16_t millivolt);
|
||||
int setDC3(uint16_t millivolt);
|
||||
int setLDO2(uint16_t millivolt);
|
||||
int setLDOio(uint16_t millivolt);
|
||||
|
||||
int enableDC1(bool onff = true);
|
||||
int enableDC3(bool onoff = true);
|
||||
int enableLDO2(bool onoff = true);
|
||||
int enableLDO3(bool onoff = true);
|
||||
int enableDC2(bool onoff = true);
|
||||
int enableEXTEN(bool onoff = true);
|
||||
|
||||
int enableADC(uint8_t channels);
|
||||
};
|
||||
|
||||
class AXP2101PMU : public PMU {
|
||||
public:
|
||||
AXP2101PMU(TwoWire &wire) : PMU(wire) { };
|
||||
int init();
|
||||
void disableAllIRQ();
|
||||
void enableIRQ();
|
||||
int getIrqKeyStatus();
|
||||
|
||||
int isBatteryConnected();
|
||||
int isVbusIn();
|
||||
int isCharging();
|
||||
float getBattVoltage();
|
||||
float getBattDischargeCurrent();
|
||||
float getBattChargeCurrent();
|
||||
float getAcinVoltage();
|
||||
float getAcinCurrent();
|
||||
float getVbusVoltage();
|
||||
float getVbusCurrent();
|
||||
float getTemperature();
|
||||
|
||||
protected:
|
||||
void _enableIRQ(uint8_t addr, uint8_t mask);
|
||||
|
||||
int setVBACKUP(uint16_t millivolt);
|
||||
int setDCDC1(uint16_t millivolt);
|
||||
int setALDO2(uint16_t millivolt);
|
||||
int setALDO3(uint16_t millivolt);
|
||||
|
||||
};
|
|
@ -0,0 +1,271 @@
|
|||
#include "posinfo.h"
|
||||
|
||||
#include <MicroNMEA.h>
|
||||
|
||||
|
||||
// Sation position obtained from GPS (if available)
|
||||
struct StationPos gpsPos;
|
||||
|
||||
// Station position to use (from GPS or fixed)
|
||||
struct StationPos posInfo;
|
||||
|
||||
|
||||
/* SH_LOC_OFF: never send position information to SondeHub
|
||||
SH_LOC_FIXED: send fixed position (if specified in config) to sondehub
|
||||
SH_LOC_CHASE: always activate chase mode and send GPS position (if available)
|
||||
SH_LOC_AUTO: if there is no valid GPS position, or GPS position < MIN_LOC_AUTO_DIST away from known fixed position: use FIXED mode
|
||||
otherwise, i.e. if there is a valid GPS position and (either no fixed position in config, or GPS position is far away from fixed position), use CHASE mode.
|
||||
*/
|
||||
// same constants used for SondeHub and APRS
|
||||
|
||||
/* auto mode is chase if valid GPS position and (no fixed location entered OR valid GPS position and distance in lat/lon deg to fixed location > threshold) */
|
||||
//#define MIN_LOC_AUTO_DIST 200 /* meter */
|
||||
//#define SH_LOC_AUTO_IS_CHASE ( gpsPos.valid && ( (isnan(sonde.config.rxlat) || isnan(sonde.config.rxlon) ) || \
|
||||
// calcLatLonDist( gpsPos.lat, gpsPos.lon, sonde.config.rxlat, sonde.config.rxlon ) > MIN_LOC_AUTO_DIST ) )
|
||||
//extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2);
|
||||
|
||||
/////
|
||||
// set fixed position based on config
|
||||
void fixedToPosInfo() {
|
||||
memset(&posInfo, 0, sizeof(posInfo));
|
||||
if( isnan(sonde.config.rxlat) || isnan(sonde.config.rxlon) )
|
||||
return;
|
||||
posInfo.lat = sonde.config.rxlat;
|
||||
posInfo.lon = sonde.config.rxlon;
|
||||
posInfo.alt = sonde.config.rxalt;
|
||||
posInfo.valid = 1;
|
||||
}
|
||||
|
||||
|
||||
///// GPS handling functions
|
||||
|
||||
static char buffer[85];
|
||||
static MicroNMEA nmea(buffer, sizeof(buffer));
|
||||
|
||||
|
||||
/// Arrg. MicroNMEA changes type definition... so lets auto-infer type
|
||||
template<typename T>
|
||||
//void unkHandler(const MicroNMEA& nmea) {
|
||||
void unkHandler(T nmea) {
|
||||
if (strcmp(nmea.getMessageID(), "VTG") == 0) {
|
||||
const char *s = nmea.getSentence();
|
||||
while (*s && *s != ',') s++;
|
||||
if (*s == ',') s++; else return;
|
||||
if (*s == ',') return; /// no new course data
|
||||
int lastCourse = nmea.parseFloat(s, 0, NULL);
|
||||
Serial.printf("Course update: %d\n", lastCourse);
|
||||
} else if (strcmp(nmea.getMessageID(), "GST") == 0) {
|
||||
// get horizontal accuracy for android app on devices without gps
|
||||
// GPGST,time,rms,-,-,-,stdlat,stdlon,stdalt,cs
|
||||
const char *s = nmea.getSentence();
|
||||
while (*s && *s != ',') s++; // #0: GST
|
||||
if (*s == ',') s++; else return;
|
||||
while (*s && *s != ',') s++; // #1: time: skip
|
||||
if (*s == ',') s++; else return;
|
||||
while (*s && *s != ',') s++; // #1: rms: skip
|
||||
if (*s == ',') s++; else return;
|
||||
while (*s && *s != ',') s++; // #1: (-): skip
|
||||
if (*s == ',') s++; else return;
|
||||
while (*s && *s != ',') s++; // #1: (-): skip
|
||||
if (*s == ',') s++; else return;
|
||||
while (*s && *s != ',') s++; // #1: (-): skip
|
||||
if (*s == ',') s++; else return;
|
||||
// stdlat
|
||||
int stdlat = nmea.parseFloat(s, 1, NULL);
|
||||
while (*s && *s != ',') s++;
|
||||
if (*s == ',') s++; else return;
|
||||
// stdlong
|
||||
int stdlon = nmea.parseFloat(s, 1, NULL);
|
||||
// calculate position error as 1-signma horizontal RMS
|
||||
// I guess that is equivalent to Androids getAccurac()?
|
||||
int poserr = 0;
|
||||
if (stdlat < 10000 && stdlon < 10000) { // larger errors: no GPS fix, avoid overflow in *
|
||||
poserr = (int)(sqrt(0.5 * (stdlat * stdlat + stdlon * stdlon)));
|
||||
}
|
||||
//Serial.printf("\nHorizontal accuracy: %d, %d => %.1fm\n", stdlat, stdlon, 0.1*poserr);
|
||||
gpsPos.accuracy = poserr;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 deg = aprox. 100 km ==> approx. 200m
|
||||
#define AUTO_CHASE_THRESHOLD 0.002
|
||||
|
||||
//#define DEBUG_GPS
|
||||
static bool gpsCourseOld;
|
||||
static int lastCourse;
|
||||
void gpsTask(void *parameter) {
|
||||
nmea.setUnknownSentenceHandler(unkHandler);
|
||||
|
||||
while (1) {
|
||||
while (Serial2.available()) {
|
||||
char c = Serial2.read();
|
||||
//Serial.print(c);
|
||||
if (nmea.process(c)) {
|
||||
gpsPos.valid = nmea.isValid();
|
||||
if (gpsPos.valid) {
|
||||
gpsPos.lon = nmea.getLongitude() * 0.000001;
|
||||
gpsPos.lat = nmea.getLatitude() * 0.000001;
|
||||
long alt = 0;
|
||||
nmea.getAltitude(alt);
|
||||
gpsPos.alt = (int)(alt / 1000);
|
||||
gpsPos.course = (int)(nmea.getCourse() / 1000);
|
||||
gpsCourseOld = false;
|
||||
if (gpsPos.course == 0) {
|
||||
// either north or not new
|
||||
if (lastCourse != 0) // use old value...
|
||||
{
|
||||
gpsCourseOld = true;
|
||||
gpsPos.course = lastCourse;
|
||||
}
|
||||
}
|
||||
if (gpsPos.lon == 0 && gpsPos.lat == 0) gpsPos.valid = false;
|
||||
}
|
||||
/* Check if home */
|
||||
if(gpsPos.valid) {
|
||||
float d = fabs(gpsPos.lon - sonde.config.rxlon);
|
||||
d += fabs(gpsPos.lat - sonde.config.rxlat);
|
||||
if(!posInfo.chase && d > AUTO_CHASE_THRESHOLD) {
|
||||
posInfo = gpsPos;
|
||||
posInfo.chase = 1;
|
||||
} else if ( posInfo.chase && d < AUTO_CHASE_THRESHOLD/2 ) {
|
||||
fixedToPosInfo();
|
||||
}
|
||||
}
|
||||
|
||||
gpsPos.hdop = nmea.getHDOP();
|
||||
gpsPos.sat = nmea.getNumSatellites();
|
||||
gpsPos.speed = nmea.getSpeed() / 1000.0 * 0.514444; // speed is in m/s nmea.getSpeed is in 0.001 knots
|
||||
#ifdef DEBUG_GPS
|
||||
uint8_t hdop = nmea.getHDOP();
|
||||
Serial.printf(" =>: valid: %d N %f E %f alt %d course:%d dop:%d\n", gpsPos.valid ? 1 : 0, gpsPos.lat, gpsPos.lon, gpsPos.alt, gpsPos.course, hdop);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define UBX_SYNCH_1 0xB5
|
||||
#define UBX_SYNCH_2 0x62
|
||||
uint8_t ubx_set9k6[] = {UBX_SYNCH_1, UBX_SYNCH_2, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x8F};
|
||||
uint8_t ubx_factorydef[] = {UBX_SYNCH_1, UBX_SYNCH_2, 0x06, 0x09, 13, 0, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x7c };
|
||||
uint8_t ubx_hardreset[] = {UBX_SYNCH_1, UBX_SYNCH_2, 0x06, 0x04, 4, 0, 0xff, 0xff, 0, 0, 0x0C, 0x5D };
|
||||
// GPGST: Class 0xF0 Id 0x07
|
||||
uint8_t ubx_enable_gpgst[] = {UBX_SYNCH_1, UBX_SYNCH_2, 0x06, 0x01, 3, 0, 0xF0, 0x07, 2, 0x03, 0x1F};
|
||||
|
||||
void dumpGPS() {
|
||||
while (Serial2.available()) {
|
||||
char c = Serial2.read();
|
||||
Serial.printf("%02x ", (uint8_t)c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void initGPS() {
|
||||
if (sonde.config.gps_rxd < 0) return; // GPS disabled
|
||||
if (sonde.config.gps_txd >= 0) { // TX enable, thus try setting baud to 9600 and do a factory reset
|
||||
File testfile = SPIFFS.open("/GPSRESET", FILE_READ);
|
||||
if (testfile && !testfile.isDirectory()) {
|
||||
testfile.close();
|
||||
Serial.println("GPS resetting baud to 9k6...");
|
||||
/* TODO: debug:
|
||||
Sometimes I have seen the Serial2.begin to cause a reset
|
||||
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
|
||||
Backtrace: 0x40081d2f:0x3ffc11b0 0x40087969:0x3ffc11e0 0x4000bfed:0x3ffb1db0 0x4008b7dd:0x3ffb1dc0 0x4017afee:0x3ffb1de0 0x4017b04b:0x3ffb1e20 0x4010722b:0x3ffb1e50 0x40107303:0x3ffb1e70 0x4010782d:0x3ffb1e90 0x40103814:0x3ffb1ed0 0x400d8772:0x3ffb1f10 0x400d9057:0x3ffb1f60 0x40107aca:0x3ffb1fb0 0x4008a63e:0x3ffb1fd0
|
||||
#0 0x40081d2f:0x3ffc11b0 in _uart_isr at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464
|
||||
#1 0x40087969:0x3ffc11e0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
|
||||
#2 0x4000bfed:0x3ffb1db0 in ?? ??:0
|
||||
#3 0x4008b7dd:0x3ffb1dc0 in vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:3507
|
||||
#4 0x4017afee:0x3ffb1de0 in esp_intr_alloc_intrstatus at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784
|
||||
#5 0x4017b04b:0x3ffb1e20 in esp_intr_alloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c:784
|
||||
#6 0x4010722b:0x3ffb1e50 in uartEnableInterrupt at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464
|
||||
#7 0x40107303:0x3ffb1e70 in uartAttachRx at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464
|
||||
#8 0x4010782d:0x3ffb1e90 in uartBegin at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-uart.c:464
|
||||
#9 0x40103814:0x3ffb1ed0 in HardwareSerial::begin(unsigned long, unsigned int, signed char, signed char, bool, unsigned long) at /Users/hansi/.platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.cpp:190
|
||||
*/
|
||||
Serial2.begin(115200, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
Serial2.write(ubx_set9k6, sizeof(ubx_set9k6));
|
||||
delay(200);
|
||||
Serial2.begin(38400, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
Serial2.write(ubx_set9k6, sizeof(ubx_set9k6));
|
||||
delay(200);
|
||||
Serial2.begin(19200, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
Serial2.write(ubx_set9k6, sizeof(ubx_set9k6));
|
||||
Serial2.begin(9600, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
delay(1000);
|
||||
dumpGPS();
|
||||
Serial.println("GPS factory reset...");
|
||||
Serial2.write(ubx_factorydef, sizeof(ubx_factorydef));
|
||||
delay(1000);
|
||||
dumpGPS();
|
||||
delay(1000);
|
||||
dumpGPS();
|
||||
delay(1000);
|
||||
dumpGPS();
|
||||
SPIFFS.remove("/GPSRESET");
|
||||
} else if (testfile) {
|
||||
Serial.println("GPS reset file: not found/isdir");
|
||||
testfile.close();
|
||||
Serial2.begin(9600, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
}
|
||||
// Enable GPGST messages
|
||||
Serial2.write(ubx_enable_gpgst, sizeof(ubx_enable_gpgst));
|
||||
} else {
|
||||
Serial2.begin(9600, SERIAL_8N1, sonde.config.gps_rxd, sonde.config.gps_txd);
|
||||
}
|
||||
xTaskCreate( gpsTask, "gpsTask",
|
||||
5000, /* stack size */
|
||||
NULL, /* paramter */
|
||||
1, /* priority */
|
||||
NULL); /* task handle*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Getting GPS data from App (phone)
|
||||
|
||||
void parseGpsJson(char *data, int len) {
|
||||
char *key = NULL;
|
||||
char *value = NULL;
|
||||
// very simple json parser: look for ", then key, then ", then :, then number, then , or } or \0
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (key == NULL) {
|
||||
if (data[i] != '"') continue;
|
||||
key = data + i + 1;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (value == NULL) {
|
||||
if (data[i] != ':') continue;
|
||||
value = data + i + 1;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (data[i] == ',' || data[i] == '}' || data[i] == 0) {
|
||||
// get value
|
||||
double val = strtod(value, NULL);
|
||||
// get data
|
||||
if (strncmp(key, "lat", 3) == 0) {
|
||||
gpsPos.lat = val;
|
||||
}
|
||||
else if (strncmp(key, "lon", 3) == 0) {
|
||||
gpsPos.lon = val;
|
||||
}
|
||||
else if (strncmp(key, "alt", 3) == 0) {
|
||||
gpsPos.alt = (int)val;
|
||||
}
|
||||
else if (strncmp(key, "course", 6) == 0) {
|
||||
gpsPos.course = (int)val;
|
||||
}
|
||||
gpsPos.valid = true;
|
||||
|
||||
// next item:
|
||||
if (data[i] != ',') break;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
if (gpsPos.lat == 0 && gpsPos.lon == 0) gpsPos.valid = false;
|
||||
Serial.printf("Parse result: lat=%f, lon=%f, alt=%d, valid=%d\n", gpsPos.lat, gpsPos.lon, gpsPos.alt, gpsPos.valid);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
#ifndef _posinfo_h
|
||||
#define _posinfo_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Sonde.h"
|
||||
#include <SPIFFS.h>
|
||||
|
||||
enum { SH_LOC_OFF, SH_LOC_FIXED, SH_LOC_CHASE, SH_LOC_AUTO };
|
||||
|
||||
|
||||
// Handling of station position (GPS, fixed location)
|
||||
|
||||
struct StationPos {
|
||||
double lat;
|
||||
double lon;
|
||||
int alt;
|
||||
float speed;
|
||||
int16_t course;
|
||||
int16_t accuracy;
|
||||
int16_t hdop;
|
||||
int8_t sat;
|
||||
int8_t valid;
|
||||
int8_t chase;
|
||||
};
|
||||
|
||||
extern struct StationPos gpsPos, posInfo;
|
||||
|
||||
|
||||
// Initialize GPS chip
|
||||
void initGPS();
|
||||
|
||||
// Update position from app (if not local GPS chip)
|
||||
void parseGpsJson(char *data, int len);
|
||||
|
||||
// Update position from static config
|
||||
void fixedToPosInfo();
|
||||
|
||||
#endif
|
|
@ -1,3 +1,6 @@
|
|||
#include "../features.h"
|
||||
#if FEATURE_RS92
|
||||
|
||||
/* SPDX-License-Identifier: GPL-3.0
|
||||
* based on https://github.com/rs1729/RS/blob/master/rs92/rs92gps.c
|
||||
*
|
||||
|
@ -1202,3 +1205,4 @@ void get_eph(const char *file) {
|
|||
if (!option_der) d_err = 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const char *version_name = "rdzTTGOsonde";
|
||||
const char *version_id = "master_v0.9.3";
|
||||
const char *version_id = "master_v0.9.4";
|
||||
const int SPIFFS_MAJOR=2;
|
||||
const int SPIFFS_MINOR=17;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x140000,
|
||||
app1, app, ota_1, 0x150000,0x140000,
|
||||
spiffs, data, spiffs, 0x290000,0x160000,
|
||||
coredump, data, coredump,0x3F0000,0x10000,
|
|
|
@ -17,16 +17,17 @@ data_dir = RX_FSK/data
|
|||
lib_deps_builtin =
|
||||
; src
|
||||
lib_deps_external =
|
||||
olikraus/U8g2 @ ^2.28.8
|
||||
AXP202X_Library
|
||||
olikraus/U8g2 @ ^2.35.8
|
||||
stevemarple/MicroNMEA @ ^2.0.5
|
||||
me-no-dev/ESP Async WebServer @ ^1.2.3
|
||||
https://github.com/moononournation/Arduino_GFX#v1.1.5
|
||||
; This is an old version with regex support unconditionally compiled in (adds >100k of code)
|
||||
; me-no-dev/ESP Async WebServer @ ^1.2.3
|
||||
https://github.com/me-no-dev/ESPAsyncWebServer/archive/refs/heads/master.zip
|
||||
; https://github.com/moononournation/Arduino_GFX#v1.1.5
|
||||
https://github.com/moononournation/Arduino_GFX#v1.2.9
|
||||
https://github.com/dx168b/async-mqtt-client
|
||||
|
||||
[env:ttgo-lora32]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#v3.3.2
|
||||
#platform = https://github.com/platformio/platform-espressif32.git#v4.4.0
|
||||
platform = https://github.com/platformio/platform-espressif32.git#v6.4.0
|
||||
board = ttgo-lora32-v1
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
|
@ -35,6 +36,8 @@ lib_deps =
|
|||
${extra.lib_deps_external}
|
||||
paulstoffregen/Time@^1.6.0
|
||||
lib_ignore = Time
|
||||
; Same as with ArduinoIDE. Saves around 27k code
|
||||
build_flags = -DCORE_DEBUG_LEVEL=0
|
||||
|
||||
; Add / remove the following two lines for separate fonts partition in flash
|
||||
; after changes:
|
||||
|
@ -46,3 +49,7 @@ lib_ignore = Time
|
|||
;
|
||||
extra_scripts = post:scripts/makefontpartition.py
|
||||
;board_build.partitions = partition-fonts.csv
|
||||
|
||||
; Uncomment the following if you want to have the partition scheme used in the ESP32 board version 2.0.x of ArduinoIDE
|
||||
; board_build.partitions = partitions-esp32v2.csv
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import requests
|
|||
import sys
|
||||
import os
|
||||
import socket
|
||||
import tempfile
|
||||
import esptool
|
||||
|
||||
ttgohost = "rdzsonde.local"
|
||||
|
@ -56,6 +57,7 @@ if len(sys.argv)<=2:
|
|||
print("or: ",sys.argv[0]," <get|put> file {filename}");
|
||||
print("or: ",sys.argv[0]," update <devel-xxx|master-yyy>");
|
||||
print("or: ",sys.argv[0]," <backup|restore> file.bin");
|
||||
print("or: ",sys.argv[0]," uploadfs directory");
|
||||
print("\n",
|
||||
" screens is screens1.txt, screens2.txt, screens3.txt");
|
||||
print(" networks is networks.txt (Wifi ssid and password)")
|
||||
|
@ -94,6 +96,52 @@ if sys.argv[1]=="update":
|
|||
esptool.main()
|
||||
exit(0)
|
||||
|
||||
|
||||
def getpartinfo(partname):
|
||||
import gen_esp32part as pt
|
||||
# flash complete file system
|
||||
# automatically get file system parameters from ESP (i.e. you need to program the partition table first)
|
||||
if False:
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
partbin = os.path.join(tmpdir, "partition.bin")
|
||||
sys._argv = sys.argv[:]
|
||||
sys.argv=[sys._argv[0], "--chip", "esp32", "--baud", "921600", "--before", "default_reset",
|
||||
"--after", "no_reset", "read_flash", "0x8000", "0x1000", partbin]
|
||||
esptool.main()
|
||||
else:
|
||||
# test only
|
||||
partbin="partitions-esp32v2.csv"
|
||||
with open(partbin,"rb") as f:
|
||||
table, input_is_binary = pt.PartitionTable.from_file(f)
|
||||
print("Partition table:")
|
||||
tab = table.to_csv()
|
||||
print(tab)
|
||||
OFFSET = -1
|
||||
SIZE = -1
|
||||
for line in tab.split("\n"):
|
||||
if line.startswith(partname):
|
||||
l = line.split(",")
|
||||
OFFSET = int(l[3],0)
|
||||
SIZE = l[4]
|
||||
mult = 1
|
||||
if SIZE[-1].upper() == 'K':
|
||||
SIZE = SIZE[:-1]
|
||||
mult = 1024
|
||||
print("SIZE is:"+SIZE+"!")
|
||||
SIZE = int(SIZE,0) * mult
|
||||
|
||||
print("File system at ",hex(OFFSET)," size=",hex(SIZE))
|
||||
return [OFFSET, SIZE]
|
||||
|
||||
#OFFSET="0x3F0000"
|
||||
#SIZE="0x10000"
|
||||
|
||||
if sys.argv[1]=="uploadfs":
|
||||
(offset, size) = getpartinfo("spiffs")
|
||||
print("Using offset ",offset,"; size is ",size)
|
||||
exit(0)
|
||||
|
||||
|
||||
addrinfo = socket.gethostbyname(ttgohost)
|
||||
url = "http://"+addrinfo+"/"
|
||||
print("Using URL ",url)
|
||||
|
|
Ładowanie…
Reference in New Issue