mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Compare commits
405
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b298d6e31 | ||
|
|
c0c65364e5 | ||
|
|
5f89698308 | ||
|
|
400ee82686 | ||
|
|
485f97bdc2 | ||
|
|
5821377b6c | ||
|
|
e6e3c1ddee | ||
|
|
a6ea35ef9c | ||
|
|
fe9a579dc3 | ||
|
|
017aad051e | ||
|
|
8a30659015 | ||
|
|
ed7f597b3d | ||
|
|
6700030d7c | ||
|
|
f45c7650de | ||
|
|
a36ee65865 | ||
|
|
b61c638f0a | ||
|
|
dfb5b8a4c5 | ||
|
|
09e5d6abcd | ||
|
|
2aafbb57a8 | ||
|
|
9d3dd49e9d | ||
|
|
744f22112b | ||
|
|
b38edfb672 | ||
|
|
a73875a2e2 | ||
|
|
0833029c82 | ||
|
|
71cf207bf7 | ||
|
|
f7ea185f80 | ||
|
|
3d3a035822 | ||
|
|
11a94aae25 | ||
|
|
af3bf5217d | ||
|
|
11f47f26e6 | ||
|
|
57c6fbbaab | ||
|
|
f7b37306aa | ||
|
|
8b3d8f6ad4 | ||
|
|
7a9726063d | ||
|
|
d6680b604f | ||
|
|
25ef1803e0 | ||
|
|
2bc72151bc | ||
|
|
93ceae3bef | ||
|
|
b5cad22afd | ||
|
|
2bf31a1985 | ||
|
|
5796f50439 | ||
|
|
36415d424e | ||
|
|
76be5dd8d9 | ||
|
|
407dae03ca | ||
|
|
6e760cd25b | ||
|
|
69c03cafb9 | ||
|
|
c17e683834 | ||
|
|
311abeabd0 | ||
|
|
b20d4a10ba | ||
|
|
548bf8b867 | ||
|
|
0b68e16894 | ||
|
|
33e46addbb | ||
|
|
04f27e0d03 | ||
|
|
628ff925b7 | ||
|
|
6fddf25a39 | ||
|
|
84e58285af | ||
|
|
fc5103de8d | ||
|
|
14b6345277 | ||
|
|
9a70037e32 | ||
|
|
3a8323faab | ||
|
|
fe1944922c | ||
|
|
7ea0c767fa | ||
|
|
ec18e5c530 | ||
|
|
885781850b | ||
|
|
443b46f383 | ||
|
|
8ce1aa0092 | ||
|
|
801a591282 | ||
|
|
740efcb763 | ||
|
|
67fa39f4ed | ||
|
|
7a8bb7c0e0 | ||
|
|
961b1106aa | ||
|
|
9dc549e62d | ||
|
|
c1a11ff6e4 | ||
|
|
151bf18cc6 | ||
|
|
d2e2522c07 | ||
|
|
4a212302e0 | ||
|
|
993dd7ade3 | ||
|
|
e4d68b9d0e | ||
|
|
b5e093bc80 | ||
|
|
d544fc84e8 | ||
|
|
e6dba4456c | ||
|
|
a0a0c31a49 | ||
|
|
d2777a9b15 | ||
|
|
c7d12bb798 | ||
|
|
901d87ad1d | ||
|
|
ef912a4484 | ||
|
|
b4debd9559 | ||
|
|
d7277649dd | ||
|
|
f177ff9e11 | ||
|
|
53a2008a0a | ||
|
|
2525b0e502 | ||
|
|
b7e7c0bb0b | ||
|
|
a397796188 | ||
|
|
33ec7e5240 | ||
|
|
d62b692b3b | ||
|
|
493bfd56b9 | ||
|
|
0f0bc30052 | ||
|
|
abbfa24ca6 | ||
|
|
fae1edc859 | ||
|
|
a9a741f775 | ||
|
|
c0d482e4fc | ||
|
|
2b256389dd | ||
|
|
b5cabdc775 | ||
|
|
e103cc38f7 | ||
|
|
c71a43c3a6 | ||
|
|
cd01283ac6 | ||
|
|
7ce1077bd6 | ||
|
|
f9701d1c7b | ||
|
|
e764830113 | ||
|
|
28eceffedf | ||
|
|
57a1b0dd6f | ||
|
|
9646457b50 | ||
|
|
7346e55e0d | ||
|
|
ae38a8cb4f | ||
|
|
df46a4a5fc | ||
|
|
a0b546e416 | ||
|
|
7c6797a141 | ||
|
|
83abac8c5e | ||
|
|
5ba6b2f335 | ||
|
|
64caeac9ee | ||
|
|
0d4ba7c6f1 | ||
|
|
a1fc351183 | ||
|
|
3131a075f5 | ||
|
|
33a6c39fc4 | ||
|
|
f853f6ef25 | ||
|
|
7a2d114360 | ||
|
|
0157f387ee | ||
|
|
3418f2b708 | ||
|
|
5a0f588344 | ||
|
|
d362446451 | ||
|
|
c23be231e1 | ||
|
|
00f5c36919 | ||
|
|
c960175ec1 | ||
|
|
e456604436 | ||
|
|
ac4657e77f | ||
|
|
3817427e79 | ||
|
|
0200b3c63e | ||
|
|
972a1a5703 | ||
|
|
73c22176b8 | ||
|
|
4db036f350 | ||
|
|
52223f0a20 | ||
|
|
907ad0faf6 | ||
|
|
887e10c947 | ||
|
|
b4c463e452 | ||
|
|
66ba9b1f46 | ||
|
|
7db50811ba | ||
|
|
17d20705ff | ||
|
|
e3bd782a42 | ||
|
|
b073379fff | ||
|
|
b89d8ff946 | ||
|
|
22ad971c8e | ||
|
|
ab06cc3703 | ||
|
|
8a5cc5f2bd | ||
|
|
6919baf23c | ||
|
|
ddedb215c4 | ||
|
|
3dc5f1e160 | ||
|
|
08d4d817f6 | ||
|
|
e8bdcfbaf2 | ||
|
|
743fb4494e | ||
|
|
0a4bc7fad6 | ||
|
|
49d0b16324 | ||
|
|
de479d6188 | ||
|
|
3fd3e13dc7 | ||
|
|
d7d913d439 | ||
|
|
5c4ae3820b | ||
|
|
38774a20c6 | ||
|
|
9fc58bb4df | ||
|
|
ca936ca42f | ||
|
|
840fb6b647 | ||
|
|
34f54c51e4 | ||
|
|
cda973a54f | ||
|
|
8d77c29d75 | ||
|
|
c80b5d6d78 | ||
|
|
0454926d68 | ||
|
|
40067c514f | ||
|
|
77e5d8f00e | ||
|
|
e33f9c1709 | ||
|
|
31ba3aad85 | ||
|
|
3c591f146e | ||
|
|
35f82ea616 | ||
|
|
60f5bdb069 | ||
|
|
7be9f321a2 | ||
|
|
00998a8d3e | ||
|
|
1f5d0f1968 | ||
|
|
ec83cf39cd | ||
|
|
7c8487632d | ||
|
|
e6bd9adc03 | ||
|
|
6f0c10dcd7 | ||
|
|
ddb3d1a0dd | ||
|
|
c187e7edc3 | ||
|
|
9735e33e51 | ||
|
|
4eeb22110d | ||
|
|
b190a43e7e | ||
|
|
20b95c425e | ||
|
|
5ba05ff769 | ||
|
|
051f7c9f52 | ||
|
|
0fa7817b2a | ||
|
|
95d5dd3c68 | ||
|
|
56fd1e0203 | ||
|
|
890487fcae | ||
|
|
9b9dce0aaf | ||
|
|
139ae36d3e | ||
|
|
da6edeab86 | ||
|
|
cdcf041073 | ||
|
|
ec99795c1e | ||
|
|
0bc8570b4a | ||
|
|
2d8e14eb87 | ||
|
|
4917dab1d3 | ||
|
|
42e1eb33ef | ||
|
|
c2fdd50655 | ||
|
|
a643596c48 | ||
|
|
04465454f4 | ||
|
|
190783f382 | ||
|
|
e51c5d8504 | ||
|
|
3849befeaf | ||
|
|
05c61879f9 | ||
|
|
71f6b58dd7 | ||
|
|
c30074afc5 | ||
|
|
5aef196306 | ||
|
|
e09f5ca0a1 | ||
|
|
716ae30d9d | ||
|
|
116c653db5 | ||
|
|
dcfc1e3689 | ||
|
|
7ba981eaea | ||
|
|
ede5ed8b0d | ||
|
|
b8877c53ed | ||
|
|
296271007b | ||
|
|
d49a91c4a2 | ||
|
|
2b567f5578 | ||
|
|
8469188f75 | ||
|
|
2409df4f5b | ||
|
|
c5c33cf6b6 | ||
|
|
cea1d8b825 | ||
|
|
982ed4d677 | ||
|
|
d424803cac | ||
|
|
6cd3f514a6 | ||
|
|
b5d4b96f14 | ||
|
|
f9ce235b32 | ||
|
|
491fa5c0a2 | ||
|
|
1bbbaa18f7 | ||
|
|
eff68b2173 | ||
|
|
8b6adac269 | ||
|
|
e0edd56413 | ||
|
|
c95d04aa6b | ||
|
|
9a88269e28 | ||
|
|
d5847f9ea1 | ||
|
|
b3a75c0105 | ||
|
|
3ba2f38408 | ||
|
|
b455a676d8 | ||
|
|
e5dbb3c680 | ||
|
|
7d236e8564 | ||
|
|
ae18a47bc9 | ||
|
|
5dd4d49517 | ||
|
|
d708d6a057 | ||
|
|
c3db03ea5e | ||
|
|
b65812ebf3 | ||
|
|
698299f918 | ||
|
|
277d12205d | ||
|
|
52b3c2e962 | ||
|
|
f6cadc43f3 | ||
|
|
e393d66283 | ||
|
|
10e33de018 | ||
|
|
842dc38805 | ||
|
|
52ef5c06fd | ||
|
|
1c63589b3d | ||
|
|
3e230310b9 | ||
|
|
ce249aaa4a | ||
|
|
bd216674d4 | ||
|
|
32c4b1d614 | ||
|
|
1847746077 | ||
|
|
56741b425c | ||
|
|
4f3a8e6acb | ||
|
|
f40d8c3cf4 | ||
|
|
d7a3c74ad9 | ||
|
|
b5049cd9ca | ||
|
|
55536cc4b3 | ||
|
|
cbbec517d6 | ||
|
|
db2624d49d | ||
|
|
d7116735e9 | ||
|
|
43ba235e68 | ||
|
|
2c3c8f6e0d | ||
|
|
6dc816869f | ||
|
|
5fff3c6ce7 | ||
|
|
fe85b0908c | ||
|
|
612742f669 | ||
|
|
8d2303db5f | ||
|
|
97b90a09db | ||
|
|
dcdf095575 | ||
|
|
9ecfce472d | ||
|
|
20e5bc0081 | ||
|
|
5136d4757c | ||
|
|
2729e341c8 | ||
|
|
6d0399c6c7 | ||
|
|
72d07bc303 | ||
|
|
c55bb28038 | ||
|
|
0a746d017e | ||
|
|
de4517f614 | ||
|
|
0dcd89a653 | ||
|
|
f70970c6f3 | ||
|
|
4d28d2b837 | ||
|
|
b63e76adfe | ||
|
|
77eedf5d6c | ||
|
|
01ff98be05 | ||
|
|
6222041a30 | ||
|
|
302e0d7fa7 | ||
|
|
894e9c3ff6 | ||
|
|
66bda6d531 | ||
|
|
f3c7c68248 | ||
|
|
093767f2b1 | ||
|
|
50f6c403e8 | ||
|
|
3c41155ee4 | ||
|
|
dcc2dbf0c6 | ||
|
|
fd1da876a4 | ||
|
|
93fc1b6140 | ||
|
|
80fb17ca05 | ||
|
|
ee0069ffa4 | ||
|
|
b1bd7d63f6 | ||
|
|
ef8059cf56 | ||
|
|
8d246947c1 | ||
|
|
8bcf29fa11 | ||
|
|
4b900daa67 | ||
|
|
a84567c14e | ||
|
|
d4420b9e36 | ||
|
|
6daa9a1e3c | ||
|
|
6a4f8a6942 | ||
|
|
41974d12e5 | ||
|
|
ea5168c08a | ||
|
|
d07bb3574a | ||
|
|
fb83badfce | ||
|
|
1a9eedc6d6 | ||
|
|
b26b4a1a93 | ||
|
|
f3e7dffec4 | ||
|
|
9341bde0da | ||
|
|
e10a6e6f55 | ||
|
|
f0ed209ba6 | ||
|
|
2672558bfe | ||
|
|
ffe2f3f775 | ||
|
|
92816f1a9f | ||
|
|
43ef90f688 | ||
|
|
2c6096dd31 | ||
|
|
1cefa5eb1b | ||
|
|
a8e39b1899 | ||
|
|
b1a47e4c3a | ||
|
|
b7d881d136 | ||
|
|
67c3a166f5 | ||
|
|
060b72e88b | ||
|
|
36550511f5 | ||
|
|
fb8188b14b | ||
|
|
436564ba51 | ||
|
|
9016f1b53e | ||
|
|
0404a871f2 | ||
|
|
1413c92678 | ||
|
|
28208ac7a2 | ||
|
|
168a2c343c | ||
|
|
a873e920d4 | ||
|
|
10838d544c | ||
|
|
ab48fc0dfd | ||
|
|
bcf6521ef9 | ||
|
|
6f8d7d1ada | ||
|
|
c6f03551c5 | ||
|
|
b2a9679488 | ||
|
|
b66d983060 | ||
|
|
2b16ddedbf | ||
|
|
dbd89deb7b | ||
|
|
6c52721ed1 | ||
|
|
03fbe8fcca | ||
|
|
9e0af20343 | ||
|
|
aa0b4d0fce | ||
|
|
a9f6605065 | ||
|
|
26b073ba34 | ||
|
|
27bba1b628 | ||
|
|
6131ebca73 | ||
|
|
01b42a6dfb | ||
|
|
23be929f72 | ||
|
|
b536770a07 | ||
|
|
792982262b | ||
|
|
541d50e6bb | ||
|
|
c8d88140f7 | ||
|
|
d3fdf27746 | ||
|
|
afb6860156 | ||
|
|
48563bade6 | ||
|
|
017019e122 | ||
|
|
8e0d78af7b | ||
|
|
66531d46bd | ||
|
|
83dbb63d13 | ||
|
|
771f981c13 | ||
|
|
9d5afd1e2a | ||
|
|
33ac272804 | ||
|
|
30a1e4c7c3 | ||
|
|
1d97f08b34 | ||
|
|
752a741e60 | ||
|
|
9eaf88abad | ||
|
|
f5ffcf5454 | ||
|
|
e8c5a02ead | ||
|
|
5c9d00c0a9 | ||
|
|
9b8d5bba4c | ||
|
|
5f8e2a70d0 | ||
|
|
19b1316205 | ||
|
|
b9f47d3cf2 | ||
|
|
75067cd33f | ||
|
|
25477a1232 | ||
|
|
4b9b3f5a37 | ||
|
|
c0d147f3df | ||
|
|
228f782762 | ||
|
|
e952bb8731 |
@@ -0,0 +1,22 @@
|
||||
# cmd: "cd {PROJECT_PATH}; platformio"
|
||||
cmd: "platformio"
|
||||
name: "Build with error highlighting (dev_ESP8266_4096)"
|
||||
args:
|
||||
- run --environment dev_ESP8266_4096
|
||||
sh: true
|
||||
cwd: "{PROJECT_PATH}"
|
||||
# env:
|
||||
# VARIABLE1: "VALUE1"
|
||||
# VARIABLE2: "VALUE2"
|
||||
errorMatch:
|
||||
- "(?<file>[\\/0-9a-zA-Z\\._]+):(?<line>\\d+):(?<col>\\d+):\\s+error:\\s+(?<message>.+)"
|
||||
|
||||
warningMatch:
|
||||
- "(?<file>[\\/0-9a-zA-Z\\._]+):(?<line>\\d+):(?<col>\\d+):\\s+warning:\\s+(?<message>.+)"
|
||||
# keymap: <keymap string>
|
||||
# atomCommandName: namespace:command
|
||||
# targets:
|
||||
# extraTargetName:
|
||||
# cmd: "<command to execute>"
|
||||
# args:
|
||||
# # (any previous options are viable here except `targets` itself)
|
||||
+12
-8
@@ -15,15 +15,19 @@ Also there are more people on the forum that can help you with support.
|
||||
## Pull requests
|
||||
|
||||
* Make sure your code compiles.
|
||||
|
||||
* Try to create different pull requests for different features/fixes.
|
||||
|
||||
|
||||
* Make sure your code does not have warnings. (Warnings will be treated as errors by our Travis system.)
|
||||
|
||||
* Try to create different pull requests for different features/fixes.
|
||||
|
||||
* Dont combine a lot of different stuff in one huge pull request.
|
||||
|
||||
* Incomplete or unstable plugins should have a PLUGIN_BUILD_DEV ifdef around them.
|
||||
|
||||
* New plugins that seem to be working correctly should have a PLUGIN_BUILD_TESTING around until they are tested enough.
|
||||
* The v2.0 branch should get only fixes, new stuff should go into the mega-branch. (We will merge those fixes from v2.0 to mega)
|
||||
|
||||
* Incomplete or unstable plugins should have a PLUGIN_BUILD_DEV #ifdef around them. Also add [DEVELOPMENT] to the name.
|
||||
|
||||
* Do not modify any of the variables passed to your PLUGIN_WRITE handler.
|
||||
|
||||
* New plugins that seem to be working correctly should have a PLUGIN_BUILD_TESTING around until they are tested enough. Also add [TESTING] to the name
|
||||
|
||||
* Also see our general guidelines at: https://www.letscontrolit.com/wiki/index.php/ESPEasyDevelopmentGuidelines
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
**NOTE: This is not a support forum! For questions and support go here: https://www.letscontrolit.com/forum/viewforum.php?f=1**
|
||||
|
||||
### Steps to reproduce
|
||||
How can we trigger this problem?
|
||||
|
||||
Does the problem presist after powering off and on? (just resetting isnt enough sometimes)
|
||||
|
||||
### Expected behavior
|
||||
Tell us what should happen?
|
||||
|
||||
|
||||
@@ -2,3 +2,5 @@
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.piolibdeps
|
||||
|
||||
lib/readme.txt
|
||||
|
||||
+21
-3
@@ -1,15 +1,33 @@
|
||||
language: python
|
||||
python:
|
||||
- '2.7'
|
||||
- '2.7'
|
||||
|
||||
#we want a newer cppcheck, so use trusty
|
||||
dist: trusty
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "./.pioenvs"
|
||||
|
||||
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- cppcheck
|
||||
|
||||
|
||||
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- pip install -U platformio
|
||||
|
||||
script:
|
||||
- platformio run
|
||||
# - cppcheck --enable=warning src/*.ino -q --force -I src --include=src/ESPEasy.ino --error-exitcode=1
|
||||
# - ./memanalyzer.py ~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-objdump
|
||||
- PLATFORMIO_BUILD_FLAGS="-D CONTINUOUS_INTEGRATION" platformio run -s
|
||||
|
||||
before_deploy:
|
||||
- ./before_deploy
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
# ESPEasy (mega branch)
|
||||
# ESPEasy (development branch)
|
||||
|
||||
Build status: [](https://travis-ci.org/letscontrolit/ESPEasy)
|
||||
|
||||
This is the development branch for the next upcoming release (2.0.0). This is also known as ESPEasyMega.
|
||||
Introduction and wiki: https://www.letscontrolit.com/wiki/index.php/ESPEasy#Introduction
|
||||
|
||||
This is the development branch of ESPEasy. All new untested features go into this branch. Fixes from stable branches will also be merged in this one.
|
||||
|
||||
Check here to learn how to use this branch and help us improving ESPEasy: http://www.letscontrolit.com/wiki/index.php/ESPEasy#Source_code_development
|
||||
|
||||
Binary development releases are here: https://github.com/letscontrolit/ESPEasy/releases
|
||||
|
||||
Details and discussion are on the Experimental forum: http://www.letscontrolit.com/forum/viewtopic.php?f=18&t=2257&p=13600#p13600
|
||||
## Automated binary releases
|
||||
|
||||
Every night our build-bot will build a new binary release: https://github.com/letscontrolit/ESPEasy/releases
|
||||
|
||||
The releases are named something like 'mega-20180102' (last number is the build date)
|
||||
|
||||
Depending on your needs, we release different types of files:
|
||||
|
||||
Firmware name | Hardware | Included plugins |
|
||||
----------------------------------------------|-------------------------|-----------------------------|
|
||||
ESPEasy_mega-20180102_normal_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test + Development |
|
||||
ESPEasy_mega-20180102_normal_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test + Development |
|
||||
ESPEasy_mega-20180102_normal_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test + Development |
|
||||
|
||||
## More info
|
||||
|
||||
Details and discussion are on the Experimental forum: https://www.letscontrolit.com/forum/viewforum.php?f=18
|
||||
|
||||
We're also on IRC: #ESPEasy @freenode
|
||||
|
||||
+13
-7
@@ -3,16 +3,22 @@
|
||||
VERSION=$(git describe)
|
||||
echo "Creating release archives for $VERSION ..."
|
||||
#binaries
|
||||
# cp .pioenvs/mini_512/firmware.bin dist/"ESPEasy_$VERSION""_mini_512.bin"
|
||||
|
||||
cp .pioenvs/normal_1024/firmware.bin dist/"ESPEasy_$VERSION""_normal_1024.bin"
|
||||
cp .pioenvs/normal_4096/firmware.bin dist/"ESPEasy_$VERSION""_normal_4096.bin"
|
||||
#ESP_Easy_v[version]-[build type]-dev[dev number]-ESP[chip type]-[size].bin
|
||||
|
||||
cp .pioenvs/test_1024/firmware.bin dist/"ESPEasy_$VERSION""_test_1024.bin"
|
||||
cp .pioenvs/test_4096/firmware.bin dist/"ESPEasy_$VERSION""_test_4096.bin"
|
||||
#cp .pioenvs/mini_512/firmware.bin dist/"ESPEasy_$VERSION""_mini_512.bin"
|
||||
|
||||
cp .pioenvs/dev_1024/firmware.bin dist/"ESPEasy_$VERSION""_dev_1024.bin"
|
||||
cp .pioenvs/dev_4096/firmware.bin dist/"ESPEasy_$VERSION""_dev_4096.bin"
|
||||
cp .pioenvs/normal_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8266_1024.bin"
|
||||
cp .pioenvs/normal_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8266_4096.bin"
|
||||
cp .pioenvs/normal_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8285_1024.bin"
|
||||
|
||||
cp .pioenvs/test_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8266_1024.bin"
|
||||
cp .pioenvs/test_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8266_4096.bin"
|
||||
cp .pioenvs/test_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8285_1024.bin"
|
||||
|
||||
cp .pioenvs/dev_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8266_1024.bin"
|
||||
cp .pioenvs/dev_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8266_4096.bin"
|
||||
cp .pioenvs/dev_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8285_1024.bin"
|
||||
|
||||
#create a source structure that is the same as the original ESPEasy project (and works with the howto on the wiki)
|
||||
rm -rf dist/Source 2>/dev/null
|
||||
|
||||
Vendored
+733
@@ -1,3 +1,736 @@
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180119 (since mega-20180118)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Jan 19 05:00:07 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180118
|
||||
|
||||
Edwin Eefting (2):
|
||||
refactoring test suite controller stuff
|
||||
test suite domoticz mqtt + found few fixmes
|
||||
|
||||
jctual (1):
|
||||
DHT plugin update (#736)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180118 (since mega-20180117)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 18 05:00:07 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180116
|
||||
|
||||
Edwin Eefting (3):
|
||||
made test resumable and importable
|
||||
now supports powercycle to test for bugs like #719
|
||||
added fixme
|
||||
|
||||
Gijs Noorlander (2):
|
||||
[issue 733] Fix for negative values on MQTT import (#735)
|
||||
[issue 728] Proper reconnect for MQTT controllers (#737)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180117 (since mega-20180116)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Jan 17 05:00:08 CET 2018
|
||||
|
||||
Edwin Eefting (1):
|
||||
fix #719 (initial ds18b20 value after power on 85 degrees)
|
||||
|
||||
papperone (1):
|
||||
merge with main branch (#648)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180116 (since mega-20180114)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 16 05:00:11 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180113
|
||||
|
||||
Edwin Eefting (2):
|
||||
testsuite: working on generic http/mqtt controller emulatior receiving
|
||||
fixed custom build path
|
||||
|
||||
Gijs Noorlander (1):
|
||||
[AutoDST] Added Auto DST (Bugfix/v2.0 issue569) (#726)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180114 (since mega-20180113)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sun Jan 14 05:00:08 CET 2018
|
||||
|
||||
s0170071 (1):
|
||||
preparations for lwip2 (#707)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180113 (since mega-20180112)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Jan 13 05:00:10 CET 2018
|
||||
|
||||
Edwin Eefting (2):
|
||||
ESPEasy v2.0 only supports compiling under arduino core 2.3.0 to prevent issues like #705 when people use Arduino IDE to compile with arduino core 2.4.0
|
||||
fix version number
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180112 (since mega-20180111)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Jan 12 02:05:49 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180111
|
||||
|
||||
Edwin Eefting (8):
|
||||
added http server emulation and domotics http to testsuite
|
||||
first http domoticz test works
|
||||
testsuite requirements
|
||||
fixed releasebot issues with multiple branches
|
||||
automaticly updated release notes for v2.0-20180112
|
||||
release bot fixes
|
||||
dont make same release twice
|
||||
dont make same release twice
|
||||
|
||||
Gijs Noorlander (2):
|
||||
[Issue 699] Incorrect shown device name (#700)
|
||||
[v2.0 #470] Do not send invalid values to a controller (#701)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180111 (since v2.0-20180110)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 11 05:00:08 CET 2018
|
||||
|
||||
Alexander Schulz (1):
|
||||
improvement: Configurable number of tasks for "Devices" page (TASKS_P…
|
||||
|
||||
BadWolf42 (1):
|
||||
Dallas Plugin enhanced : no more "delay()" (#488)
|
||||
|
||||
Bartłomiej Zimoń (1):
|
||||
Update _C002.ino (#645)
|
||||
|
||||
DaM (1):
|
||||
[Domoticz HTTP] Compatibility fix for BMP280 (#636)
|
||||
|
||||
ESPEasy release bot (5):
|
||||
created releasebot script
|
||||
automaticly updated release notes for mega-01022018
|
||||
automaticly updated release notes for mega-01032018
|
||||
changed date format of nightly builds
|
||||
automaticly updated release notes for mega-20180104
|
||||
|
||||
Edwin Eefting (22):
|
||||
keep TASKS_PER_PAGE at default value of 4
|
||||
fix plugin id (starting with a 0 makes it octal in c++ :( )
|
||||
fix warnings
|
||||
fixed bug in oled upstream lib
|
||||
test fixes
|
||||
smooth out testing code
|
||||
esptest stuff
|
||||
fix travis build errors. disable cpp checking for now
|
||||
set lcd to NULL by default. #584
|
||||
fix illegal string manipulations in PLUGIN_WRITE for some plugins. fixes #347 and #460
|
||||
fix #588. parseTemplate() now only checks enabled taskes for [] macros
|
||||
testing for ds18b20
|
||||
updated travis link to reflect v2.0
|
||||
changed readme to reflect mega branch and automated builds
|
||||
updates version numbering documentation
|
||||
changed devicecombobox handling to save a lot of memory on device page. fixes #654 #676 and could be triggered by #683 in some cases.
|
||||
oops...somehow git did made some changes :(
|
||||
copied test-stuff from mega to v2.0 to do some testing
|
||||
analysed some code and added comments
|
||||
test suite fixes
|
||||
added frame oled test
|
||||
working on http mocker for test suite
|
||||
|
||||
GHolli (1):
|
||||
Cosmetics: fixing typos. (#628)
|
||||
|
||||
Gijs Noorlander (14):
|
||||
P028 to support both BME280 and BMP280 to reduce resource usage (#481)
|
||||
Single function for format to user defined number decimals (#482)
|
||||
OLED framed improve header footer (#495)
|
||||
[SSD1306] Feature/oled 1306 library upgrade (#501)
|
||||
[MH-Z19] Allow for B-version and add filtering (#525)
|
||||
Support both SSD1306 and SH1106 OLED in OLED_Framed plugin (#509)
|
||||
[LCD plugin] Added check of LCD object before dereferencing it (#584)
|
||||
[P039 Thermocouple] Handling negative values and proper error logging (#586)
|
||||
Reduce iRAM usage for plugins using SoftwareSerial (#631)
|
||||
[Security] Add IP-based filtering to web interface and http-commands. (#653)
|
||||
[SDS011] Allow the sensor to sleep to extend sensor lifetime (#668)
|
||||
[CPPcheck] v2.0 ControllerSettingsStruct some variables not initialized (#692)
|
||||
Merge/v2.0 dev13 to mega (#695)
|
||||
[v2.0_kamstrup] Plugin configuration does not load (#697)
|
||||
|
||||
Grovkillen (6):
|
||||
Added categories... (#552)
|
||||
Changed bin file names to be more descriptive. (#597)
|
||||
Move "TTP229 keypad" and "Encoder" plugin from "testing" to "normal" (#619)
|
||||
Updated ESPTOOLS.exe from 0.4.6 to 0.4.12 (#627)
|
||||
Updated "/pinstates" page: Made the plugin number column display "P001" instead of "1" and "P012" instead of "12".
|
||||
Update README.md
|
||||
|
||||
M0ebiu5 (1):
|
||||
P022_PCA9685 added change frequency - P038_NeoPixel added RGBW strips (SK6812) (#638)
|
||||
|
||||
Michael (2):
|
||||
WebServer.ino: enhance handle_SDfilelist() (#507)
|
||||
src/Hardware.ino: make it possible to use GPIO-0 (D3) as Pin_sd_cs (#508)
|
||||
|
||||
Sen Haerens (1):
|
||||
Enhanced system info layout (#624)
|
||||
|
||||
SightofSilence (1):
|
||||
Add System Variable for day, month and year / Fix for "Calculate" function to recognize minus-sign (#485)
|
||||
|
||||
SloMusti (1):
|
||||
implemewnted web activity timer tracker (#462)
|
||||
|
||||
Tomasz Torcz (1):
|
||||
retain MQTT LWT messages (#516)
|
||||
|
||||
denisfrench (1):
|
||||
Set MQTT clientid to %sysname% +/- Settings.Unit (#431) (#436)
|
||||
|
||||
fensoft (1):
|
||||
added #define FEATURE_SD (permit a flash size reduction of ~10k) (#568)
|
||||
|
||||
hatzlhoffer (1):
|
||||
added new display size 128x32 (#545)
|
||||
|
||||
krikk (1):
|
||||
added support for the TSL2591 Sensor based on Adafruit Library (#661)
|
||||
|
||||
mvdbro (8):
|
||||
First preparations for ESP32
|
||||
ESP32 IRAM/Deepsleep
|
||||
ESP32 Rules/ADC/PWM
|
||||
ESP32 fix FreeRAM reporting
|
||||
ESP32 Enabled OTA
|
||||
ESP32 fix UDP instability
|
||||
ESP32 fixed chunked HTTP transfer
|
||||
Fix #599
|
||||
|
||||
papperone (3):
|
||||
Plugin 073 - 7-segment display plugin TM1637/MAX7219
|
||||
Update _P073_7DGT.ino (#553)
|
||||
deleted GPIO notes referring to 75HC595 not supported (#591)
|
||||
|
||||
paulv888 (1):
|
||||
usesID = true (#666)
|
||||
|
||||
s0170071 (2):
|
||||
split IP addrress (#605)
|
||||
fix chunking (#649)
|
||||
|
||||
sakinit (1):
|
||||
Fix p1 wifi gateway module (#587)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180104 (since mega-01032018)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 4 03:13:01 UTC 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
changed date format of nightly builds
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-01032018 (since mega-01022018)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Jan 3 04:00:06 UTC 2018
|
||||
|
||||
Edwin Eefting (4):
|
||||
updated readme to reflect new binary names
|
||||
updated travis link to reflect v2.0
|
||||
updated travis link to reflect v2.0
|
||||
changed readme to reflect mega branch and automated builds
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-01022018 (since v2.0.0-dev13)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 2 23:32:50 UTC 2018
|
||||
|
||||
Alexander Schulz (1):
|
||||
improvement: Configurable number of tasks for "Devices" page (TASKS_P…
|
||||
|
||||
BadWolf42 (1):
|
||||
Dallas Plugin enhanced : no more "delay()" (#488)
|
||||
|
||||
Bartłomiej Zimoń (1):
|
||||
Update _C002.ino (#645)
|
||||
|
||||
DaM (1):
|
||||
[Domoticz HTTP] Compatibility fix for BMP280 (#636)
|
||||
|
||||
ESPEasy release bot (1):
|
||||
created releasebot script
|
||||
|
||||
Edwin Eefting (12):
|
||||
keep TASKS_PER_PAGE at default value of 4
|
||||
fix plugin id (starting with a 0 makes it octal in c++ :( )
|
||||
fix warnings
|
||||
fixed bug in oled upstream lib
|
||||
test fixes
|
||||
smooth out testing code
|
||||
esptest stuff
|
||||
fix travis build errors. disable cpp checking for now
|
||||
set lcd to NULL by default. #584
|
||||
fix illegal string manipulations in PLUGIN_WRITE for some plugins. fixes #347 and #460
|
||||
fix #588. parseTemplate() now only checks enabled taskes for [] macros
|
||||
testing for ds18b20
|
||||
|
||||
GHolli (1):
|
||||
Cosmetics: fixing typos. (#628)
|
||||
|
||||
Gijs Noorlander (11):
|
||||
P028 to support both BME280 and BMP280 to reduce resource usage (#481)
|
||||
Single function for format to user defined number decimals (#482)
|
||||
OLED framed improve header footer (#495)
|
||||
[SSD1306] Feature/oled 1306 library upgrade (#501)
|
||||
[MH-Z19] Allow for B-version and add filtering (#525)
|
||||
Support both SSD1306 and SH1106 OLED in OLED_Framed plugin (#509)
|
||||
[LCD plugin] Added check of LCD object before dereferencing it (#584)
|
||||
[P039 Thermocouple] Handling negative values and proper error logging (#586)
|
||||
Reduce iRAM usage for plugins using SoftwareSerial (#631)
|
||||
[Security] Add IP-based filtering to web interface and http-commands. (#653)
|
||||
[SDS011] Allow the sensor to sleep to extend sensor lifetime (#668)
|
||||
|
||||
Grovkillen (5):
|
||||
Added categories... (#552)
|
||||
Changed bin file names to be more descriptive. (#597)
|
||||
Move "TTP229 keypad" and "Encoder" plugin from "testing" to "normal" (#619)
|
||||
Updated ESPTOOLS.exe from 0.4.6 to 0.4.12 (#627)
|
||||
Updated "/pinstates" page: Made the plugin number column display "P001" instead of "1" and "P012" instead of "12".
|
||||
|
||||
M0ebiu5 (1):
|
||||
P022_PCA9685 added change frequency - P038_NeoPixel added RGBW strips (SK6812) (#638)
|
||||
|
||||
Michael (2):
|
||||
WebServer.ino: enhance handle_SDfilelist() (#507)
|
||||
src/Hardware.ino: make it possible to use GPIO-0 (D3) as Pin_sd_cs (#508)
|
||||
|
||||
Sen Haerens (1):
|
||||
Enhanced system info layout (#624)
|
||||
|
||||
SightofSilence (1):
|
||||
Add System Variable for day, month and year / Fix for "Calculate" function to recognize minus-sign (#485)
|
||||
|
||||
SloMusti (1):
|
||||
implemewnted web activity timer tracker (#462)
|
||||
|
||||
Tomasz Torcz (1):
|
||||
retain MQTT LWT messages (#516)
|
||||
|
||||
denisfrench (1):
|
||||
Set MQTT clientid to %sysname% +/- Settings.Unit (#431) (#436)
|
||||
|
||||
fensoft (1):
|
||||
added #define FEATURE_SD (permit a flash size reduction of ~10k) (#568)
|
||||
|
||||
hatzlhoffer (1):
|
||||
added new display size 128x32 (#545)
|
||||
|
||||
krikk (1):
|
||||
added support for the TSL2591 Sensor based on Adafruit Library (#661)
|
||||
|
||||
mvdbro (8):
|
||||
First preparations for ESP32
|
||||
ESP32 IRAM/Deepsleep
|
||||
ESP32 Rules/ADC/PWM
|
||||
ESP32 fix FreeRAM reporting
|
||||
ESP32 Enabled OTA
|
||||
ESP32 fix UDP instability
|
||||
ESP32 fixed chunked HTTP transfer
|
||||
Fix #599
|
||||
|
||||
papperone (3):
|
||||
Plugin 073 - 7-segment display plugin TM1637/MAX7219
|
||||
Update _P073_7DGT.ino (#553)
|
||||
deleted GPIO notes referring to 75HC595 not supported (#591)
|
||||
|
||||
paulv888 (1):
|
||||
usesID = true (#666)
|
||||
|
||||
s0170071 (2):
|
||||
split IP addrress (#605)
|
||||
fix chunking (#649)
|
||||
|
||||
sakinit (1):
|
||||
Fix p1 wifi gateway module (#587)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0.0-dev13 (since v2.0.0-dev12)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 2 17:41:19 CET 2018
|
||||
|
||||
Edwin Eefting (27):
|
||||
more fixes for #235
|
||||
final fixes for #235, untested. all spiffs errors should be handled now and also show up in logs and webinterface
|
||||
fixed obscure crash caused by not returning a value in #235. we need to adjust compiler flags to detect these kinds of issues.
|
||||
always define PLUGIN_BUILD_NORMAL so normal plugins are compiled
|
||||
cleaned up buildflags and created common build variable
|
||||
solution for better error and warning highlighting when compiling with platformio
|
||||
enabled warnings and started fixing all the warnings to reduce the noise. (because warnings where disabled wasted about 3 hours debugging a simple no-return bug)
|
||||
cleaned up more warnings and fixed a few real bug along the way. #235
|
||||
now using PRAGMA to enable warnings, so that we dont get warnings from core libraries. also warnings will be treated as errors in Travis, this makes approving pull requests less work for me.
|
||||
travis fix
|
||||
worked around error caused by upstream libraries
|
||||
fixes
|
||||
cleaned up notification stuff. fixed #502
|
||||
warnings are treated as errors now, by travis
|
||||
refactored and added automated test stuff
|
||||
examples for the lone wanderer
|
||||
cleaner errors
|
||||
working on test stuff
|
||||
update branching info
|
||||
test library stuff
|
||||
Simple fix for MH-Z19 B version. #529
|
||||
set lcd to NULL by default. #584
|
||||
fix #588. parseTemplate() now only checks enabled taskes for [] macros
|
||||
automaticly updated release notes for v2.0.0-dev13
|
||||
release all binaries by doing the full compile step as last
|
||||
automaticly updated release notes for v2.0.0-dev13
|
||||
still trying to fix travis release scripts..
|
||||
|
||||
Gijs Noorlander (9):
|
||||
[INA219] Allow for multiple instances on the same controller (#519)
|
||||
[INA219_v2.0] Improve logs for multiple devices (#546)
|
||||
[LCD plugin] Added check of LCD object before dereferencing it (#584)
|
||||
Move CO2 MH-Z19 plugin from "testing" to "normal" (#618)
|
||||
[DNS/IP] Obey UseDNS setting for all controllers (#629)
|
||||
[v2.0] Add more characters to the list not to escape in URLs (#635)
|
||||
[>49.7 days uptime overflow] Use separate function to compute time differences (#621)
|
||||
[WiFi] Avoid timeouts when not connected to WiFi (#639)
|
||||
[PubSubClient] Bug in handling domainname (#660)
|
||||
|
||||
Grovkillen (2):
|
||||
Added categories... (#552)
|
||||
Changed bin file names to be more descriptive. (#597)
|
||||
|
||||
Neo (1):
|
||||
[HT16K33_LED] Brightness control (#523)
|
||||
|
||||
mvdbro (1):
|
||||
Bugfix: %eventvalue% parsing on literal strings
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0.0-dev12 (since v2.0.0-dev11)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Sep 22 01:25:29 CEST 2017
|
||||
|
||||
Daniel Tedenljung (1):
|
||||
This plugin is tested and working good. (#428)
|
||||
|
||||
Edwin Eefting (6):
|
||||
first set of changes for #235. added spiffs error checking and loging, and cleaner flashguarding code. next change will show feedback in web interface as well. also need to cleanup loose SPIFFS filehandling at other places in webserver.ino (create a save-function for all those things and use FLASH_GUARD)
|
||||
missed return after setting event buffer
|
||||
fixes bug #486 in counter-plugin
|
||||
plugin is not generic enough, so its disabled by default
|
||||
automaticly updated release notes for 2.0.0-dev12
|
||||
fixed release-notes bug
|
||||
|
||||
Gerben Meijer (1):
|
||||
Add SENSOR_TYPE_TRIPLE support to Domoticz MQTT (#468)
|
||||
|
||||
Gijs Noorlander (1):
|
||||
[MH-Z19] Add 'ABC disable' option to web config (#472)
|
||||
|
||||
Jeroen (1):
|
||||
Create _P071_Kamstrup401.ino (#504)
|
||||
|
||||
Jochen Krapf (4):
|
||||
Added Plugins for SHT3x and LM75A - Issue #433 (#442)
|
||||
Descriptive GPIO-Names (#448)
|
||||
Rework of Plugin _P056_SDS011-Dust (#451)
|
||||
Fixed HTML text box length for controller settings - Issue #453 (#455)
|
||||
|
||||
Ovidiu Schiopu (1):
|
||||
Added _P070_NeoPixel_Clock.ino (#489)
|
||||
|
||||
SightofSilence (1):
|
||||
Add files via upload (#493)
|
||||
|
||||
beic (2):
|
||||
Moving from Temperature to Environment naming (#492)
|
||||
Moving from Temperature to Environment naming (#506)
|
||||
|
||||
mvdbro (4):
|
||||
Custom WEB page handler (SPIFFS)
|
||||
Finished work on Level Control & config
|
||||
Fixed a tasksettings load bug that was introduced with commit dcfc1e3 on july 18th.
|
||||
Moved HTML template logging to level LOG_LEVEL_DEBUG_DEV
|
||||
|
||||
papperone (1):
|
||||
HDC1080 plugin (#497)
|
||||
|
||||
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev11
|
||||
-----------------------------
|
||||
|
||||
Release date: Mon Jul 17 00:55:29 CEST 2017
|
||||
|
||||
Daniel Tedenljung (5):
|
||||
Fixed decimal values (#329)
|
||||
Senseair update (#333)
|
||||
Reading error code in other way (#394)
|
||||
Added relay control from commands (#395)
|
||||
Renamed command to be unique. (#427)
|
||||
|
||||
DatuX (3):
|
||||
Update README.md
|
||||
Update issue_template.md
|
||||
Update issue_template.md
|
||||
|
||||
Edwin Eefting (27):
|
||||
cleaned up RTC initialisation. fixed some fuzzy issues after flashing/factory reset. improved flash-counter messages and added powercycle tips
|
||||
started working on regression testing scripts for The Rig
|
||||
large changes to wifi handling. code cleanup, more efficent connecting, only one connect retry in deepsleep. better serial logging for connections and APmode. always enable ap mode when wifi is disconnected
|
||||
prevent recursion when processing background tasks. might help with issue #117
|
||||
added option do deepsleep on connection failures. had to change boot order a bit, so the rebooted/warmboot message is the first one now. (this also makes more sense). issue #206
|
||||
better rtc error logging
|
||||
Fixed crashbug in email notification
|
||||
Fixed variable naming bug in FEATURE_ADC_VCC
|
||||
working on test framework
|
||||
esptesting framework
|
||||
dont want wifi passwords on github
|
||||
dont want wifi passwords on github
|
||||
converted all commands to python
|
||||
backup
|
||||
saved ~800 bytes ram in handle_devices(), issue #352. left old code commented for reference, in case i created bugs. will remove later
|
||||
accidently enabled FEATURE_ARDUINO_OTA
|
||||
fix #372
|
||||
serial now no longer resonds to empty commands
|
||||
add caching headers to static content
|
||||
upgraded IRremoteESP8266 from v1.0.2 to v1.2.0. fixes #188
|
||||
fix HTTP chunked transfer encoding, since WebServer class doesnt support it. this fixes the 2 second delay in some browsers. (we where out of spec.)
|
||||
more details AP mode serial output
|
||||
made mdns a feature. consitent use of hostname for both mdns and dhcp client. hostname now is name_unitnumber, with spaces replaced by -
|
||||
gave some html logging debug-level
|
||||
imlemented setting name, unit and password via serial. implements #317
|
||||
added note to inverse logic to fix #318
|
||||
automaticly updated release notes for v2.0.0-dev11
|
||||
|
||||
Gustavo Spadari (1):
|
||||
Adding comments on RAW code (#386) (#393)
|
||||
|
||||
JK (7):
|
||||
First draft
|
||||
Send web page as junked data
|
||||
Accept CR and LF at serial commands
|
||||
First draft
|
||||
Added Plugin for Touch KeyPad Chip TTP229
|
||||
Fine tuning of CSS and menu
|
||||
Reenabled javascript for device-selector
|
||||
|
||||
Jochen Krapf (25):
|
||||
Added _P054_DMX512 (#322)
|
||||
Added _P055_Chiming (#323)
|
||||
Added _P056_SDS011-Dust (#324)
|
||||
Added Plugin for Quadrature Encoder Interface (Rotary Encoder) (#335)
|
||||
Added Plugin _P061_KeyPad (#340)
|
||||
Added Plugin _P060_MCP3221 (#342)
|
||||
Formula option for _P013_HCSR04 plugin issue #343 #313 (#344)
|
||||
Fixed issues #308 #305 (#345)
|
||||
Added Plugin _P062_MPR121_KeyPad (#346)
|
||||
Fixed issue #348 (#349)
|
||||
Added plugins for HT16K33 LED matrix driver and key pad scanner (#328)
|
||||
Increase DEVICES_MAX for more testing and dev plugins (#353)
|
||||
Write default CSS to SPIFFS on boot (#357)
|
||||
Fixed DEVICES_MAX for testing and dev (#374)
|
||||
Step back to style-based-css for speed up + pimp menu (#376)
|
||||
Check plugin-array size on init - issue #119 (#389)
|
||||
Added Plugin for MP3 module (#402)
|
||||
Minor corrections and documentation (#404)
|
||||
Added Plugin for Gesture Sensor APDS9960 (#409)
|
||||
Added Plugin for Color Sensor VEML6040 (#412)
|
||||
Added Plugin for HX711 Load Cell - Request #408 (#415)
|
||||
Fixed multiline define bug on CRLF (#416)
|
||||
Added Value Logger on SD Card (#429)
|
||||
Plugin65 MP3 - volume updated in device menu - issue #424 (#438)
|
||||
Plugin HX711 - Added Tare function (#419)
|
||||
|
||||
PieVo (1):
|
||||
Update P053 (PMSx003) to support software serial and minor cleanup (#390)
|
||||
|
||||
SloMusti (3):
|
||||
fixed deep sleep, such that it can be enabled from Rules (#375)
|
||||
Implemented a better WiFI AP naming strategy. ESP_Easy has replaced the newdevice text as the default name and now the name is used as and AP SSID (#410)
|
||||
added mDNS implementation (#418)
|
||||
|
||||
elucas2uy (1):
|
||||
FIX Pass and Index on handle_controllers() (#331)
|
||||
|
||||
imthemichi (1):
|
||||
Plugin_008-RFID extended with wiegand 34-bits and key-pad (#387)
|
||||
|
||||
krikk (5):
|
||||
changed the ina219 plugin so that is always sends 3 values, voltage, current, power... like a normal plugin should do... (#325)
|
||||
delay option should be displayed even if the SendDataOption is false, because the delay option also controls the refresh rate of the oled display... fixes issue #336 (#339)
|
||||
seconds were displayed without leading zero issue #337 (#338)
|
||||
added local ip to sysinfo plugin, due to limitation of return type float, i had to split up the ip in its octets... fixes issue #228 (#341)
|
||||
implemented a measurement type selection to retain backward compability to Domoticz... hope this works... (#351)
|
||||
|
||||
mvdbro (8):
|
||||
Fix Domoticz helper plugin #330
|
||||
Enlarge MQTT buffer for Domoticz MQTT controller
|
||||
MQTT Controller enable/disable fix (#287)
|
||||
Fix incorrect ADC GPIO display
|
||||
Fix default controller settings (#360)
|
||||
Added pin state buffer table page (mainly for debugging)
|
||||
Update checkRAM function
|
||||
Revert to default ESP Easy colorscheme
|
||||
|
||||
papperone (5):
|
||||
Fixed Broken P038
|
||||
p038
|
||||
reverted some changes due to bug fixed in the "webserver.ino #348"
|
||||
P038 - optimization
|
||||
P010 plugin optimization (#403)
|
||||
|
||||
tedenda (2):
|
||||
Renamed Prefix from P011 to C011
|
||||
Missed one...
|
||||
|
||||
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev10
|
||||
-----------------------------
|
||||
|
||||
Release date: Mon May 29 22:53:54 CEST 2017
|
||||
|
||||
DatuX (1):
|
||||
Update README.md
|
||||
|
||||
Jochen Krapf (1):
|
||||
Rework of plugin ADC (#319)
|
||||
|
||||
krikk (1):
|
||||
reverted change, this fix seems to have exactly opposite outcome than expected... with the fix applied i get errors, without is i get no errors... (#320)
|
||||
|
||||
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev9
|
||||
-----------------------------
|
||||
|
||||
Release date: Sun May 28 15:16:00 CEST 2017
|
||||
|
||||
Alex Schwantes (1):
|
||||
Implemented use of addFormSelector methods to _P004_Dallas plugin. Changed the device select box to show the one wire address for each connected sensor instead of just a number. Added a blank option to the device address select box so that in the event that multiple devices are present and the configured device is not currently available, the select box will be blank instead of selecting a different device.
|
||||
|
||||
Bartlomiej Zimon (5):
|
||||
- Misc: typo
|
||||
Custom Controller Settings - add controller index
|
||||
Push ProtocolIndex and ControllerIndex into CPLUGIN_WEBFORM_SAVE/LOAD
|
||||
Add WifiSSID2,WifiKey2 commands
|
||||
Add backup Wifi network to Settings command
|
||||
|
||||
Blair Thompson (1):
|
||||
Added Par4 and Par5 Variables (#248)
|
||||
|
||||
Daniel Tedenljung (5):
|
||||
Updated wrong plugin number. (#269)
|
||||
P052: More descriptive log messages (#283)
|
||||
GUI touchup on Tools (#286)
|
||||
addSubmitButton function added (#289)
|
||||
New look on Tools page (#296)
|
||||
|
||||
DatuX (5):
|
||||
Update README.md
|
||||
Update issue_template.md
|
||||
Update CONTRIBUTING.md
|
||||
Update README.md
|
||||
Update README.md
|
||||
|
||||
Edwin Eefting (17):
|
||||
cleaned up messagedelay: use the same function everywhere. and do serial processing as well during the messagedelay
|
||||
fixed issue #253 (memory leaks/crashes)
|
||||
more details in memory analyser. run memory analyser via Travis
|
||||
cosmetic buildlog fix
|
||||
publish MQTT Connected message
|
||||
timer boundschecker was off by one. fixed memanalyser total
|
||||
input box fix on setting pages
|
||||
comments. checkudp only in backgroundtasks()
|
||||
reboot and wifidisconnect should be handled by /
|
||||
bugfix in rtc checksum
|
||||
nicer sleep messages
|
||||
fixed a few out of bounds bugs in Misc.ino _P023_OLED.ino _P035_IRTX.ino _P037_MQTTImport.ino with cppcheck. also added cppcheck to travis to prevent such cases in the future
|
||||
fixing cpp check
|
||||
fixing cpp check
|
||||
fixing cpp check
|
||||
fixing cpp check
|
||||
also distribute ESP8285 binaries
|
||||
|
||||
JK (5):
|
||||
added functions addCheckBox and addNumericBox
|
||||
added checkbox for status LED inversed
|
||||
fine tuning of status LED and pimp hardware web site
|
||||
solved my commit mismatch
|
||||
Fixed #196 and rework of IDX display
|
||||
|
||||
Jochen Krapf (11):
|
||||
Added addForm*-functions for easy web-interface and pimp GUI (#259)
|
||||
Added function addFormSelector (#270)
|
||||
Preliminary final draft of bugfix #264 (#271)
|
||||
Replaced HTML code with addFormSelector() in all plugins (#278)
|
||||
Fixed readUserVarFromRTC() #265 (#280)
|
||||
Limits to NumericBox and a bit of security to PasswordBox (#281)
|
||||
Added HTML templates for customization (#290)
|
||||
Fixed rules bug #297 (#299)
|
||||
Pimp device-GUI and optimized HTML (#306)
|
||||
Fixed some minor HTML syntax bugs (#310)
|
||||
Rework of plugin ADS1115 (#315)
|
||||
|
||||
PieVo (1):
|
||||
Plantower (#300)
|
||||
|
||||
beic (1):
|
||||
Some little description corrections (#297)
|
||||
|
||||
krikk (13):
|
||||
http advanced controller, correct passing of hostname (#250)
|
||||
i2c Temperatur & Humidity Sensor Am2320 (#251)
|
||||
use the new addCheckBox function and better display of device config page
|
||||
another fix to http advanced...
|
||||
replaced static html code with the new addForm* Functions
|
||||
bug fix wrong return type + form function fixes (#266)
|
||||
addFormNumeric with min and max & More Form-Function replacements (#272)
|
||||
make the Settings - Save. Filename more descriptive... (#273)
|
||||
addHelpButton Function and a new Help Button for the Rules and Hardware Page (#282)
|
||||
DHT plugin fix 'NaN' issue (#285)
|
||||
i don't like hidden features, added a json button to the tools menu, next to the advanced button (#292)
|
||||
do a dns lookup on every request, solves issue #261 (#302)
|
||||
AM2320: negative temperature fix... (#312)
|
||||
|
||||
tedenda (1):
|
||||
Moving plugin from Playground into main repo. (#262)
|
||||
|
||||
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev8
|
||||
-----------------------------
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,59 @@
|
||||
#include "AM2320.h"
|
||||
#include <Wire.h>
|
||||
//
|
||||
// AM2321 Temperature & Humidity Sensor library for Arduino
|
||||
// Сделана Тимофеевым Е.Н. из AM2320-master
|
||||
|
||||
unsigned int CRC16(byte *ptr, byte length)
|
||||
{
|
||||
unsigned int crc = 0xFFFF;
|
||||
uint8_t s = 0x00;
|
||||
|
||||
while(length--) {
|
||||
crc ^= *ptr++;
|
||||
for(s = 0; s < 8; s++) {
|
||||
if((crc & 0x01) != 0) {
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
} else crc >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
AM2320::AM2320()
|
||||
{
|
||||
}
|
||||
|
||||
int AM2320::Read()
|
||||
{
|
||||
byte buf[8];
|
||||
for(int s = 0; s < 8; s++) buf[s] = 0x00;
|
||||
|
||||
Wire.beginTransmission(AM2320_address);
|
||||
Wire.endTransmission();
|
||||
// запрос 4 байт (температуры и влажности)
|
||||
Wire.beginTransmission(AM2320_address);
|
||||
Wire.write(0x03);// запрос
|
||||
Wire.write(0x00); // с 0-го адреса
|
||||
Wire.write(0x04); // 4 байта
|
||||
if (Wire.endTransmission(1) != 0) return 1;
|
||||
delayMicroseconds(1600); //>1.5ms
|
||||
// считываем результаты запроса
|
||||
Wire.requestFrom(AM2320_address, 0x08);
|
||||
for (int i = 0; i < 0x08; i++) buf[i] = Wire.read();
|
||||
|
||||
// CRC check
|
||||
unsigned int Rcrc = buf[7] << 8;
|
||||
Rcrc += buf[6];
|
||||
if (Rcrc == CRC16(buf, 6)) {
|
||||
unsigned int temperature = ((buf[4] & 0x7F) << 8) + buf[5];
|
||||
t = temperature / 10.0;
|
||||
t = ((buf[4] & 0x80) >> 7) == 1 ? t * (-1) : t;
|
||||
|
||||
unsigned int humidity = (buf[2] << 8) + buf[3];
|
||||
h = humidity / 10.0;
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef AM2320_H
|
||||
#define AM2320_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define AM2320_address (0xB8 >> 1)
|
||||
|
||||
class AM2320
|
||||
{
|
||||
public:
|
||||
AM2320();
|
||||
float t;
|
||||
float h;
|
||||
int Read(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <Wire.h>
|
||||
#include <AM2320.h>
|
||||
|
||||
AM2320 th;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
switch(th.Read()) {
|
||||
case 2:
|
||||
Serial.println("CRC failed");
|
||||
break;
|
||||
case 1:
|
||||
Serial.println("Sensor offline");
|
||||
break;
|
||||
case 0:
|
||||
Serial.print("humidity: ");
|
||||
Serial.print(th.h);
|
||||
Serial.print("%, temperature: ");
|
||||
Serial.print(th.t);
|
||||
Serial.println("*C");
|
||||
break;
|
||||
}
|
||||
|
||||
delay(200);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
AM2320 KEYWORD1
|
||||
getTemperature KEYWORD2
|
||||
getHumidity KEYWORD2
|
||||
CRCCheck KEYWORD2
|
||||
@@ -0,0 +1,132 @@
|
||||
/***************************************************
|
||||
This is a library for the MPR121 I2C 12-chan Capacitive Sensor
|
||||
|
||||
Designed specifically to work with the MPR121 sensor from Adafruit
|
||||
----> https://www.adafruit.com/products/1982
|
||||
|
||||
These sensors use I2C to communicate, 2+ pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include "Adafruit_MPR121.h"
|
||||
|
||||
Adafruit_MPR121::Adafruit_MPR121() {
|
||||
}
|
||||
|
||||
boolean Adafruit_MPR121::begin(uint8_t i2caddr) {
|
||||
Wire.begin();
|
||||
|
||||
_i2caddr = i2caddr;
|
||||
|
||||
// soft reset
|
||||
writeRegister(MPR121_SOFTRESET, 0x63);
|
||||
delay(1);
|
||||
for (uint8_t i=0; i<0x7F; i++) {
|
||||
// Serial.print("$"); Serial.print(i, HEX);
|
||||
// Serial.print(": 0x"); Serial.println(readRegister8(i));
|
||||
}
|
||||
|
||||
|
||||
writeRegister(MPR121_ECR, 0x0);
|
||||
|
||||
uint8_t c = readRegister8(MPR121_CONFIG2);
|
||||
|
||||
if (c != 0x24) return false;
|
||||
|
||||
|
||||
setThresholds(12, 6);
|
||||
writeRegister(MPR121_MHDR, 0x01);
|
||||
writeRegister(MPR121_NHDR, 0x01);
|
||||
writeRegister(MPR121_NCLR, 0x0E);
|
||||
writeRegister(MPR121_FDLR, 0x00);
|
||||
|
||||
writeRegister(MPR121_MHDF, 0x01);
|
||||
writeRegister(MPR121_NHDF, 0x05);
|
||||
writeRegister(MPR121_NCLF, 0x01);
|
||||
writeRegister(MPR121_FDLF, 0x00);
|
||||
|
||||
writeRegister(MPR121_NHDT, 0x00);
|
||||
writeRegister(MPR121_NCLT, 0x00);
|
||||
writeRegister(MPR121_FDLT, 0x00);
|
||||
|
||||
writeRegister(MPR121_DEBOUNCE, 0);
|
||||
writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
|
||||
writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
|
||||
|
||||
// writeRegister(MPR121_AUTOCONFIG0, 0x8F);
|
||||
|
||||
// writeRegister(MPR121_UPLIMIT, 150);
|
||||
// writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
|
||||
// writeRegister(MPR121_LOWLIMIT, 50);
|
||||
// enable all electrodes
|
||||
writeRegister(MPR121_ECR, 0x8F); // start with first 5 bits of baseline tracking
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Adafruit_MPR121::setThreshholds(uint8_t touch, uint8_t release) {
|
||||
|
||||
setThresholds(touch, release);
|
||||
}
|
||||
|
||||
void Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t release) {
|
||||
for (uint8_t i=0; i<12; i++) {
|
||||
writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
|
||||
writeRegister(MPR121_RELEASETH_0 + 2*i, release);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Adafruit_MPR121::filteredData(uint8_t t) {
|
||||
if (t > 12) return 0;
|
||||
return readRegister16(MPR121_FILTDATA_0L + t*2);
|
||||
}
|
||||
|
||||
uint16_t Adafruit_MPR121::baselineData(uint8_t t) {
|
||||
if (t > 12) return 0;
|
||||
uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
|
||||
return (bl << 2);
|
||||
}
|
||||
|
||||
uint16_t Adafruit_MPR121::touched(void) {
|
||||
uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
|
||||
return t & 0x0FFF;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
uint8_t Adafruit_MPR121::readRegister8(uint8_t reg) {
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission(false);
|
||||
while (Wire.requestFrom(_i2caddr, 1) != 1);
|
||||
return ( Wire.read());
|
||||
}
|
||||
|
||||
uint16_t Adafruit_MPR121::readRegister16(uint8_t reg) {
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission(false);
|
||||
while (Wire.requestFrom(_i2caddr, 2) != 2);
|
||||
uint16_t v = Wire.read();
|
||||
v |= ((uint16_t) Wire.read()) << 8;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Writes 8-bits to the specified destination register
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_MPR121::writeRegister(uint8_t reg, uint8_t value) {
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)(value));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************
|
||||
This is a library for the MPR121 12-Channel Capacitive Sensor
|
||||
|
||||
Designed specifically to work with the MPR121 breakout from Adafruit
|
||||
----> https://www.adafruit.com/products/1982
|
||||
|
||||
These sensors use I2C to communicate, 2+ pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifndef ADAFRUIT_MPR121_H
|
||||
#define ADAFRUIT_MPR121_H
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
|
||||
// The default I2C address
|
||||
#define MPR121_I2CADDR_DEFAULT 0x5A
|
||||
|
||||
#define MPR121_TOUCHSTATUS_L 0x00
|
||||
#define MPR121_TOUCHSTATUS_H 0x01
|
||||
#define MPR121_FILTDATA_0L 0x04
|
||||
#define MPR121_FILTDATA_0H 0x05
|
||||
#define MPR121_BASELINE_0 0x1E
|
||||
#define MPR121_MHDR 0x2B
|
||||
#define MPR121_NHDR 0x2C
|
||||
#define MPR121_NCLR 0x2D
|
||||
#define MPR121_FDLR 0x2E
|
||||
#define MPR121_MHDF 0x2F
|
||||
#define MPR121_NHDF 0x30
|
||||
#define MPR121_NCLF 0x31
|
||||
#define MPR121_FDLF 0x32
|
||||
#define MPR121_NHDT 0x33
|
||||
#define MPR121_NCLT 0x34
|
||||
#define MPR121_FDLT 0x35
|
||||
|
||||
#define MPR121_TOUCHTH_0 0x41
|
||||
#define MPR121_RELEASETH_0 0x42
|
||||
#define MPR121_DEBOUNCE 0x5B
|
||||
#define MPR121_CONFIG1 0x5C
|
||||
#define MPR121_CONFIG2 0x5D
|
||||
#define MPR121_CHARGECURR_0 0x5F
|
||||
#define MPR121_CHARGETIME_1 0x6C
|
||||
#define MPR121_ECR 0x5E
|
||||
#define MPR121_AUTOCONFIG0 0x7B
|
||||
#define MPR121_AUTOCONFIG1 0x7C
|
||||
#define MPR121_UPLIMIT 0x7D
|
||||
#define MPR121_LOWLIMIT 0x7E
|
||||
#define MPR121_TARGETLIMIT 0x7F
|
||||
|
||||
#define MPR121_GPIODIR 0x76
|
||||
#define MPR121_GPIOEN 0x77
|
||||
#define MPR121_GPIOSET 0x78
|
||||
#define MPR121_GPIOCLR 0x79
|
||||
#define MPR121_GPIOTOGGLE 0x7A
|
||||
|
||||
|
||||
|
||||
#define MPR121_SOFTRESET 0x80
|
||||
|
||||
//.. thru to 0x1C/0x1D
|
||||
class Adafruit_MPR121 {
|
||||
public:
|
||||
// Hardware I2C
|
||||
Adafruit_MPR121(void);
|
||||
|
||||
boolean begin(uint8_t i2caddr = MPR121_I2CADDR_DEFAULT);
|
||||
|
||||
uint16_t filteredData(uint8_t t);
|
||||
uint16_t baselineData(uint8_t t);
|
||||
|
||||
uint8_t readRegister8(uint8_t reg);
|
||||
uint16_t readRegister16(uint8_t reg);
|
||||
void writeRegister(uint8_t reg, uint8_t value);
|
||||
uint16_t touched(void);
|
||||
// Add deprecated attribute so that the compiler shows a warning
|
||||
__attribute__((deprecated)) void setThreshholds(uint8_t touch, uint8_t release);
|
||||
void setThresholds(uint8_t touch, uint8_t release);
|
||||
|
||||
private:
|
||||
int8_t _i2caddr;
|
||||
};
|
||||
|
||||
#endif // ADAFRUIT_MPR121_H
|
||||
@@ -0,0 +1,32 @@
|
||||
# Adafruit_MPR121_Library
|
||||
<!-- START COMPATIBILITY TABLE -->
|
||||
|
||||
## Compatibility
|
||||
|
||||
MCU | Tested Works | Doesn't Work | Not Tested | Notes
|
||||
------------------ | :----------: | :----------: | :---------: | -----
|
||||
Atmega328 @ 16MHz | X | | |
|
||||
Atmega328 @ 12MHz | X | | |
|
||||
Atmega32u4 @ 16MHz | X | | |
|
||||
Atmega32u4 @ 8MHz | X | | |
|
||||
ESP8266 | | X | |
|
||||
Atmega2560 @ 16MHz | X | | |
|
||||
ATSAM3X8E | | X | |
|
||||
ATSAM21D | X | | |
|
||||
ATtiny85 @ 16MHz | | | X |
|
||||
ATtiny85 @ 8MHz | | | X |
|
||||
Intel Curie @ 32MHz | | | X |
|
||||
STM32F2 | | | X |
|
||||
|
||||
* ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
|
||||
* ATmega328 @ 12MHz : Adafruit Pro Trinket 3V
|
||||
* ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0
|
||||
* ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro
|
||||
* ESP8266 : Adafruit Huzzah
|
||||
* ATmega2560 @ 16MHz : Arduino Mega
|
||||
* ATSAM3X8E : Arduino Due
|
||||
* ATSAM21D : Arduino Zero, M0 Pro
|
||||
* ATtiny85 @ 16MHz : Adafruit Trinket 5V
|
||||
* ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V
|
||||
|
||||
<!-- END COMPATIBILITY TABLE -->
|
||||
@@ -0,0 +1,25 @@
|
||||
This is a library for the MPR121 12-channel Capacitive touch sensor
|
||||
|
||||
Designed specifically to work with the MPR121 Breakout in the Adafruit shop
|
||||
----> https://www.adafruit.com/products/1982
|
||||
|
||||
These sensors use I2C communicate, at least 2 pins are required
|
||||
to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
|
||||
To download. click the ZIP button, and rename the uncompressed folder Adafruit_MPR121
|
||||
Check that the Adafruit_MPR121 folder contains Adafruit_MPR121.cpp and Adafruit_MPR121.h
|
||||
|
||||
Place the Adafruit_MPR121 library folder your arduinosketchfolder/libraries/ folder.
|
||||
You may need to create the libraries subfolder if its your first library. Restart the IDE.
|
||||
|
||||
We also have a great tutorial on Arduino library installation at:
|
||||
http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use
|
||||
@@ -0,0 +1,83 @@
|
||||
/*********************************************************
|
||||
This is a library for the MPR121 12-channel Capacitive touch sensor
|
||||
|
||||
Designed specifically to work with the MPR121 Breakout in the Adafruit shop
|
||||
----> https://www.adafruit.com/products/
|
||||
|
||||
These sensors use I2C communicate, at least 2 pins are required
|
||||
to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
**********************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include "Adafruit_MPR121.h"
|
||||
|
||||
// You can have up to 4 on one i2c bus but one is enough for testing!
|
||||
Adafruit_MPR121 cap = Adafruit_MPR121();
|
||||
|
||||
// Keeps track of the last pins touched
|
||||
// so we know when buttons are 'released'
|
||||
uint16_t lasttouched = 0;
|
||||
uint16_t currtouched = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
while (!Serial) { // needed to keep leonardo/micro from starting too fast!
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Serial.println("Adafruit MPR121 Capacitive Touch sensor test");
|
||||
|
||||
// Default address is 0x5A, if tied to 3.3V its 0x5B
|
||||
// If tied to SDA its 0x5C and if SCL then 0x5D
|
||||
if (!cap.begin(0x5A)) {
|
||||
Serial.println("MPR121 not found, check wiring?");
|
||||
while (1);
|
||||
}
|
||||
Serial.println("MPR121 found!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Get the currently touched pads
|
||||
currtouched = cap.touched();
|
||||
|
||||
for (uint8_t i=0; i<12; i++) {
|
||||
// it if *is* touched and *wasnt* touched before, alert!
|
||||
if ((currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) {
|
||||
Serial.print(i); Serial.println(" touched");
|
||||
}
|
||||
// if it *was* touched and now *isnt*, alert!
|
||||
if (!(currtouched & _BV(i)) && (lasttouched & _BV(i)) ) {
|
||||
Serial.print(i); Serial.println(" released");
|
||||
}
|
||||
}
|
||||
|
||||
// reset our state
|
||||
lasttouched = currtouched;
|
||||
|
||||
// comment out this line for detailed data from the sensor!
|
||||
return;
|
||||
|
||||
// debugging info, what
|
||||
Serial.print("\t\t\t\t\t\t\t\t\t\t\t\t\t 0x"); Serial.println(cap.touched(), HEX);
|
||||
Serial.print("Filt: ");
|
||||
for (uint8_t i=0; i<12; i++) {
|
||||
Serial.print(cap.filteredData(i)); Serial.print("\t");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print("Base: ");
|
||||
for (uint8_t i=0; i<12; i++) {
|
||||
Serial.print(cap.baselineData(i)); Serial.print("\t");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// put a delay so it isn't overwhelming
|
||||
delay(100);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Adafruit_MPR121 KEYWORD1
|
||||
begin KEYWORD2
|
||||
filteredData KEYWORD2
|
||||
baselineData KEYWORD2
|
||||
touched KEYWORD2
|
||||
setThresholds KEYWORD2
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit MPR121
|
||||
version=1.0.0
|
||||
author=Adafruit <info@adafruit.com>
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Arduino library for the MPR121-based capacitive sensors in the Adafruit shop.
|
||||
paragraph=Designed specifically to work with the MPR121 Breakout in the Adafruit shop.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_MPR121
|
||||
architectures=*
|
||||
@@ -1,14 +1,14 @@
|
||||
/******************************************************************
|
||||
This is the library for the Adafruit Motor Shield V2 for Arduino.
|
||||
This is the library for the Adafruit Motor Shield V2 for Arduino.
|
||||
It supports DC motors & Stepper motors with microstepping as well
|
||||
as stacking-support. It is *not* compatible with the V1 library!
|
||||
|
||||
It will only work with https://www.adafruit.com/products/1483
|
||||
|
||||
|
||||
Adafruit invests time and resources providing this open
|
||||
source code, please support Adafruit and open-source hardware
|
||||
by purchasing products from Adafruit!
|
||||
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information.
|
||||
All text above must be included in any redistribution.
|
||||
@@ -48,14 +48,14 @@ void Adafruit_MotorShield::begin(uint16_t freq) {
|
||||
_pwm.begin();
|
||||
_freq = freq;
|
||||
_pwm.setPWMFreq(_freq); // This is the maximum PWM frequency
|
||||
for (uint8_t i=0; i<16; i++)
|
||||
for (uint8_t i=0; i<16; i++)
|
||||
_pwm.setPWM(i, 0, 0);
|
||||
}
|
||||
|
||||
void Adafruit_MotorShield::setPWM(uint8_t pin, uint16_t value) {
|
||||
if (value > 4095) {
|
||||
_pwm.setPWM(pin, 4096, 0);
|
||||
} else
|
||||
} else
|
||||
_pwm.setPWM(pin, 0, value);
|
||||
}
|
||||
void Adafruit_MotorShield::setPin(uint8_t pin, boolean value) {
|
||||
@@ -170,7 +170,7 @@ uint16_t steps, Adafruit_MotorShield controller) {
|
||||
if (steppernum == 1) {
|
||||
latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) &
|
||||
~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0
|
||||
|
||||
|
||||
// enable both H bridges
|
||||
pinMode(11, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
@@ -282,7 +282,7 @@ uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) {
|
||||
} else {
|
||||
currentstep -= MICROSTEPS/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (style == MICROSTEP) {
|
||||
if (dir == FORWARD) {
|
||||
@@ -316,12 +316,12 @@ uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) {
|
||||
|
||||
#ifdef MOTORDEBUG
|
||||
Serial.print("current step: "); Serial.println(currentstep, DEC);
|
||||
Serial.print(" pwmA = "); Serial.print(ocra, DEC);
|
||||
Serial.print(" pwmB = "); Serial.println(ocrb, DEC);
|
||||
Serial.print(" pwmA = "); Serial.print(ocra, DEC);
|
||||
Serial.print(" pwmB = "); Serial.println(ocrb, DEC);
|
||||
#endif
|
||||
MC->setPWM(PWMApin, ocra*16);
|
||||
MC->setPWM(PWMBpin, ocrb*16);
|
||||
|
||||
|
||||
|
||||
// release all
|
||||
uint8_t latch_state = 0; // all motor pins to 0
|
||||
@@ -352,7 +352,7 @@ uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) {
|
||||
break;
|
||||
case 4:
|
||||
latch_state |= 0x4; // energize coil 3 only
|
||||
break;
|
||||
break;
|
||||
case 5:
|
||||
latch_state |= 0xC; // energize coil 3+4
|
||||
break;
|
||||
@@ -395,4 +395,3 @@ uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) {
|
||||
|
||||
return currentstep;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software< /span>
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
|
||||
* extended sensor support to include color, voltage and current */
|
||||
|
||||
#ifndef _ADAFRUIT_SENSOR_H
|
||||
#define _ADAFRUIT_SENSOR_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
/* Intentionally modeled after sensors.h in the Android API:
|
||||
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */
|
||||
|
||||
/* Constants */
|
||||
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
|
||||
#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */
|
||||
#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */
|
||||
#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
|
||||
#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */
|
||||
#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */
|
||||
|
||||
/** Sensor types */
|
||||
typedef enum
|
||||
{
|
||||
SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
|
||||
SENSOR_TYPE_MAGNETIC_FIELD = (2),
|
||||
SENSOR_TYPE_ORIENTATION = (3),
|
||||
SENSOR_TYPE_GYROSCOPE = (4),
|
||||
SENSOR_TYPE_LIGHT = (5),
|
||||
SENSOR_TYPE_PRESSURE = (6),
|
||||
SENSOR_TYPE_PROXIMITY = (8),
|
||||
SENSOR_TYPE_GRAVITY = (9),
|
||||
SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */
|
||||
SENSOR_TYPE_ROTATION_VECTOR = (11),
|
||||
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
|
||||
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
|
||||
SENSOR_TYPE_VOLTAGE = (15),
|
||||
SENSOR_TYPE_CURRENT = (16),
|
||||
SENSOR_TYPE_COLOR = (17)
|
||||
} sensors_type_t;
|
||||
|
||||
/** struct sensors_vec_s is used to return a vector in a common format. */
|
||||
typedef struct {
|
||||
union {
|
||||
float v[3];
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
/* Orientation sensors */
|
||||
struct {
|
||||
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
|
||||
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
|
||||
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
|
||||
};
|
||||
};
|
||||
int8_t status;
|
||||
uint8_t reserved[3];
|
||||
} sensors_vec_t;
|
||||
|
||||
/** struct sensors_color_s is used to return color data in a common format. */
|
||||
typedef struct {
|
||||
union {
|
||||
float c[3];
|
||||
/* RGB color space */
|
||||
struct {
|
||||
float r; /**< Red component */
|
||||
float g; /**< Green component */
|
||||
float b; /**< Blue component */
|
||||
};
|
||||
};
|
||||
uint32_t rgba; /**< 24-bit RGBA value */
|
||||
} sensors_color_t;
|
||||
|
||||
/* Sensor event (36 bytes) */
|
||||
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
|
||||
typedef struct
|
||||
{
|
||||
int32_t version; /**< must be sizeof(struct sensors_event_t) */
|
||||
int32_t sensor_id; /**< unique sensor identifier */
|
||||
int32_t type; /**< sensor type */
|
||||
int32_t reserved0; /**< reserved */
|
||||
int32_t timestamp; /**< time is in milliseconds */
|
||||
union
|
||||
{
|
||||
float data[4];
|
||||
sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */
|
||||
sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
|
||||
sensors_vec_t orientation; /**< orientation values are in degrees */
|
||||
sensors_vec_t gyro; /**< gyroscope values are in rad/s */
|
||||
float temperature; /**< temperature is in degrees centigrade (Celsius) */
|
||||
float distance; /**< distance in centimeters */
|
||||
float light; /**< light in SI lux units */
|
||||
float pressure; /**< pressure in hectopascal (hPa) */
|
||||
float relative_humidity; /**< relative humidity in percent */
|
||||
float current; /**< current in milliamps (mA) */
|
||||
float voltage; /**< voltage in volts (V) */
|
||||
sensors_color_t color; /**< color in RGB component values */
|
||||
};
|
||||
} sensors_event_t;
|
||||
|
||||
/* Sensor details (40 bytes) */
|
||||
/** struct sensor_s is used to describe basic information about a specific sensor. */
|
||||
typedef struct
|
||||
{
|
||||
char name[12]; /**< sensor name */
|
||||
int32_t version; /**< version of the hardware + driver */
|
||||
int32_t sensor_id; /**< unique sensor identifier */
|
||||
int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
|
||||
float max_value; /**< maximum value of this sensor's value in SI units */
|
||||
float min_value; /**< minimum value of this sensor's value in SI units */
|
||||
float resolution; /**< smallest difference between two values reported by this sensor */
|
||||
int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */
|
||||
} sensor_t;
|
||||
|
||||
class Adafruit_Sensor {
|
||||
public:
|
||||
// Constructor(s)
|
||||
Adafruit_Sensor() {}
|
||||
virtual ~Adafruit_Sensor() {}
|
||||
|
||||
// These must be defined by the subclass
|
||||
virtual void enableAutoRange(bool enabled) {};
|
||||
virtual bool getEvent(sensors_event_t*) = 0;
|
||||
virtual void getSensor(sensor_t*) = 0;
|
||||
|
||||
private:
|
||||
bool _autoRange;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,221 @@
|
||||
# Adafruit Unified Sensor Driver #
|
||||
|
||||
Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing.
|
||||
|
||||
One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road.
|
||||
|
||||
Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement.
|
||||
|
||||
By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse.
|
||||
|
||||
The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire.
|
||||
|
||||
## Unified Sensor Drivers ##
|
||||
|
||||
The following drivers are based on the Adafruit Unified Sensor Driver:
|
||||
|
||||
**Accelerometers**
|
||||
- [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345)
|
||||
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
|
||||
- [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library)
|
||||
|
||||
**Gyroscope**
|
||||
- [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U)
|
||||
|
||||
**Light**
|
||||
- [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561)
|
||||
- [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library)
|
||||
|
||||
**Magnetometers**
|
||||
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
|
||||
- [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified)
|
||||
|
||||
**Barometric Pressure**
|
||||
- [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified)
|
||||
- [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library)
|
||||
|
||||
**Humidity & Temperature**
|
||||
- [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library)
|
||||
|
||||
**Orientation**
|
||||
- [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055)
|
||||
|
||||
## How Does it Work? ##
|
||||
|
||||
Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values:
|
||||
|
||||
**Sensor Types (sensors\_type\_t)**
|
||||
|
||||
These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc.
|
||||
|
||||
```
|
||||
/** Sensor types */
|
||||
typedef enum
|
||||
{
|
||||
SENSOR_TYPE_ACCELEROMETER = (1),
|
||||
SENSOR_TYPE_MAGNETIC_FIELD = (2),
|
||||
SENSOR_TYPE_ORIENTATION = (3),
|
||||
SENSOR_TYPE_GYROSCOPE = (4),
|
||||
SENSOR_TYPE_LIGHT = (5),
|
||||
SENSOR_TYPE_PRESSURE = (6),
|
||||
SENSOR_TYPE_PROXIMITY = (8),
|
||||
SENSOR_TYPE_GRAVITY = (9),
|
||||
SENSOR_TYPE_LINEAR_ACCELERATION = (10),
|
||||
SENSOR_TYPE_ROTATION_VECTOR = (11),
|
||||
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
|
||||
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
|
||||
SENSOR_TYPE_VOLTAGE = (15),
|
||||
SENSOR_TYPE_CURRENT = (16),
|
||||
SENSOR_TYPE_COLOR = (17)
|
||||
} sensors_type_t;
|
||||
```
|
||||
|
||||
**Sensor Details (sensor\_t)**
|
||||
|
||||
This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer.
|
||||
|
||||
```
|
||||
/* Sensor details (40 bytes) */
|
||||
/** struct sensor_s is used to describe basic information about a specific sensor. */
|
||||
typedef struct
|
||||
{
|
||||
char name[12];
|
||||
int32_t version;
|
||||
int32_t sensor_id;
|
||||
int32_t type;
|
||||
float max_value;
|
||||
float min_value;
|
||||
float resolution;
|
||||
int32_t min_delay;
|
||||
} sensor_t;
|
||||
```
|
||||
|
||||
The individual fields are intended to be used as follows:
|
||||
|
||||
- **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2")
|
||||
- **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver
|
||||
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network
|
||||
- **type**: The sensor type, based on **sensors\_type\_t** in sensors.h
|
||||
- **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit)
|
||||
- **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit)
|
||||
- **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit)
|
||||
- **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate
|
||||
|
||||
**Sensor Data/Events (sensors\_event\_t)**
|
||||
|
||||
This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales.
|
||||
|
||||
```
|
||||
/* Sensor event (36 bytes) */
|
||||
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
|
||||
typedef struct
|
||||
{
|
||||
int32_t version;
|
||||
int32_t sensor_id;
|
||||
int32_t type;
|
||||
int32_t reserved0;
|
||||
int32_t timestamp;
|
||||
union
|
||||
{
|
||||
float data[4];
|
||||
sensors_vec_t acceleration;
|
||||
sensors_vec_t magnetic;
|
||||
sensors_vec_t orientation;
|
||||
sensors_vec_t gyro;
|
||||
float temperature;
|
||||
float distance;
|
||||
float light;
|
||||
float pressure;
|
||||
float relative_humidity;
|
||||
float current;
|
||||
float voltage;
|
||||
sensors_color_t color;
|
||||
};
|
||||
} sensors_event_t;
|
||||
```
|
||||
It includes the following fields:
|
||||
|
||||
- **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future
|
||||
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!)
|
||||
- **type**: the sensor type, based on **sensors\_type\_t** in sensors.h
|
||||
- **timestamp**: time in milliseconds when the sensor value was read
|
||||
- **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below)
|
||||
|
||||
**Required Functions**
|
||||
|
||||
In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions:
|
||||
|
||||
```
|
||||
bool getEvent(sensors_event_t*);
|
||||
```
|
||||
Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data.
|
||||
|
||||
```
|
||||
void getSensor(sensor_t*);
|
||||
```
|
||||
Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc.
|
||||
|
||||
**Standardised SI values for sensors\_event\_t**
|
||||
|
||||
A key part of the abstraction layer is the standardisation of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales:
|
||||
|
||||
- **acceleration**: values are in **meter per second per second** (m/s^2)
|
||||
- **magnetic**: values are in **micro-Tesla** (uT)
|
||||
- **orientation**: values are in **degrees**
|
||||
- **gyro**: values are in **rad/s**
|
||||
- **temperature**: values in **degrees centigrade** (Celsius)
|
||||
- **distance**: values are in **centimeters**
|
||||
- **light**: values are in **SI lux** units
|
||||
- **pressure**: values are in **hectopascal** (hPa)
|
||||
- **relative\_humidity**: values are in **percent**
|
||||
- **current**: values are in **milliamps** (mA)
|
||||
- **voltage**: values are in **volts** (V)
|
||||
- **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format
|
||||
|
||||
## The Unified Driver Abstraction Layer in Practice ##
|
||||
|
||||
Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created.
|
||||
|
||||
Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardised way of interrogating a sensor about its specific capabilities (via sensor\_t).
|
||||
|
||||
An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below:
|
||||
|
||||
```
|
||||
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
|
||||
...
|
||||
/* Get a new sensor event */
|
||||
sensors_event_t event;
|
||||
tsl.getEvent(&event);
|
||||
|
||||
/* Display the results (light is measured in lux) */
|
||||
if (event.light)
|
||||
{
|
||||
Serial.print(event.light); Serial.println(" lux");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If event.light = 0 lux the sensor is probably saturated
|
||||
and no reliable data could be generated! */
|
||||
Serial.println("Sensor overload");
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, we can get the basic technical capabilities of this sensor with the following code:
|
||||
|
||||
```
|
||||
sensor_t sensor;
|
||||
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
|
||||
/* Display the sensor details */
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Sensor: "); Serial.println(sensor.name);
|
||||
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
|
||||
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
|
||||
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
|
||||
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
|
||||
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit Unified Sensor
|
||||
version=1.0.2
|
||||
author=Adafruit <info@adafruit.com>
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Required for all Adafruit Unified Sensor based libraries.
|
||||
paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_Sensor
|
||||
architectures=*
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
||||
@@ -0,0 +1,26 @@
|
||||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
||||
@@ -0,0 +1,504 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_TSL2591.cpp
|
||||
@author KT0WN (adafruit.com)
|
||||
|
||||
This is a library for the Adafruit TSL2591 breakout board
|
||||
This library works with the Adafruit TSL2591 breakout
|
||||
----> https://www.adafruit.com/products/1980
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2014 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:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. 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.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''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 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.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#include <pgmspace.h>
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#if defined(__AVR__)
|
||||
#include <util/delay.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
Adafruit_TSL2591::Adafruit_TSL2591(int32_t sensorID)
|
||||
{
|
||||
_initialized = false;
|
||||
_integration = TSL2591_INTEGRATIONTIME_100MS;
|
||||
_gain = TSL2591_GAIN_MED;
|
||||
_sensorID = sensorID;
|
||||
|
||||
// we cant do wire initialization till later, because we havent loaded Wire yet
|
||||
}
|
||||
|
||||
boolean Adafruit_TSL2591::begin(void)
|
||||
{
|
||||
Wire.begin();
|
||||
|
||||
/*
|
||||
for (uint8_t i=0; i<0x20; i++)
|
||||
{
|
||||
uint8_t id = read8(0x12);
|
||||
Serial.print("$"); Serial.print(i, HEX);
|
||||
Serial.print(" = 0x"); Serial.println(read8(i), HEX);
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t id = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID);
|
||||
if (id == 0x50 )
|
||||
{
|
||||
// Serial.println("Found Adafruit_TSL2591");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
|
||||
// Set default integration time and gain
|
||||
setTiming(_integration);
|
||||
setGain(_gain);
|
||||
|
||||
// Note: by default, the device is in power down mode on bootup
|
||||
disable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::enable(void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device by setting the control bit to 0x01
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN | TSL2591_ENABLE_AIEN | TSL2591_ENABLE_NPIEN);
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::disable(void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the device by setting the control bit to 0x00
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF);
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::setGain(tsl2591Gain_t gain)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
_gain = gain;
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain);
|
||||
disable();
|
||||
}
|
||||
|
||||
tsl2591Gain_t Adafruit_TSL2591::getGain()
|
||||
{
|
||||
return _gain;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::setTiming(tsl2591IntegrationTime_t integration)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
_integration = integration;
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain);
|
||||
disable();
|
||||
}
|
||||
|
||||
tsl2591IntegrationTime_t Adafruit_TSL2591::getTiming()
|
||||
{
|
||||
return _integration;
|
||||
}
|
||||
|
||||
float Adafruit_TSL2591::calculateLuxf(uint16_t ch0, uint16_t ch1)
|
||||
{
|
||||
float atime, again;
|
||||
float cpl, lux1, lux2, lux;
|
||||
uint32_t chan0, chan1;
|
||||
|
||||
// Check for overflow conditions first
|
||||
if ((ch0 == 0xFFFF) | (ch1 == 0xFFFF))
|
||||
{
|
||||
// Signal an overflow
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: This algorithm is based on preliminary coefficients
|
||||
// provided by AMS and may need to be updated in the future
|
||||
|
||||
switch (_integration)
|
||||
{
|
||||
case TSL2591_INTEGRATIONTIME_100MS :
|
||||
atime = 100.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_200MS :
|
||||
atime = 200.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_300MS :
|
||||
atime = 300.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_400MS :
|
||||
atime = 400.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_500MS :
|
||||
atime = 500.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_600MS :
|
||||
atime = 600.0F;
|
||||
break;
|
||||
default: // 100ms
|
||||
atime = 100.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW :
|
||||
again = 1.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_MED :
|
||||
again = 25.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH :
|
||||
again = 428.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_MAX :
|
||||
again = 9876.0F;
|
||||
break;
|
||||
default:
|
||||
again = 1.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
// cpl = (ATIME * AGAIN) / DF
|
||||
cpl = (atime * again) / TSL2591_LUX_DF;
|
||||
|
||||
lux1 = (((float) ch0 - (float) ch1)) * (1.0F - ((float) ch1 / (float) ch0)) / cpl;//( (float)ch0 - (TSL2591_LUX_COEFB * (float)ch1) ) / cpl;
|
||||
lux2 = ((TSL2591_LUX_COEFC * (float) ch0) - (TSL2591_LUX_COEFD * (float) ch1)) / cpl;
|
||||
lux = lux1 > lux2 ? lux1 : lux2;
|
||||
|
||||
// Alternate lux calculation
|
||||
//lux = ( (float)ch0 - ( 1.7F * (float)ch1 ) ) / cpl;
|
||||
|
||||
// Signal I2C had no errors
|
||||
return lux;
|
||||
}
|
||||
|
||||
uint32_t Adafruit_TSL2591::calculateLux(uint16_t ch0, uint16_t ch1)
|
||||
{
|
||||
return (uint32_t) calculateLuxf(ch0, ch1);
|
||||
}
|
||||
|
||||
uint32_t Adafruit_TSL2591::getFullLuminosity (void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device
|
||||
enable();
|
||||
|
||||
// Wait x ms for ADC to complete
|
||||
for (uint8_t d=0; d<=_integration; d++)
|
||||
{
|
||||
delay(120);
|
||||
}
|
||||
|
||||
uint32_t x;
|
||||
uint16_t y;
|
||||
y |= read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW);
|
||||
x = read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW);
|
||||
x <<= 16;
|
||||
x |= y;
|
||||
|
||||
disable();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Adafruit_TSL2591::getLuminosity (uint8_t channel)
|
||||
{
|
||||
uint32_t x = getFullLuminosity();
|
||||
|
||||
if (channel == TSL2591_FULLSPECTRUM)
|
||||
{
|
||||
// Reads two byte value from channel 0 (visible + infrared)
|
||||
return (x & 0xFFFF);
|
||||
}
|
||||
else if (channel == TSL2591_INFRARED)
|
||||
{
|
||||
// Reads two byte value from channel 1 (infrared)
|
||||
return (x >> 16);
|
||||
}
|
||||
else if (channel == TSL2591_VISIBLE)
|
||||
{
|
||||
// Reads all and subtracts out just the visible!
|
||||
return ( (x & 0xFFFF) - (x >> 16));
|
||||
}
|
||||
|
||||
// unknown channel!
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAILTL, lowerThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAILTH, lowerThreshold >> 8);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAIHTL, upperThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAIHTH, upperThreshold >> 8);
|
||||
disable();
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_PERSIST_FILTER, persist);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTL, lowerThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTH, lowerThreshold >> 8);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTL, upperThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTH, upperThreshold >> 8);
|
||||
disable();
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::clearInterrupt()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_CLEAR_INT);
|
||||
disable();
|
||||
}
|
||||
|
||||
|
||||
uint8_t Adafruit_TSL2591::getStatus()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device
|
||||
enable();
|
||||
uint8_t x;
|
||||
x = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_STATUS);
|
||||
disable();
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
uint8_t Adafruit_TSL2591::read8(uint8_t reg)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(TSL2591_ADDR, 1);
|
||||
#if ARDUINO >= 100
|
||||
x = Wire.read();
|
||||
#else
|
||||
x = Wire.receive();
|
||||
#endif
|
||||
// while (! Wire.available());
|
||||
// return Wire.read();
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Adafruit_TSL2591::read16(uint8_t reg)
|
||||
{
|
||||
uint16_t x;
|
||||
uint16_t t;
|
||||
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(TSL2591_ADDR, 2);
|
||||
#if ARDUINO >= 100
|
||||
t = Wire.read();
|
||||
x = Wire.read();
|
||||
#else
|
||||
t = Wire.receive();
|
||||
x = Wire.receive();
|
||||
#endif
|
||||
x <<= 8;
|
||||
x |= t;
|
||||
return x;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::write8 (uint8_t reg, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
Wire.send(value);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_TSL2591::write8 (uint8_t reg)
|
||||
{
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Gets the most recent sensor event
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool Adafruit_TSL2591::getEvent(sensors_event_t *event)
|
||||
{
|
||||
uint16_t ir, full;
|
||||
uint32_t lum = getFullLuminosity();
|
||||
/* Early silicon seems to have issues when there is a sudden jump in */
|
||||
/* light levels. :( To work around this for now sample the sensor 2x */
|
||||
lum = getFullLuminosity();
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
|
||||
/* Clear the event */
|
||||
memset(event, 0, sizeof(sensors_event_t));
|
||||
|
||||
event->version = sizeof(sensors_event_t);
|
||||
event->sensor_id = _sensorID;
|
||||
event->type = SENSOR_TYPE_LIGHT;
|
||||
event->timestamp = millis();
|
||||
|
||||
/* Calculate the actual lux value */
|
||||
/* 0 = sensor overflow (too much light) */
|
||||
event->light = calculateLux(full, ir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Gets the sensor_t data
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_TSL2591::getSensor(sensor_t *sensor)
|
||||
{
|
||||
/* Clear the sensor_t object */
|
||||
memset(sensor, 0, sizeof(sensor_t));
|
||||
|
||||
/* Insert the sensor name in the fixed length char array */
|
||||
strncpy (sensor->name, "TSL2591", sizeof(sensor->name) - 1);
|
||||
sensor->name[sizeof(sensor->name)- 1] = 0;
|
||||
sensor->version = 1;
|
||||
sensor->sensor_id = _sensorID;
|
||||
sensor->type = SENSOR_TYPE_LIGHT;
|
||||
sensor->min_delay = 0;
|
||||
sensor->max_value = 88000.0;
|
||||
sensor->min_value = 0.0;
|
||||
sensor->resolution = 1.0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_TSL2591.h
|
||||
@author KT0WN (adafruit.com)
|
||||
|
||||
This is a library for the Adafruit TSL2591 breakout board
|
||||
This library works with the Adafruit TSL2591 breakout
|
||||
----> https://www.adafruit.com/products/1980
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2014 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:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. 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.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''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 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.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef _TSL2591_H_
|
||||
#define _TSL2591_H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#define TSL2591_VISIBLE (2) // channel 0 - channel 1
|
||||
#define TSL2591_INFRARED (1) // channel 1
|
||||
#define TSL2591_FULLSPECTRUM (0) // channel 0
|
||||
|
||||
#define TSL2591_ADDR (0x29)
|
||||
#define TSL2591_READBIT (0x01)
|
||||
|
||||
#define TSL2591_COMMAND_BIT (0xA0) // 1010 0000: bits 7 and 5 for 'command normal'
|
||||
#define TSL2591_CLEAR_INT (0xE7)
|
||||
#define TSL2591_TEST_INT (0xE4)
|
||||
#define TSL2591_WORD_BIT (0x20) // 1 = read/write word (rather than byte)
|
||||
#define TSL2591_BLOCK_BIT (0x10) // 1 = using block read/write
|
||||
|
||||
#define TSL2591_ENABLE_POWEROFF (0x00)
|
||||
#define TSL2591_ENABLE_POWERON (0x01)
|
||||
#define TSL2591_ENABLE_AEN (0x02) // ALS Enable. This field activates ALS function. Writing a one activates the ALS. Writing a zero disables the ALS.
|
||||
#define TSL2591_ENABLE_AIEN (0x10) // ALS Interrupt Enable. When asserted permits ALS interrupts to be generated, subject to the persist filter.
|
||||
#define TSL2591_ENABLE_NPIEN (0x80) // No Persist Interrupt Enable. When asserted NP Threshold conditions will generate an interrupt, bypassing the persist filter
|
||||
|
||||
#define TSL2591_LUX_DF (408.0F)
|
||||
#define TSL2591_LUX_COEFB (1.64F) // CH0 coefficient
|
||||
#define TSL2591_LUX_COEFC (0.59F) // CH1 coefficient A
|
||||
#define TSL2591_LUX_COEFD (0.86F) // CH2 coefficient B
|
||||
|
||||
enum
|
||||
{
|
||||
TSL2591_REGISTER_ENABLE = 0x00,
|
||||
TSL2591_REGISTER_CONTROL = 0x01,
|
||||
TSL2591_REGISTER_THRESHOLD_AILTL = 0x04, // ALS low threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_AILTH = 0x05, // ALS low threshold upper byte
|
||||
TSL2591_REGISTER_THRESHOLD_AIHTL = 0x06, // ALS high threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_AIHTH = 0x07, // ALS high threshold upper byte
|
||||
TSL2591_REGISTER_THRESHOLD_NPAILTL = 0x08, // No Persist ALS low threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_NPAILTH = 0x09, // etc
|
||||
TSL2591_REGISTER_THRESHOLD_NPAIHTL = 0x0A,
|
||||
TSL2591_REGISTER_THRESHOLD_NPAIHTH = 0x0B,
|
||||
TSL2591_REGISTER_PERSIST_FILTER = 0x0C,
|
||||
TSL2591_REGISTER_PACKAGE_PID = 0x11,
|
||||
TSL2591_REGISTER_DEVICE_ID = 0x12,
|
||||
TSL2591_REGISTER_DEVICE_STATUS = 0x13,
|
||||
TSL2591_REGISTER_CHAN0_LOW = 0x14,
|
||||
TSL2591_REGISTER_CHAN0_HIGH = 0x15,
|
||||
TSL2591_REGISTER_CHAN1_LOW = 0x16,
|
||||
TSL2591_REGISTER_CHAN1_HIGH = 0x17
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSL2591_INTEGRATIONTIME_100MS = 0x00,
|
||||
TSL2591_INTEGRATIONTIME_200MS = 0x01,
|
||||
TSL2591_INTEGRATIONTIME_300MS = 0x02,
|
||||
TSL2591_INTEGRATIONTIME_400MS = 0x03,
|
||||
TSL2591_INTEGRATIONTIME_500MS = 0x04,
|
||||
TSL2591_INTEGRATIONTIME_600MS = 0x05,
|
||||
}
|
||||
tsl2591IntegrationTime_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// bit 7:4: 0
|
||||
TSL2591_PERSIST_EVERY = 0x00, // Every ALS cycle generates an interrupt
|
||||
TSL2591_PERSIST_ANY = 0x01, // Any value outside of threshold range
|
||||
TSL2591_PERSIST_2 = 0x02, // 2 consecutive values out of range
|
||||
TSL2591_PERSIST_3 = 0x03, // 3 consecutive values out of range
|
||||
TSL2591_PERSIST_5 = 0x04, // 5 consecutive values out of range
|
||||
TSL2591_PERSIST_10 = 0x05, // 10 consecutive values out of range
|
||||
TSL2591_PERSIST_15 = 0x06, // 15 consecutive values out of range
|
||||
TSL2591_PERSIST_20 = 0x07, // 20 consecutive values out of range
|
||||
TSL2591_PERSIST_25 = 0x08, // 25 consecutive values out of range
|
||||
TSL2591_PERSIST_30 = 0x09, // 30 consecutive values out of range
|
||||
TSL2591_PERSIST_35 = 0x0A, // 35 consecutive values out of range
|
||||
TSL2591_PERSIST_40 = 0x0B, // 40 consecutive values out of range
|
||||
TSL2591_PERSIST_45 = 0x0C, // 45 consecutive values out of range
|
||||
TSL2591_PERSIST_50 = 0x0D, // 50 consecutive values out of range
|
||||
TSL2591_PERSIST_55 = 0x0E, // 55 consecutive values out of range
|
||||
TSL2591_PERSIST_60 = 0x0F, // 60 consecutive values out of range
|
||||
}
|
||||
tsl2591Persist_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSL2591_GAIN_LOW = 0x00, // low gain (1x)
|
||||
TSL2591_GAIN_MED = 0x10, // medium gain (25x)
|
||||
TSL2591_GAIN_HIGH = 0x20, // medium gain (428x)
|
||||
TSL2591_GAIN_MAX = 0x30, // max gain (9876x)
|
||||
}
|
||||
tsl2591Gain_t;
|
||||
|
||||
class Adafruit_TSL2591 : public Adafruit_Sensor
|
||||
{
|
||||
public:
|
||||
Adafruit_TSL2591(int32_t sensorID = -1);
|
||||
|
||||
boolean begin ( void );
|
||||
void enable ( void );
|
||||
void disable ( void );
|
||||
void write8 ( uint8_t r);
|
||||
void write8 ( uint8_t r, uint8_t v );
|
||||
uint16_t read16 ( uint8_t reg );
|
||||
uint8_t read8 ( uint8_t reg );
|
||||
|
||||
uint32_t calculateLux ( uint16_t ch0, uint16_t ch1 );
|
||||
float calculateLuxf ( uint16_t ch0, uint16_t ch1 );
|
||||
void setGain ( tsl2591Gain_t gain );
|
||||
void setTiming ( tsl2591IntegrationTime_t integration );
|
||||
uint16_t getLuminosity (uint8_t channel );
|
||||
uint32_t getFullLuminosity ( );
|
||||
|
||||
tsl2591IntegrationTime_t getTiming();
|
||||
tsl2591Gain_t getGain();
|
||||
|
||||
// Interrupt
|
||||
void clearInterrupt(void);
|
||||
void registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold);
|
||||
void registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist);
|
||||
uint8_t getStatus();
|
||||
|
||||
/* Unified Sensor API Functions */
|
||||
bool getEvent ( sensors_event_t* );
|
||||
void getSensor ( sensor_t* );
|
||||
|
||||
private:
|
||||
tsl2591IntegrationTime_t _integration;
|
||||
tsl2591Gain_t _gain;
|
||||
int32_t _sensorID;
|
||||
|
||||
boolean _initialized;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
This is an Arduino library for the TSL2591 digital luminosity (light) sensors.
|
||||
|
||||
Pick one up at http://www.adafruit.com/products/1980
|
||||
|
||||
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_TSL2591. Check that the Adafruit_TSL2591 folder contains Adafruit_TSL2591.cpp and Adafruit_TSL2591.h
|
||||
|
||||
Place the Adafruit_TSL2591 library folder your <arduinosketchfolder>/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
|
||||
|
||||
You'll also need the Adafruit_Sensor library from https://github.com/adafruit/Adafruit_Sensor
|
||||
@@ -0,0 +1,200 @@
|
||||
/* TSL2591 Digital Light Sensor */
|
||||
/* Dynamic Range: 600M:1 */
|
||||
/* Maximum Lux: 88K */
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
// Example for demonstrating the TSL2591 library - public domain!
|
||||
|
||||
// connect SCL to analog 5
|
||||
// connect SDA to analog 4
|
||||
// connect Vin to 3.3-5V DC
|
||||
// connect GROUND to common ground
|
||||
|
||||
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Displays some basic information on this sensor from the unified
|
||||
sensor API sensor_t type (see Adafruit_Sensor for more information)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void displaySensorDetails(void)
|
||||
{
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.print (F("Sensor: ")); Serial.println(sensor.name);
|
||||
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
|
||||
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
|
||||
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F(" lux"));
|
||||
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F(" lux"));
|
||||
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F(" lux"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F(""));
|
||||
delay(500);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Configures the gain and integration time for the TSL2591
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void configureSensor(void)
|
||||
{
|
||||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
|
||||
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
|
||||
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
|
||||
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
|
||||
|
||||
// Changing the integration time gives you a longer time over which to sense light
|
||||
// longer timelines are slower, but are good in very low light situtations!
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
|
||||
|
||||
/* Display the gain and integration time for reference sake */
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.print (F("Gain: "));
|
||||
tsl2591Gain_t gain = tsl.getGain();
|
||||
switch(gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW:
|
||||
Serial.println(F("1x (Low)"));
|
||||
break;
|
||||
case TSL2591_GAIN_MED:
|
||||
Serial.println(F("25x (Medium)"));
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH:
|
||||
Serial.println(F("428x (High)"));
|
||||
break;
|
||||
case TSL2591_GAIN_MAX:
|
||||
Serial.println(F("9876x (Max)"));
|
||||
break;
|
||||
}
|
||||
Serial.print (F("Timing: "));
|
||||
Serial.print((tsl.getTiming() + 1) * 100, DEC);
|
||||
Serial.println(F(" ms"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F(""));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Program entry point for the Arduino sketch
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
Serial.println(F("Starting Adafruit TSL2591 Test!"));
|
||||
|
||||
if (tsl.begin())
|
||||
{
|
||||
Serial.println(F("Found a TSL2591 sensor"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No sensor found ... check your wiring?"));
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Display some basic information on this sensor */
|
||||
displaySensorDetails();
|
||||
|
||||
/* Configure the sensor */
|
||||
configureSensor();
|
||||
|
||||
// Now we're ready to get readings ... move on to loop()!
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Shows how to perform a basic read on visible, full spectrum or
|
||||
infrared light (returns raw 16-bit ADC values)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void simpleRead(void)
|
||||
{
|
||||
// Simple data read example. Just read the infrared, fullspecrtrum diode
|
||||
// or 'visible' (difference between the two) channels.
|
||||
// This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
|
||||
uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
|
||||
//uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
|
||||
//uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);
|
||||
|
||||
Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
|
||||
Serial.print(F("Luminosity: "));
|
||||
Serial.println(x, DEC);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Show how to read IR and Full Spectrum at once and convert to lux
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void advancedRead(void)
|
||||
{
|
||||
// More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
|
||||
// That way you can do whatever math and comparisons you want!
|
||||
uint32_t lum = tsl.getFullLuminosity();
|
||||
uint16_t ir, full;
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
|
||||
Serial.print(F("IR: ")); Serial.print(ir); Serial.print(F(" "));
|
||||
Serial.print(F("Full: ")); Serial.print(full); Serial.print(F(" "));
|
||||
Serial.print(F("Visible: ")); Serial.print(full - ir); Serial.print(F(" "));
|
||||
Serial.print(F("Lux: ")); Serial.println(tsl.calculateLux(full, ir));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Performs a read using the Adafruit Unified Sensor API.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void unifiedSensorAPIRead(void)
|
||||
{
|
||||
/* Get a new sensor event */
|
||||
sensors_event_t event;
|
||||
tsl.getEvent(&event);
|
||||
|
||||
/* Display the results (light is measured in lux) */
|
||||
Serial.print(F("[ ")); Serial.print(event.timestamp); Serial.print(F(" ms ] "));
|
||||
if ((event.light == 0) |
|
||||
(event.light > 4294966000.0) |
|
||||
(event.light <-4294966000.0))
|
||||
{
|
||||
/* If event.light = 0 lux the sensor is probably saturated */
|
||||
/* and no reliable data could be generated! */
|
||||
/* if event.light is +/- 4294967040 there was a float over/underflow */
|
||||
Serial.println(F("Invalid data (adjust gain or timing)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(event.light); Serial.println(F(" lux"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Arduino loop function, called once 'setup' is complete (your own code
|
||||
should go here)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void loop(void)
|
||||
{
|
||||
//simpleRead();
|
||||
advancedRead();
|
||||
// unifiedSensorAPIRead();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/* TSL2591 Digital Light Sensor, example with (simple) interrupt support */
|
||||
/* Dynamic Range: 600M:1 */
|
||||
/* Maximum Lux: 88K */
|
||||
|
||||
/* This example shows how the interrupt system on the TLS2591
|
||||
* can be used to detect a meaningful change in light levels.
|
||||
*
|
||||
* Two thresholds can be set:
|
||||
*
|
||||
* Lower Threshold - Any light sample on CHAN0 below this value
|
||||
* will trigger an interrupt
|
||||
* Upper Threshold - Any light sample on CHAN0 above this value
|
||||
* will trigger an interrupt
|
||||
*
|
||||
* If CHAN0 (full light) crosses below the low threshold specified,
|
||||
* or above the higher threshold, an interrupt is asserted on the interrupt
|
||||
* pin. The use of the HW pin is optional, though, since the change can
|
||||
* also be detected in software by looking at the status byte via
|
||||
* tsl.getStatus().
|
||||
*
|
||||
* An optional third parameter can be used in the .registerInterrupt
|
||||
* function to indicate the number of samples that must stay outside
|
||||
* the threshold window before the interrupt fires, providing some basic
|
||||
* debouncing of light level data.
|
||||
*
|
||||
* For example, the following code will fire an interrupt on any and every
|
||||
* sample outside the window threshold (meaning a sample below 100 or above
|
||||
* 1500 on CHAN0 or FULL light):
|
||||
*
|
||||
* tsl.registerInterrupt(100, 1500, TSL2591_PERSIST_ANY);
|
||||
*
|
||||
* This code would require five consecutive changes before the interrupt
|
||||
* fires though (see tls2591Persist_t in Adafruit_TLS2591.h for possible
|
||||
* values):
|
||||
*
|
||||
* tsl.registerInterrupt(100, 1500, TSL2591_PERSIST_5);
|
||||
*/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
// Example for demonstrating the TSL2591 library - public domain!
|
||||
|
||||
// connect SCL to analog 5
|
||||
// connect SDA to analog 4
|
||||
// connect Vin to 3.3-5V DC
|
||||
// connect GROUND to common ground
|
||||
|
||||
// Interrupt thresholds and persistance
|
||||
#define TLS2591_INT_THRESHOLD_LOWER (100)
|
||||
#define TLS2591_INT_THRESHOLD_UPPER (1500)
|
||||
//#define TLS2591_INT_PERSIST (TSL2591_PERSIST_ANY) // Fire on any valid change
|
||||
#define TLS2591_INT_PERSIST (TSL2591_PERSIST_60) // Require at least 60 samples to fire
|
||||
|
||||
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Displays some basic information on this sensor from the unified
|
||||
sensor API sensor_t type (see Adafruit_Sensor for more information)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void displaySensorDetails(void)
|
||||
{
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Sensor: "); Serial.println(sensor.name);
|
||||
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
|
||||
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
|
||||
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
|
||||
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
|
||||
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Configures the gain and integration time for the TSL2591
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void configureSensor(void)
|
||||
{
|
||||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
|
||||
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
|
||||
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
|
||||
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
|
||||
|
||||
// Changing the integration time gives you a longer time over which to sense light
|
||||
// longer timelines are slower, but are good in very low light situtations!
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
|
||||
|
||||
/* Display the gain and integration time for reference sake */
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Gain: ");
|
||||
tsl2591Gain_t gain = tsl.getGain();
|
||||
switch (gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW:
|
||||
Serial.println("1x (Low)");
|
||||
break;
|
||||
case TSL2591_GAIN_MED:
|
||||
Serial.println("25x (Medium)");
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH:
|
||||
Serial.println("428x (High)");
|
||||
break;
|
||||
case TSL2591_GAIN_MAX:
|
||||
Serial.println("9876x (Max)");
|
||||
break;
|
||||
}
|
||||
Serial.print ("Timing: ");
|
||||
Serial.print((tsl.getTiming() + 1) * 100, DEC);
|
||||
Serial.println(" ms");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
|
||||
/* Setup the SW interrupt to trigger between 100 and 1500 lux */
|
||||
/* Threshold values are defined at the top of this sketch */
|
||||
tsl.clearInterrupt();
|
||||
tsl.registerInterrupt(TLS2591_INT_THRESHOLD_LOWER,
|
||||
TLS2591_INT_THRESHOLD_UPPER,
|
||||
TLS2591_INT_PERSIST);
|
||||
|
||||
/* Display the interrupt threshold window */
|
||||
Serial.print("Interrupt Threshold Window: -");
|
||||
Serial.print(TLS2591_INT_THRESHOLD_LOWER, DEC);
|
||||
Serial.print(" to +");
|
||||
Serial.println(TLS2591_INT_THRESHOLD_LOWER, DEC);
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Program entry point for the Arduino sketch
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
// Enable this line for Flora, Zero and Feather boards with no FTDI chip
|
||||
// Waits for the serial port to connect before sending data out
|
||||
// while (!Serial) { delay(1); }
|
||||
|
||||
Serial.println("Starting Adafruit TSL2591 interrupt Test!");
|
||||
|
||||
if (tsl.begin())
|
||||
{
|
||||
Serial.println("Found a TSL2591 sensor");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("No sensor found ... check your wiring?");
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Display some basic information on this sensor */
|
||||
displaySensorDetails();
|
||||
|
||||
/* Configure the sensor (including the interrupt threshold) */
|
||||
configureSensor();
|
||||
|
||||
// Now we're ready to get readings ... move on to loop()!
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Show how to read IR and Full Spectrum at once and convert to lux
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void advancedRead(void)
|
||||
{
|
||||
// More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
|
||||
// That way you can do whatever math and comparisons you want!
|
||||
uint32_t lum = tsl.getFullLuminosity();
|
||||
uint16_t ir, full;
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.print("IR: "); Serial.print(ir); Serial.print(" ");
|
||||
Serial.print("Full: "); Serial.print(full); Serial.print(" ");
|
||||
Serial.print("Visible: "); Serial.print(full - ir); Serial.print(" ");
|
||||
Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir));
|
||||
}
|
||||
|
||||
|
||||
void getStatus(void)
|
||||
{
|
||||
uint8_t x = tsl.getStatus();
|
||||
// bit 4: ALS Interrupt occured
|
||||
// bit 5: No-persist Interrupt occurence
|
||||
if (x & 0x10) {
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.println("ALS Interrupt occured");
|
||||
}
|
||||
if (x & 0x20) {
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.println("No-persist Interrupt occured");
|
||||
}
|
||||
|
||||
// Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.print("Status: ");
|
||||
Serial.println(x, BIN);
|
||||
tsl.clearInterrupt();
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Arduino loop function, called once 'setup' is complete (your own code
|
||||
should go here)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void loop(void)
|
||||
{
|
||||
advancedRead();
|
||||
getStatus();
|
||||
delay(500);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit TSL2591 Library
|
||||
version=1.0.2
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Library for the TSL2591 digital luminosity (light) sensors.
|
||||
paragraph=Library for the TSL2591 digital luminosity (light) sensors.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_TSL2591_Library
|
||||
architectures=*
|
||||
@@ -0,0 +1,174 @@
|
||||
#include "HT16K33.h"
|
||||
#include <Wire.h>
|
||||
|
||||
CHT16K33::CHT16K33(void)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CHT16K33::Init(uint8_t addr)
|
||||
{
|
||||
_addr = addr;
|
||||
|
||||
// System Setup Register
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(0x21); // oscillator on
|
||||
Wire.endTransmission();
|
||||
|
||||
// Display Setup Register
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(0x81); // blink off; display on
|
||||
Wire.endTransmission();
|
||||
|
||||
SetBrightness(15);
|
||||
ClearRowBuffer();
|
||||
TransmitRowBuffer();
|
||||
};
|
||||
|
||||
void CHT16K33::SetBrightness(uint8_t b)
|
||||
{
|
||||
if (b > 15)
|
||||
b = 15;
|
||||
// Digital Dimming Data Input
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(0xE0 | b); // brightness
|
||||
Wire.endTransmission();
|
||||
};
|
||||
|
||||
void CHT16K33::TransmitRowBuffer(void)
|
||||
{
|
||||
// Display Memory
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(0); // start data at address 0
|
||||
for (byte i=0; i<8; i++)
|
||||
{
|
||||
Wire.write(_rowBuffer[i] & 0xFF);
|
||||
Wire.write(_rowBuffer[i] >> 8);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
};
|
||||
|
||||
void CHT16K33::ClearRowBuffer(void)
|
||||
{
|
||||
for (byte i=0; i<8; i++)
|
||||
_rowBuffer[i] = 0;
|
||||
};
|
||||
|
||||
void CHT16K33::SetRow(uint8_t com, uint16_t data)
|
||||
{
|
||||
if (com < 8)
|
||||
_rowBuffer[com] = data;
|
||||
};
|
||||
|
||||
uint16_t CHT16K33::GetRow(uint8_t com)
|
||||
{
|
||||
if (com < 8)
|
||||
return _rowBuffer[com];
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
|
||||
void CHT16K33::SetDigit(uint8_t com, uint8_t c)
|
||||
{
|
||||
uint16_t value = 0;
|
||||
|
||||
if (c <= 0xF)
|
||||
value = _digits[c];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
value = c + 10 - 'A';
|
||||
value = _digits[value & 0xF];
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
value = c - '0';
|
||||
value = _digits[value & 0xF];
|
||||
break;
|
||||
case ' ':
|
||||
value = 0;
|
||||
break;
|
||||
case ':':
|
||||
value = 0x02; //special for China 4 x 7-seg big display
|
||||
break;
|
||||
case '-':
|
||||
value = 0x40;
|
||||
break;
|
||||
}
|
||||
|
||||
SetRow(com, value);
|
||||
}
|
||||
|
||||
uint8_t CHT16K33::ReadKeys(void)
|
||||
{
|
||||
// Display Memory
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(0x40); // start data at address 0x40
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(_addr, (uint8_t)6);
|
||||
if (Wire.available() == 6)
|
||||
{
|
||||
for (byte i=0; i<3; i++)
|
||||
{
|
||||
_keyBuffer[i] = Wire.read() | (Wire.read() << 8);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
for (byte i=0; i<3; i++)
|
||||
{
|
||||
byte mask = 1;
|
||||
for (byte k=0; k<12; k++)
|
||||
{
|
||||
if (_keyBuffer[i] & mask)
|
||||
{
|
||||
_keydown = 16*(i+1) + (k+1);
|
||||
return _keydown;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
_keydown = 0;
|
||||
return _keydown;
|
||||
};
|
||||
|
||||
const uint8_t CHT16K33::_digits[16] =
|
||||
{
|
||||
0x3F, // 0
|
||||
0x06, // 1
|
||||
0x5B, // 2
|
||||
0x4F, // 3
|
||||
0x66, // 4
|
||||
0x6D, // 5
|
||||
0x7D, // 6
|
||||
0x07, // 7
|
||||
0x7F, // 8
|
||||
0x6F, // 9
|
||||
0x77, // A
|
||||
0x7C, // B
|
||||
0x39, // C
|
||||
0x5E, // D
|
||||
0x79, // E
|
||||
0x71, // F
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef CHT16K33_h
|
||||
#define CHT16K33_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class CHT16K33 {
|
||||
public:
|
||||
CHT16K33(void);
|
||||
|
||||
void Init(uint8_t addr);
|
||||
|
||||
// LED buffer
|
||||
void ClearRowBuffer(void);
|
||||
void SetRow(uint8_t com, uint16_t data);
|
||||
uint16_t GetRow(uint8_t com);
|
||||
void SetDigit(uint8_t com, uint8_t c);
|
||||
|
||||
// LED output and control
|
||||
void SetBrightness(uint8_t b);
|
||||
void TransmitRowBuffer(void);
|
||||
|
||||
//KeyPad Scan
|
||||
uint8_t ReadKeys(void);
|
||||
|
||||
protected:
|
||||
uint8_t _addr;
|
||||
uint16_t _rowBuffer[8];
|
||||
uint16_t _keyBuffer[3];
|
||||
byte _keydown;
|
||||
|
||||
static const uint8_t _digits[16];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
name=CHT16K33 LED Matrix Library
|
||||
version=0.0.1
|
||||
author=Jochen Krapf
|
||||
maintainer=Jochen Krapf <jk@nerd2nerd.org>
|
||||
sentence=CHT16K33 16x8 LED and 13x3 KeyPad Matrix Library
|
||||
paragraph=CHT16K33 16x8 LED and 13x3 KeyPad Matrix Library
|
||||
category=LED
|
||||
url=https://github.com/???
|
||||
architectures=esp8266,avr
|
||||
@@ -1,13 +1,14 @@
|
||||
language: c
|
||||
env:
|
||||
- BD=esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M
|
||||
- BD=esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M3M
|
||||
before_install:
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.1-linux64.tar.xz
|
||||
- tar xf arduino-1.8.1-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.1 /usr/local/share/arduino
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.2-linux64.tar.xz
|
||||
- tar xf arduino-1.8.2-linux64.tar.xz
|
||||
- sudo mv arduino-1.8.2 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
install:
|
||||
- ln -s $PWD /usr/local/share/arduino/libraries/
|
||||
@@ -25,7 +26,7 @@ script:
|
||||
- arduino --verify --board $BD $PWD/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino
|
||||
- arduino --verify --board $BD $PWD/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino
|
||||
- arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino
|
||||
- arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnMitsubishiAC.ino
|
||||
- arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
@@ -9,17 +9,17 @@ IRDaikinESP::IRDaikinESP(int pin) : _irsend(pin)
|
||||
{
|
||||
}
|
||||
|
||||
void IRDaikinESP::begin()
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::begin()
|
||||
{
|
||||
_irsend.begin();
|
||||
}
|
||||
|
||||
void IRDaikinESP::send()
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::send()
|
||||
{
|
||||
_irsend.sendDaikin(daikin);
|
||||
}
|
||||
|
||||
void IRDaikinESP::checksum()
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::checksum()
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
uint8_t i;
|
||||
@@ -36,39 +36,39 @@ void IRDaikinESP::checksum()
|
||||
daikin[26] = sum &0xFF;
|
||||
}
|
||||
|
||||
void IRDaikinESP::on()
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::on()
|
||||
{
|
||||
//state = ON;
|
||||
daikin[13] |= 0x01;
|
||||
checksum();
|
||||
}
|
||||
|
||||
void IRDaikinESP::off()
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::off()
|
||||
{
|
||||
//state = OFF;
|
||||
daikin[13] &= 0xFE;
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getPower()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getPower()
|
||||
{
|
||||
return (daikin[13])&0x01;
|
||||
}
|
||||
|
||||
// DAIKIN_SILENT or DAIKIN_POWERFUL
|
||||
void IRDaikinESP::setAux(uint8_t aux)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setAux(uint8_t aux)
|
||||
{
|
||||
daikin[21] = aux;
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getAux(){
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getAux(){
|
||||
return daikin[21];
|
||||
}
|
||||
|
||||
|
||||
// Set the temp in deg C
|
||||
void IRDaikinESP::setTemp(uint8_t temp)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setTemp(uint8_t temp)
|
||||
{
|
||||
if (temp < 18)
|
||||
temp = 18;
|
||||
@@ -78,13 +78,13 @@ void IRDaikinESP::setTemp(uint8_t temp)
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getTemp()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getTemp()
|
||||
{
|
||||
return (daikin[14])/2;
|
||||
}
|
||||
|
||||
// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed
|
||||
void IRDaikinESP::setFan(uint8_t fan)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setFan(uint8_t fan)
|
||||
{
|
||||
// Set the fan speed bits, leave low 4 bits alone
|
||||
uint8_t fanset;
|
||||
@@ -97,7 +97,7 @@ void IRDaikinESP::setFan(uint8_t fan)
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getFan()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getFan()
|
||||
{
|
||||
uint8_t fan = daikin[16] >> 4;
|
||||
fan = fan - 2;
|
||||
@@ -106,7 +106,7 @@ uint8_t IRDaikinESP::getFan()
|
||||
return fan;
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getMode()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getMode()
|
||||
{/*
|
||||
DAIKIN_COOL
|
||||
DAIKIN_HEAT
|
||||
@@ -117,13 +117,13 @@ uint8_t IRDaikinESP::getMode()
|
||||
return (daikin[13])>>4;
|
||||
}
|
||||
|
||||
void IRDaikinESP::setMode(uint8_t mode)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setMode(uint8_t mode)
|
||||
{
|
||||
daikin[13]=mode<<4 | getPower();
|
||||
checksum();
|
||||
}
|
||||
|
||||
void IRDaikinESP::setSwingVertical(uint8_t swing)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setSwingVertical(uint8_t swing)
|
||||
{
|
||||
if (swing)
|
||||
daikin[16] = daikin[16] | 0x0F;
|
||||
@@ -132,12 +132,12 @@ void IRDaikinESP::setSwingVertical(uint8_t swing)
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getSwingVertical()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getSwingVertical()
|
||||
{
|
||||
return (daikin[16])&0x01;
|
||||
}
|
||||
|
||||
void IRDaikinESP::setSwingHorizontal(uint8_t swing)
|
||||
void ICACHE_FLASH_ATTR IRDaikinESP::setSwingHorizontal(uint8_t swing)
|
||||
{
|
||||
if (swing)
|
||||
daikin[17] = daikin[17] | 0x0F;
|
||||
@@ -146,7 +146,7 @@ void IRDaikinESP::setSwingHorizontal(uint8_t swing)
|
||||
checksum();
|
||||
}
|
||||
|
||||
uint8_t IRDaikinESP::getSwingHorizontal()
|
||||
uint8_t ICACHE_FLASH_ATTR IRDaikinESP::getSwingHorizontal()
|
||||
{
|
||||
return (daikin[17])&0x01;
|
||||
}
|
||||
|
||||
@@ -20,36 +20,36 @@ IRKelvinatorAC::IRKelvinatorAC(int pin) : _irsend(pin) {
|
||||
stateReset();
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::stateReset() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::stateReset() {
|
||||
for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++)
|
||||
remote_state[i] = 0x0;
|
||||
remote_state[3] = 0x50;
|
||||
remote_state[11] = 0x70;
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::begin() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::begin() {
|
||||
_irsend.begin();
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::fixup() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::fixup() {
|
||||
// X-Fan mode is only valid in COOL or DRY modes.
|
||||
if (getMode() != KELVINATOR_COOL && getMode() != KELVINATOR_DRY)
|
||||
setXFan(false);
|
||||
checksum(); // Calculate the checksums
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::send() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::send() {
|
||||
fixup(); // Ensure correct settings before sending.
|
||||
_irsend.sendKelvinator(remote_state);
|
||||
}
|
||||
|
||||
uint8_t* IRKelvinatorAC::getRaw() {
|
||||
uint8_t* ICACHE_FLASH_ATTR IRKelvinatorAC::getRaw() {
|
||||
fixup(); // Ensure correct settings before sending.
|
||||
return remote_state;
|
||||
}
|
||||
|
||||
// Many Bothans died to bring us this information.
|
||||
void IRKelvinatorAC::checksum() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::checksum() {
|
||||
// For each command + options block.
|
||||
for (uint8_t offset = 0; offset < KELVINATOR_STATE_LENGTH; offset += 8) {
|
||||
uint8_t sum = KELVINATOR_CHECKSUM_START;
|
||||
@@ -68,31 +68,31 @@ void IRKelvinatorAC::checksum() {
|
||||
}
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::on() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::on() {
|
||||
//state = ON;
|
||||
remote_state[0] |= KELVINATOR_POWER;
|
||||
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::off() {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::off() {
|
||||
//state = OFF;
|
||||
remote_state[0] &= ~KELVINATOR_POWER;
|
||||
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setPower(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setPower(bool state) {
|
||||
if (state)
|
||||
on();
|
||||
else
|
||||
off();
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getPower() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getPower() {
|
||||
return ((remote_state[0] & KELVINATOR_POWER) != 0);
|
||||
}
|
||||
|
||||
// Set the temp. in deg C
|
||||
void IRKelvinatorAC::setTemp(uint8_t temp) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setTemp(uint8_t temp) {
|
||||
temp = max(KELVINATOR_MIN_TEMP, temp);
|
||||
temp = min(KELVINATOR_MAX_TEMP, temp);
|
||||
remote_state[1] = (remote_state[1] & 0xF0U) | (temp - KELVINATOR_MIN_TEMP);
|
||||
@@ -100,12 +100,12 @@ void IRKelvinatorAC::setTemp(uint8_t temp) {
|
||||
}
|
||||
|
||||
// Return the set temp. in deg C
|
||||
uint8_t IRKelvinatorAC::getTemp() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRKelvinatorAC::getTemp() {
|
||||
return ((remote_state[1] & 0xFU) + KELVINATOR_MIN_TEMP);
|
||||
}
|
||||
|
||||
// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed
|
||||
void IRKelvinatorAC::setFan(uint8_t fan) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setFan(uint8_t fan) {
|
||||
fan = min(KELVINATOR_FAN_MAX, fan); // Bounds check
|
||||
|
||||
// Only change things if we need to.
|
||||
@@ -122,11 +122,11 @@ void IRKelvinatorAC::setFan(uint8_t fan) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t IRKelvinatorAC::getFan() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRKelvinatorAC::getFan() {
|
||||
return ((remote_state[14] & ~KELVINATOR_FAN_MASK) >> KELVINATOR_FAN_OFFSET);
|
||||
}
|
||||
|
||||
uint8_t IRKelvinatorAC::getMode() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRKelvinatorAC::getMode() {
|
||||
/*
|
||||
KELVINATOR_AUTO
|
||||
KELVINATOR_COOL
|
||||
@@ -137,7 +137,7 @@ uint8_t IRKelvinatorAC::getMode() {
|
||||
return (remote_state[0] & ~KELVINATOR_MODE_MASK);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setMode(uint8_t mode) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setMode(uint8_t mode) {
|
||||
// If we get an unexpected mode, default to AUTO.
|
||||
if (mode > KELVINATOR_HEAT) mode = KELVINATOR_AUTO;
|
||||
remote_state[0] = (remote_state[0] & KELVINATOR_MODE_MASK) | mode;
|
||||
@@ -147,7 +147,7 @@ void IRKelvinatorAC::setMode(uint8_t mode) {
|
||||
setTemp(KELVINATOR_AUTO_TEMP);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setSwingVertical(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setSwingVertical(bool state) {
|
||||
if (state) {
|
||||
remote_state[0] |= KELVINATOR_VENT_SWING;
|
||||
remote_state[4] |= KELVINATOR_VENT_SWING_V;
|
||||
@@ -160,11 +160,11 @@ void IRKelvinatorAC::setSwingVertical(bool state) {
|
||||
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getSwingVertical() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getSwingVertical() {
|
||||
return ((remote_state[4] & KELVINATOR_VENT_SWING_V) != 0);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setSwingHorizontal(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setSwingHorizontal(bool state) {
|
||||
if (state) {
|
||||
remote_state[0] |= KELVINATOR_VENT_SWING;
|
||||
remote_state[4] |= KELVINATOR_VENT_SWING_H;
|
||||
@@ -177,57 +177,57 @@ void IRKelvinatorAC::setSwingHorizontal(bool state) {
|
||||
remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getSwingHorizontal() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getSwingHorizontal() {
|
||||
return ((remote_state[4] & KELVINATOR_VENT_SWING_H) != 0);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setQuiet(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setQuiet(bool state) {
|
||||
remote_state[12] &= ~KELVINATOR_QUIET;
|
||||
remote_state[12] |= (state << KELVINATOR_QUIET_OFFSET);
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getQuiet() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getQuiet() {
|
||||
return ((remote_state[12] & KELVINATOR_QUIET) != 0);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setIonFilter(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setIonFilter(bool state) {
|
||||
remote_state[2] &= ~KELVINATOR_ION_FILTER;
|
||||
remote_state[2] |= (state << KELVINATOR_ION_FILTER_OFFSET);
|
||||
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getIonFilter() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getIonFilter() {
|
||||
return ((remote_state[2] & KELVINATOR_ION_FILTER) != 0);
|
||||
}
|
||||
|
||||
void IRKelvinatorAC::setLight(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setLight(bool state) {
|
||||
remote_state[2] &= ~KELVINATOR_LIGHT;
|
||||
remote_state[2] |= (state << KELVINATOR_LIGHT_OFFSET);
|
||||
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getLight() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getLight() {
|
||||
return ((remote_state[2] & KELVINATOR_LIGHT) != 0);
|
||||
}
|
||||
|
||||
// Note: XFan mode is only valid in Cool or Dry mode.
|
||||
void IRKelvinatorAC::setXFan(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setXFan(bool state) {
|
||||
remote_state[2] &= ~KELVINATOR_XFAN;
|
||||
remote_state[2] |= (state << KELVINATOR_XFAN_OFFSET);
|
||||
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getXFan() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getXFan() {
|
||||
return ((remote_state[2] & KELVINATOR_XFAN) != 0);
|
||||
}
|
||||
|
||||
// Note: Turbo mode is turned off if the fan speed is changed.
|
||||
void IRKelvinatorAC::setTurbo(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRKelvinatorAC::setTurbo(bool state) {
|
||||
remote_state[2] &= ~KELVINATOR_TURBO;
|
||||
remote_state[2] |= (state << KELVINATOR_TURBO_OFFSET);
|
||||
remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk.
|
||||
}
|
||||
|
||||
bool IRKelvinatorAC::getTurbo() {
|
||||
bool ICACHE_FLASH_ATTR IRKelvinatorAC::getTurbo() {
|
||||
return ((remote_state[2] & KELVINATOR_TURBO) != 0);
|
||||
}
|
||||
|
||||
@@ -17,31 +17,31 @@ IRMitsubishiAC::IRMitsubishiAC(int pin) : _irsend(pin) {
|
||||
}
|
||||
|
||||
// Reset the state of the remote to a known good state/sequence.
|
||||
void IRMitsubishiAC::stateReset() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::stateReset() {
|
||||
for (uint8_t i = 0; i < MITSUBISHI_AC_STATE_LENGTH; i++)
|
||||
remote_state[i] = known_good_state[i];
|
||||
checksum(); // Calculate the checksum
|
||||
}
|
||||
|
||||
// Configure the pin for output.
|
||||
void IRMitsubishiAC::begin() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::begin() {
|
||||
_irsend.begin();
|
||||
}
|
||||
|
||||
// Send the current desired state to the IR LED.
|
||||
void IRMitsubishiAC::send() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::send() {
|
||||
checksum(); // Ensure correct checksum before sending.
|
||||
_irsend.sendMitsubishiAC(remote_state);
|
||||
}
|
||||
|
||||
// Return a pointer to the internal state date of the remote.
|
||||
uint8_t* IRMitsubishiAC::getRaw() {
|
||||
uint8_t* ICACHE_FLASH_ATTR IRMitsubishiAC::getRaw() {
|
||||
checksum();
|
||||
return remote_state;
|
||||
}
|
||||
|
||||
// Calculate the checksum for the current internal state of the remote.
|
||||
void IRMitsubishiAC::checksum() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::checksum() {
|
||||
uint8_t sum = 0;
|
||||
// Checksum is simple addition of all previous bytes stored
|
||||
// as a 8 bit value.
|
||||
@@ -51,19 +51,19 @@ void IRMitsubishiAC::checksum() {
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C to off.
|
||||
void IRMitsubishiAC::on() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::on() {
|
||||
//state = ON;
|
||||
remote_state[5] |= MITSUBISHI_AC_POWER;
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C to off.
|
||||
void IRMitsubishiAC::off() {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::off() {
|
||||
//state = OFF;
|
||||
remote_state[5] &= ~MITSUBISHI_AC_POWER;
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C.
|
||||
void IRMitsubishiAC::setPower(bool state) {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::setPower(bool state) {
|
||||
if (state)
|
||||
on();
|
||||
else
|
||||
@@ -71,25 +71,25 @@ void IRMitsubishiAC::setPower(bool state) {
|
||||
}
|
||||
|
||||
// Return the requested power state of the A/C.
|
||||
bool IRMitsubishiAC::getPower() {
|
||||
bool ICACHE_FLASH_ATTR IRMitsubishiAC::getPower() {
|
||||
return((remote_state[5] & MITSUBISHI_AC_POWER) != 0);
|
||||
}
|
||||
|
||||
// Set the temp. in deg C
|
||||
void IRMitsubishiAC::setTemp(uint8_t temp) {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::setTemp(uint8_t temp) {
|
||||
temp = max(MITSUBISHI_AC_MIN_TEMP, temp);
|
||||
temp = min(MITSUBISHI_AC_MAX_TEMP, temp);
|
||||
remote_state[7] = temp - MITSUBISHI_AC_MIN_TEMP;
|
||||
}
|
||||
|
||||
// Return the set temp. in deg C
|
||||
uint8_t IRMitsubishiAC::getTemp() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRMitsubishiAC::getTemp() {
|
||||
return(remote_state[7] + MITSUBISHI_AC_MIN_TEMP);
|
||||
}
|
||||
|
||||
// Set the speed of the fan, 0-6.
|
||||
// 0 is auto, 1-5 is the speed, 6 is silent.
|
||||
void IRMitsubishiAC::setFan(uint8_t fan) {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::setFan(uint8_t fan) {
|
||||
// Bounds check
|
||||
if (fan > MITSUBISHI_AC_FAN_SILENT)
|
||||
fan = MITSUBISHI_AC_FAN_MAX; // Set the fan to maximum if out of range.
|
||||
@@ -103,7 +103,7 @@ void IRMitsubishiAC::setFan(uint8_t fan) {
|
||||
}
|
||||
|
||||
// Return the requested state of the unit's fan.
|
||||
uint8_t IRMitsubishiAC::getFan() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRMitsubishiAC::getFan() {
|
||||
uint8_t fan = remote_state[9] & B111;
|
||||
if (fan == MITSUBISHI_AC_FAN_MAX)
|
||||
return MITSUBISHI_AC_FAN_SILENT;
|
||||
@@ -111,7 +111,7 @@ uint8_t IRMitsubishiAC::getFan() {
|
||||
}
|
||||
|
||||
// Return the requested climate operation mode of the a/c unit.
|
||||
uint8_t IRMitsubishiAC::getMode() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRMitsubishiAC::getMode() {
|
||||
/*
|
||||
MITSUBISHI_AC_AUTO
|
||||
MITSUBISHI_AC_COOL
|
||||
@@ -122,7 +122,7 @@ uint8_t IRMitsubishiAC::getMode() {
|
||||
}
|
||||
|
||||
// Set the requested climate operation mode of the a/c unit.
|
||||
void IRMitsubishiAC::setMode(uint8_t mode) {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::setMode(uint8_t mode) {
|
||||
// If we get an unexpected mode, default to AUTO.
|
||||
switch (mode) {
|
||||
case MITSUBISHI_AC_AUTO: break;
|
||||
@@ -135,7 +135,7 @@ void IRMitsubishiAC::setMode(uint8_t mode) {
|
||||
}
|
||||
|
||||
// Set the requested vane operation mode of the a/c unit.
|
||||
void IRMitsubishiAC::setVane(uint8_t mode) {
|
||||
void ICACHE_FLASH_ATTR IRMitsubishiAC::setVane(uint8_t mode) {
|
||||
mode = max(mode, B111); // bounds check
|
||||
mode |= B1000;
|
||||
mode <<= 3;
|
||||
@@ -143,6 +143,6 @@ void IRMitsubishiAC::setVane(uint8_t mode) {
|
||||
}
|
||||
|
||||
// Return the requested vane operation mode of the a/c unit.
|
||||
uint8_t IRMitsubishiAC::getVane() {
|
||||
uint8_t ICACHE_FLASH_ATTR IRMitsubishiAC::getVane() {
|
||||
return ((remote_state[9] & B00111000) >> 3);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@
|
||||
#define IRremote_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "IRremoteInt.h"
|
||||
|
||||
// The following are compile-time library options.
|
||||
// If you change them, recompile the library.
|
||||
@@ -68,7 +69,8 @@ enum decode_type_t {
|
||||
DENON,
|
||||
KELVINATOR,
|
||||
SHERWOOD,
|
||||
MITSUBISHI_AC
|
||||
MITSUBISHI_AC,
|
||||
RCMM
|
||||
};
|
||||
|
||||
// Results returned from the decoder
|
||||
@@ -89,30 +91,33 @@ public:
|
||||
// Decoded value for NEC when a repeat code is received
|
||||
#define REPEAT 0xffffffff
|
||||
|
||||
#define SEND_PROTOCOL_NEC case NEC: sendNEC(data, nbits); break;
|
||||
#define SEND_PROTOCOL_SONY case SONY: sendSony(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC5 case RC5: sendRC5(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC6 case RC6: sendRC6(data, nbits); break;
|
||||
#define SEND_PROTOCOL_DISH case DISH: sendDISH(data, nbits); break;
|
||||
#define SEND_PROTOCOL_JVC case JVC: sendJVC(data, nbits, 0); break;
|
||||
#define SEND_PROTOCOL_SAMSUNG case SAMSUNG: sendSAMSUNG(data, nbits); break;
|
||||
#define SEND_PROTOCOL_LG case LG: sendLG(data, nbits); break;
|
||||
#define SEND_PROTOCOL_WHYNTER case WHYNTER: sendWhynter(data, nbits); break;
|
||||
#define SEND_PROTOCOL_COOLIX case COOLIX: sendCOOLIX(data, nbits); break;
|
||||
#define SEND_PROTOCOL_DENON case DENON: sendDenon(data, nbits); break;
|
||||
#define SEND_PROTOCOL_NEC case NEC: sendNEC(data, nbits); break;
|
||||
#define SEND_PROTOCOL_SONY case SONY: sendSony(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC5 case RC5: sendRC5(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC6 case RC6: sendRC6(data, nbits); break;
|
||||
#define SEND_PROTOCOL_DISH case DISH: sendDISH(data, nbits); break;
|
||||
#define SEND_PROTOCOL_JVC case JVC: sendJVC(data, nbits, 0); break;
|
||||
#define SEND_PROTOCOL_SAMSUNG case SAMSUNG: sendSAMSUNG(data, nbits); break;
|
||||
#define SEND_PROTOCOL_LG case LG: sendLG(data, nbits); break;
|
||||
#define SEND_PROTOCOL_WHYNTER case WHYNTER: sendWhynter(data, nbits); break;
|
||||
#define SEND_PROTOCOL_COOLIX case COOLIX: sendCOOLIX(data, nbits); break;
|
||||
#define SEND_PROTOCOL_DENON case DENON: sendDenon(data, nbits); break;
|
||||
#define SEND_PROTOCOL_SHERWOOD case SHERWOOD: sendSherwood(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RCMM case RCMM: sendRCMM(data, nbits); break;
|
||||
|
||||
|
||||
// main class for receiving IR
|
||||
class IRrecv
|
||||
{
|
||||
public:
|
||||
IRrecv(int recvpin);
|
||||
bool decode(decode_results *results);
|
||||
bool decode(decode_results *results, irparams_t *save=NULL);
|
||||
void enableIRIn();
|
||||
void disableIRIn();
|
||||
void resume();
|
||||
private:
|
||||
// These are called by decode
|
||||
void copyIrParams(irparams_t *dest);
|
||||
int getRClevel(decode_results *results, int *offset, int *used, int t1);
|
||||
bool decodeNEC(decode_results *results);
|
||||
bool decodeSony(decode_results *results);
|
||||
@@ -120,6 +125,7 @@ public:
|
||||
bool decodeMitsubishi(decode_results *results);
|
||||
bool decodeRC5(decode_results *results);
|
||||
bool decodeRC6(decode_results *results);
|
||||
bool decodeRCMM(decode_results *results);
|
||||
bool decodePanasonic(decode_results *results);
|
||||
bool decodeLG(decode_results *results);
|
||||
bool decodeJVC(decode_results *results);
|
||||
@@ -131,6 +137,14 @@ public:
|
||||
bool decodeDaikin(decode_results *results);
|
||||
bool decodeDenon(decode_results *results);
|
||||
int compare(unsigned int oldval, unsigned int newval);
|
||||
uint32_t ticksLow(uint32_t usecs, uint8_t tolerance=TOLERANCE);
|
||||
uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance=TOLERANCE);
|
||||
bool match(uint32_t measured_ticks, uint32_t desired_us,
|
||||
uint8_t tolerance=TOLERANCE);
|
||||
bool matchMark(uint32_t measured_ticks, uint32_t desired_us,
|
||||
uint8_t tolerance=TOLERANCE, int excess=MARK_EXCESS);
|
||||
bool matchSpace(uint32_t measured_ticks, uint32_t desired_us,
|
||||
uint8_t tolerance=TOLERANCE, int excess=MARK_EXCESS);
|
||||
};
|
||||
|
||||
// Only used for testing; can remove virtual for shorter code
|
||||
@@ -139,6 +153,7 @@ public:
|
||||
#else
|
||||
#define VIRTUAL
|
||||
#endif
|
||||
|
||||
class IRsend
|
||||
{
|
||||
public:
|
||||
@@ -158,12 +173,13 @@ public:
|
||||
SEND_PROTOCOL_COOLIX
|
||||
SEND_PROTOCOL_DENON
|
||||
SEND_PROTOCOL_SHERWOOD
|
||||
SEND_PROTOCOL_RCMM
|
||||
}
|
||||
};
|
||||
void sendCOOLIX(unsigned long data, int nbits);
|
||||
void sendWhynter(unsigned long data, int nbits);
|
||||
void sendNEC(unsigned long data, int nbits=32, unsigned int repeat=0);
|
||||
void sendLG(unsigned long data, int nbits);
|
||||
void sendLG(unsigned long data, int nbits=28, unsigned int repeat=0);
|
||||
// sendSony() should typically be called with repeat=2 as Sony devices
|
||||
// expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes)
|
||||
// As the legacy use of this procedure was only to send a single code
|
||||
@@ -176,15 +192,19 @@ public:
|
||||
void sendGC(unsigned int buf[], int len);
|
||||
void sendRC5(unsigned long data, int nbits);
|
||||
void sendRC6(unsigned long data, int nbits);
|
||||
void sendDISH(unsigned long data, int nbits);
|
||||
void sendRCMM(uint32_t data, uint8_t nbits=24);
|
||||
// sendDISH() should typically be called with repeat=3 as DISH devices
|
||||
// expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes)
|
||||
// As the legacy use of this procedure was only to send a single code
|
||||
// it defaults to repeat=0 for backward compatiblity.
|
||||
void sendDISH(unsigned long data, int nbits, unsigned int repeat=0);
|
||||
void sendSharp(unsigned int address, unsigned int command);
|
||||
void sendSharpRaw(unsigned long data, int nbits);
|
||||
void sendPanasonic(unsigned int address, unsigned long data);
|
||||
void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does.
|
||||
void sendSAMSUNG(unsigned long data, int nbits);
|
||||
void sendDaikin(unsigned char daikin[]);
|
||||
void sendDaikinChunk(unsigned char buf[], int len, int start);
|
||||
void sendDenon(unsigned long data, int nbits);
|
||||
void sendJVC(unsigned long data, int nbits, unsigned int repeat=0);
|
||||
void sendSAMSUNG(unsigned long data, int nbits=32);
|
||||
void sendDaikin(unsigned char data[]);
|
||||
void sendDenon(unsigned long data, int nbits=14);
|
||||
void sendKelvinator(unsigned char data[]);
|
||||
void sendSherwood(unsigned long data, int nbits=32, unsigned int repeat=1);
|
||||
void sendMitsubishiAC(unsigned char data[]);
|
||||
@@ -210,12 +230,4 @@ private:
|
||||
uint32_t start;
|
||||
};
|
||||
|
||||
// Some useful constants
|
||||
#define USECPERTICK 50 // microseconds per clock interrupt tick
|
||||
#define RAWBUF 100 // Length of raw duration buffer
|
||||
|
||||
// Marks tend to be 100us too long, and spaces 100us too short
|
||||
// when received due to sensor lag.
|
||||
#define MARK_EXCESS 100
|
||||
|
||||
#endif
|
||||
|
||||
@@ -60,10 +60,11 @@
|
||||
#define NEC_RPT_SPACE 2250
|
||||
#define NEC_MIN_COMMAND_LENGTH 108000UL
|
||||
|
||||
// Timings based on http://www.sbprojects.com/knowledge/ir/sirc.php
|
||||
#define SONY_HDR_MARK 2400
|
||||
#define SONY_HDR_SPACE 600
|
||||
#define SONY_ONE_MARK 1200
|
||||
#define SONY_ZERO_MARK 600
|
||||
#define SONY_ONE_MARK 1250 // Experiments suggest +50 to spec is better.
|
||||
#define SONY_ZERO_MARK 650 // Experiments suggest +50 to spec is better.
|
||||
#define SONY_RPT_LENGTH 45000
|
||||
#define SONY_DOUBLE_SPACE_USECS 500 // usually see 713 - not using ticks as get number wrapround
|
||||
|
||||
@@ -105,6 +106,20 @@
|
||||
#define RC6_T1 444
|
||||
#define RC6_RPT_LENGTH 46000
|
||||
|
||||
// http://www.sbprojects.com/knowledge/ir/rcmm.php
|
||||
#define RCMM_HDR_MARK 416
|
||||
#define RCMM_HDR_SPACE 277
|
||||
#define RCMM_BIT_MARK 166
|
||||
#define RCMM_BIT_SPACE_0 277
|
||||
#define RCMM_BIT_SPACE_1 444
|
||||
#define RCMM_BIT_SPACE_2 611
|
||||
#define RCMM_BIT_SPACE_3 777
|
||||
#define RCMM_RPT_LENGTH 27778
|
||||
#define RCMM_MIN_GAP 3360
|
||||
// Use a tolerance of +/-10% when matching some data spaces.
|
||||
#define RCMM_TOLERANCE 10
|
||||
#define RCMM_EXCESS 50
|
||||
|
||||
#define SHARP_BIT_MARK 245
|
||||
#define SHARP_ONE_SPACE 1805
|
||||
#define SHARP_ZERO_SPACE 795
|
||||
@@ -118,13 +133,13 @@
|
||||
#define DISH_ONE_SPACE 1700
|
||||
#define DISH_ZERO_SPACE 2800
|
||||
#define DISH_RPT_SPACE 6200
|
||||
#define DISH_TOP_BIT 0x8000
|
||||
|
||||
#define PANASONIC_HDR_MARK 3502
|
||||
#define PANASONIC_HDR_SPACE 1750
|
||||
#define PANASONIC_BIT_MARK 502
|
||||
#define PANASONIC_ONE_SPACE 1244
|
||||
#define PANASONIC_ZERO_SPACE 400
|
||||
// Ref: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152
|
||||
#define PANASONIC_HDR_MARK 3456
|
||||
#define PANASONIC_HDR_SPACE 1728
|
||||
#define PANASONIC_BIT_MARK 432
|
||||
#define PANASONIC_ONE_SPACE 1296
|
||||
#define PANASONIC_ZERO_SPACE 432
|
||||
|
||||
#define JVC_HDR_MARK 8000
|
||||
#define JVC_HDR_SPACE 4000
|
||||
@@ -184,15 +199,18 @@
|
||||
#define KELVINATOR_GAP_SPACE 19950U
|
||||
#define KELVINATOR_CMD_FOOTER 2U
|
||||
|
||||
#define TOLERANCE 25 // percent tolerance in measurements
|
||||
#define LTOL (1.0 - TOLERANCE/100.)
|
||||
#define UTOL (1.0 + TOLERANCE/100.)
|
||||
// Some useful constants
|
||||
#define USECPERTICK 50 // microseconds per clock interrupt tick
|
||||
#define RAWBUF 100 // Length of raw duration buffer
|
||||
|
||||
// Marks tend to be 100us too long, and spaces 100us too short
|
||||
// when received due to sensor lag.
|
||||
#define MARK_EXCESS 100
|
||||
|
||||
#define _GAP 5000 // Minimum map between transmissions
|
||||
#define GAP_TICKS (_GAP/USECPERTICK)
|
||||
|
||||
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
|
||||
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1))
|
||||
#define TOLERANCE 25 // default percent tolerance in measurements
|
||||
|
||||
// receiver states
|
||||
#define STATE_IDLE 2
|
||||
@@ -200,14 +218,18 @@
|
||||
#define STATE_SPACE 4
|
||||
#define STATE_STOP 5
|
||||
|
||||
#define RAWBUF 100 // Length of raw duration buffer
|
||||
|
||||
// information for the interrupt handler
|
||||
typedef struct {
|
||||
uint8_t recvpin; // pin for IR data from detector
|
||||
uint8_t rcvstate; // state machine
|
||||
unsigned int timer; // state timer, counts 50uS ticks.
|
||||
unsigned int rawbuf[RAWBUF]; // raw data
|
||||
uint8_t rawlen; // counter of entries in rawbuf
|
||||
uint8_t overflow;
|
||||
uint8_t recvpin; // pin for IR data from detector
|
||||
uint8_t rcvstate; // state machine
|
||||
unsigned int timer; // state timer, counts 50uS ticks.
|
||||
unsigned int rawbuf[RAWBUF]; // raw data
|
||||
// uint16_t is used for rawlen as it saves 3 bytes of iram in the interrupt
|
||||
// handler. Don't ask why, I don't know. It just does.
|
||||
uint16_t rawlen; // counter of entries in rawbuf.
|
||||
uint8_t overflow; // Buffer overflow indicator.
|
||||
}
|
||||
irparams_t;
|
||||
|
||||
|
||||
@@ -18,6 +18,15 @@ Seb's notes : I also changed the pulse parameters for Samsung, update the Panaso
|
||||
5. Restart your Arduino ide
|
||||
6. Check out the examples
|
||||
|
||||
###### Using Git to install library ( Linux )
|
||||
```
|
||||
cd ~/Arduino/libraries
|
||||
git clone https://github.com/markszabo/IRremoteESP8266.git
|
||||
```
|
||||
###### To Update to the latest version of the library
|
||||
`
|
||||
cd ~/Arduino/libraries/IRremoteESP8266 && git pull
|
||||
`
|
||||
## Contributing
|
||||
If you want to contribute to this project:
|
||||
- Report bugs and errors
|
||||
|
||||
@@ -26,7 +26,7 @@ void handleIr(){
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
if(server.argName(i) == "code")
|
||||
{
|
||||
unsigned long code = server.arg(i).toInt();
|
||||
unsigned long code = strtoul(server.arg(i).c_str(), NULL, 10);
|
||||
irsend.sendNEC(code, 32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,39 @@
|
||||
/*
|
||||
* IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv
|
||||
* An IR detector/demodulator must be connected to the input RECV_PIN.
|
||||
* Version 0.1 Sept, 2015
|
||||
* Example circuit diagram:
|
||||
* https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving
|
||||
* Changes:
|
||||
* Version 0.2 April, 2017
|
||||
* - Decode from a copy of the data so we can start capturing faster thus
|
||||
* reduce the likelihood of miscaptures.
|
||||
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com
|
||||
*/
|
||||
|
||||
#include <IRremoteESP8266.h>
|
||||
|
||||
int RECV_PIN = 2; //an IR detector/demodulator is connected to GPIO pin 2
|
||||
// An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU board).
|
||||
int RECV_PIN = 14;
|
||||
|
||||
IRrecv irrecv(RECV_PIN);
|
||||
|
||||
void setup ( )
|
||||
{
|
||||
Serial.begin(9600); // Status message will be sent to PC at 9600 baud
|
||||
decode_results results; // Somewhere to store the results
|
||||
irparams_t save; // A place to copy the interrupt state while decoding.
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); // Status message will be sent to the PC at 115200 baud
|
||||
irrecv.enableIRIn(); // Start the receiver
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
// Display IR code
|
||||
//
|
||||
void ircode (decode_results *results)
|
||||
{
|
||||
void ircode(decode_results *results) {
|
||||
// Panasonic has an Address
|
||||
if (results->decode_type == PANASONIC) {
|
||||
Serial.print(results->panasonicAddress, HEX);
|
||||
Serial.print(":");
|
||||
}
|
||||
|
||||
// Print Code
|
||||
Serial.print(results->value, HEX);
|
||||
}
|
||||
@@ -35,8 +41,7 @@ void ircode (decode_results *results)
|
||||
//+=============================================================================
|
||||
// Display encoding type
|
||||
//
|
||||
void encoding (decode_results *results)
|
||||
{
|
||||
void encoding(decode_results *results) {
|
||||
switch (results->decode_type) {
|
||||
default:
|
||||
case UNKNOWN: Serial.print("UNKNOWN"); break ;
|
||||
@@ -54,14 +59,14 @@ void encoding (decode_results *results)
|
||||
case WHYNTER: Serial.print("WHYNTER"); break ;
|
||||
case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break ;
|
||||
case PANASONIC: Serial.print("PANASONIC"); break ;
|
||||
case DENON: Serial.print("DENON"); break ;
|
||||
}
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
// Dump out the decode_results structure.
|
||||
//
|
||||
void dumpInfo (decode_results *results)
|
||||
{
|
||||
void dumpInfo (decode_results *results) {
|
||||
if (results->overflow) {
|
||||
Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF");
|
||||
return;
|
||||
@@ -83,8 +88,7 @@ void dumpInfo (decode_results *results)
|
||||
//+=============================================================================
|
||||
// Dump out the decode_results structure.
|
||||
//
|
||||
void dumpRaw (decode_results *results)
|
||||
{
|
||||
void dumpRaw(decode_results *results) {
|
||||
// Print Raw data
|
||||
Serial.print("Timing[");
|
||||
Serial.print(results->rawlen-1, DEC);
|
||||
@@ -113,8 +117,7 @@ void dumpRaw (decode_results *results)
|
||||
//+=============================================================================
|
||||
// Dump out the decode_results structure.
|
||||
//
|
||||
void dumpCode (decode_results *results)
|
||||
{
|
||||
void dumpCode (decode_results *results) {
|
||||
// Start declaration
|
||||
Serial.print("unsigned int "); // variable type
|
||||
Serial.print("rawData["); // array name
|
||||
@@ -129,7 +132,7 @@ void dumpCode (decode_results *results)
|
||||
}
|
||||
|
||||
// End declaration
|
||||
Serial.print("};"); //
|
||||
Serial.print("};"); //
|
||||
|
||||
// Comment
|
||||
Serial.print(" // ");
|
||||
@@ -142,7 +145,6 @@ void dumpCode (decode_results *results)
|
||||
|
||||
// Now dump "known" codes
|
||||
if (results->decode_type != UNKNOWN) {
|
||||
|
||||
// Some protocols have an address
|
||||
if (results->decode_type == PANASONIC) {
|
||||
Serial.print("unsigned int addr = 0x");
|
||||
@@ -160,15 +162,12 @@ void dumpCode (decode_results *results)
|
||||
//+=============================================================================
|
||||
// The repeating section of the code
|
||||
//
|
||||
void loop ( )
|
||||
{
|
||||
decode_results results; // Somewhere to store the results
|
||||
|
||||
if (irrecv.decode(&results)) { // Grab an IR code
|
||||
void loop() {
|
||||
// Check if the IR code has been received.
|
||||
if (irrecv.decode(&results, &save)) {
|
||||
dumpInfo(&results); // Output the results
|
||||
dumpRaw(&results); // Output the results in RAW format
|
||||
dumpCode(&results); // Output the results as source code
|
||||
Serial.println(""); // Blank line between entries
|
||||
irrecv.resume(); // Prepare for the next value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,40 @@
|
||||
/*
|
||||
* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend
|
||||
* An IR LED must be connected to ESP8266 pin 0.
|
||||
* Version 0.1 June, 2015
|
||||
* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend.
|
||||
*
|
||||
* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2).
|
||||
*
|
||||
* TL;DR: The IR LED needs to be driven by a transistor for a good result.
|
||||
*
|
||||
* Suggested circuit:
|
||||
* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending
|
||||
*
|
||||
* Common mistakes & tips:
|
||||
* * Don't just connect the IR LED directly to the pin, it won't
|
||||
* have enough current to drive the IR LED effectively.
|
||||
* * Make sure you have the IR LED polarity correct.
|
||||
* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
|
||||
* * Typical digital camera/phones can be used to see if the IR LED is flashed.
|
||||
* Replace the IR LED with a normal LED if you don't have a digital camera
|
||||
* when debugging.
|
||||
* * Avoid using the following pins unless you really know what you are doing:
|
||||
* * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
|
||||
* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere.
|
||||
* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere.
|
||||
* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
|
||||
* for your first time. e.g. ESP-12 etc.
|
||||
*
|
||||
* Version 1.0 April, 2017
|
||||
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com
|
||||
*/
|
||||
|
||||
#include <IRremoteESP8266.h>
|
||||
|
||||
IRsend irsend(0); //an IR led is connected to GPIO pin 0
|
||||
IRsend irsend(4); //an IR led is connected to GPIO pin 4 (D2)
|
||||
|
||||
void setup()
|
||||
{
|
||||
irsend.begin();
|
||||
Serial.begin(9600);
|
||||
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -20,6 +42,6 @@ void loop() {
|
||||
irsend.sendNEC(0x00FFE01FUL, 32);
|
||||
delay(2000);
|
||||
Serial.println("Sony");
|
||||
irsend.sendSony(0xa90, 12);
|
||||
irsend.sendSony(0xa90, 12, 2);
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "IRremoteESP8266",
|
||||
"version": "1.0.2",
|
||||
"version": "1.2.0",
|
||||
"keywords": "infrared, ir, remote, esp8266",
|
||||
"description": "Send and receive infrared signals with multiple protocols (ESP8266)",
|
||||
"repository":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=IRremoteESP8266
|
||||
version=1.0.2
|
||||
version=1.2.0
|
||||
author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran
|
||||
maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto
|
||||
sentence=Send and receive infrared signals with multiple protocols (ESP8266)
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,241 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include "QEIx4.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
// bit masks for state machine - don't change!!!
|
||||
#define QEIx4_STATE 0xC
|
||||
#define QEIx4_MASK 0x1C
|
||||
#define QEIx4_1x_INC 0x0100
|
||||
#define QEIx4_2x_INC 0x0200
|
||||
#define QEIx4_4x_INC 0x0400
|
||||
#define QEIx4_1x_DEC 0x1000
|
||||
#define QEIx4_2x_DEC 0x2000
|
||||
#define QEIx4_4x_DEC 0x4000
|
||||
#define QEIx4_1x_MASK 0x11FF
|
||||
#define QEIx4_2x_MASK 0x33FF
|
||||
#define QEIx4_4x_MASK 0x77FF
|
||||
#define QEIx4_DIR 0x20
|
||||
#define QEIx4_A 1
|
||||
#define QEIx4_B 2
|
||||
#define QEIx4_AB 3
|
||||
#define QEIx4_S0 0x0
|
||||
#define QEIx4_S1 0x4
|
||||
#define QEIx4_S2 0x8
|
||||
#define QEIx4_S3 0xC
|
||||
#define QEIx4_CCW 0
|
||||
#define QEIx4_CW 0x10
|
||||
#define QEIx4_IS_CHG 0x7700
|
||||
#define QEIx4_IS_INC 0x0700
|
||||
#define QEIx4_IS_DEC 0x7000
|
||||
#define QEIx4_IS_DIR 0x20
|
||||
|
||||
// state machine for decoting - don't change!!!
|
||||
uint16_t QEIx4::__stateLUT[32] = {
|
||||
// act state S0 in CCW direction
|
||||
QEIx4_CCW | QEIx4_S0,
|
||||
QEIx4_CW | QEIx4_S1 | QEIx4_A | QEIx4_4x_INC | QEIx4_DIR,
|
||||
QEIx4_CCW | QEIx4_S0 | QEIx4_B,
|
||||
QEIx4_CCW | QEIx4_S3 | QEIx4_AB | QEIx4_1x_DEC,
|
||||
// act state S1 in CCW direction
|
||||
QEIx4_CCW | QEIx4_S1,
|
||||
QEIx4_CCW | QEIx4_S1 | QEIx4_A,
|
||||
QEIx4_CCW | QEIx4_S0 | QEIx4_B | QEIx4_4x_DEC,
|
||||
QEIx4_CW | QEIx4_S2 | QEIx4_AB | QEIx4_1x_INC | QEIx4_DIR,
|
||||
// act state S2 in CCW direction
|
||||
QEIx4_CCW | QEIx4_S1 | QEIx4_2x_DEC,
|
||||
QEIx4_CCW | QEIx4_S2 | QEIx4_A,
|
||||
QEIx4_CW | QEIx4_S3 | QEIx4_B | QEIx4_4x_INC | QEIx4_DIR,
|
||||
QEIx4_CCW | QEIx4_S2 | QEIx4_AB,
|
||||
// act state S3 in CCW direction
|
||||
QEIx4_CW | QEIx4_S0 | QEIx4_2x_INC | QEIx4_DIR,
|
||||
QEIx4_CCW | QEIx4_S2 | QEIx4_A | QEIx4_4x_DEC,
|
||||
QEIx4_CCW | QEIx4_S3 | QEIx4_B,
|
||||
QEIx4_CCW | QEIx4_S3 | QEIx4_AB,
|
||||
|
||||
// act state S0 in CW direction
|
||||
QEIx4_CW | QEIx4_S0,
|
||||
QEIx4_CW | QEIx4_S1 | QEIx4_A | QEIx4_4x_INC,
|
||||
QEIx4_CW | QEIx4_S0 | QEIx4_B,
|
||||
QEIx4_CCW | QEIx4_S3 | QEIx4_AB | QEIx4_1x_DEC | QEIx4_DIR,
|
||||
// act state S1 in CW direction
|
||||
QEIx4_CW | QEIx4_S1,
|
||||
QEIx4_CW | QEIx4_S1 | QEIx4_A,
|
||||
QEIx4_CCW | QEIx4_S0 | QEIx4_B | QEIx4_4x_DEC | QEIx4_DIR,
|
||||
QEIx4_CW | QEIx4_S2 | QEIx4_AB | QEIx4_1x_INC,
|
||||
// act state S2 in CW direction
|
||||
QEIx4_CCW | QEIx4_S1 | QEIx4_2x_DEC | QEIx4_DIR,
|
||||
QEIx4_CW | QEIx4_S2 | QEIx4_A,
|
||||
QEIx4_CW | QEIx4_S3 | QEIx4_B | QEIx4_4x_INC,
|
||||
QEIx4_CW | QEIx4_S2 | QEIx4_AB,
|
||||
// act state S3 in CW direction
|
||||
QEIx4_CW | QEIx4_S0 | QEIx4_2x_INC,
|
||||
QEIx4_CCW | QEIx4_S2 | QEIx4_A | QEIx4_4x_DEC | QEIx4_DIR,
|
||||
QEIx4_CW | QEIx4_S3 | QEIx4_B,
|
||||
QEIx4_CW | QEIx4_S3 | QEIx4_AB
|
||||
};
|
||||
|
||||
// Helper for ISR call
|
||||
QEIx4* QEIx4::__instance[4] = { 0 };
|
||||
|
||||
|
||||
//#define DEB(x) printf (x)
|
||||
#define DEB(x)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QEIx4::QEIx4()
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
if (__instance[i] == 0)
|
||||
{
|
||||
__instance[i] = this;
|
||||
DEB("::");
|
||||
break;
|
||||
}
|
||||
|
||||
_pinA = -1;
|
||||
_pinB = -1;
|
||||
_pinI = -1;
|
||||
_state = 0;
|
||||
_limitMin = LONG_MIN;
|
||||
_limitMax = LONG_MAX;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QEIx4::~QEIx4()
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
if (__instance[i] == this)
|
||||
{
|
||||
__instance[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QEIx4::begin(int16_t pinA, int16_t pinB, int16_t pinI, uint8_t mode)
|
||||
{
|
||||
if (_pinA >= 0)
|
||||
detachInterrupt(digitalPinToInterrupt(_pinA));
|
||||
if (_pinB >= 0)
|
||||
detachInterrupt(digitalPinToInterrupt(_pinB));
|
||||
|
||||
_pinA = pinA;
|
||||
_pinB = pinB;
|
||||
_pinI = pinI;
|
||||
|
||||
_counter = 0;
|
||||
_bHasChanged = true;
|
||||
|
||||
if (mode == 1)
|
||||
_eventMask = QEIx4_1x_MASK;
|
||||
else if (mode == 2)
|
||||
_eventMask = QEIx4_2x_MASK;
|
||||
else
|
||||
_eventMask = QEIx4_4x_MASK;
|
||||
|
||||
pinMode(_pinA, INPUT_PULLUP);
|
||||
pinMode(_pinB, INPUT_PULLUP);
|
||||
pinMode(_pinI, INPUT_PULLUP);
|
||||
|
||||
if (_pinA >= 0)
|
||||
attachInterrupt(digitalPinToInterrupt(_pinA), ISR, CHANGE);
|
||||
if (_pinB >= 0)
|
||||
attachInterrupt(digitalPinToInterrupt(_pinB), ISR, CHANGE);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
long QEIx4::read()
|
||||
{
|
||||
noInterrupts();
|
||||
_bHasChanged = false;
|
||||
long ret = _counter;
|
||||
interrupts();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QEIx4::loop()
|
||||
{
|
||||
noInterrupts();
|
||||
processStateMachine();
|
||||
interrupts();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QEIx4::processStateMachine()
|
||||
{
|
||||
DEB(".");
|
||||
|
||||
_state &= QEIx4_MASK;
|
||||
if (digitalRead(_pinA)) _state |= QEIx4_A;
|
||||
if (digitalRead(_pinB)) _state |= QEIx4_B;
|
||||
|
||||
_state = __stateLUT[_state]; // magic is done by lookup-table
|
||||
_state &= _eventMask;
|
||||
|
||||
if (_state & QEIx4_IS_CHG) { // is any change?
|
||||
bool bCounterChange = false;
|
||||
|
||||
if ((_state & QEIx4_IS_INC) && (_counter < _limitMax)) { // has moved foreward?
|
||||
_counter++;
|
||||
bCounterChange = true;
|
||||
DEB("+");
|
||||
}
|
||||
if ((_state & QEIx4_IS_DEC) && (_counter > _limitMin)) { // has moved backward?
|
||||
_counter--;
|
||||
bCounterChange = true;
|
||||
DEB("-");
|
||||
}
|
||||
|
||||
if (_pinI >= 0 && _bIndexTrigger && bCounterChange && digitalRead(_pinI)) { // is index pin triggered?
|
||||
_bIndexTrigger = false;
|
||||
_counter = 0;
|
||||
DEB("I");
|
||||
}
|
||||
|
||||
if (bCounterChange) { // has counter changed?
|
||||
_bHasChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QEIx4::ISR()
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
if (__instance[i])
|
||||
{
|
||||
__instance[i]->processStateMachine();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,133 @@
|
||||
/*--------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
#ifndef QEIX4_H
|
||||
#define QEIX4_H
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#include <pins_arduino.h>
|
||||
#endif
|
||||
|
||||
class QEIx4
|
||||
{
|
||||
public:
|
||||
|
||||
/** constructor of QEIx4 object
|
||||
*/
|
||||
QEIx4();
|
||||
|
||||
/** destructor of QEIx4 object
|
||||
*/
|
||||
~QEIx4();
|
||||
|
||||
void begin(int16_t pinA, int16_t pinB, int16_t pinI=-1, uint8_t mode=4);
|
||||
|
||||
/** Gets the actual counter value.
|
||||
*
|
||||
* @return Actual counter value
|
||||
*/
|
||||
long read();
|
||||
|
||||
/** Gets the actual counter value as long operator.
|
||||
*
|
||||
* @return Actual counter value as long operator
|
||||
*/
|
||||
operator long() { // int-Operator
|
||||
return read();
|
||||
}
|
||||
|
||||
/** Sets the counter value at actual encoder position to given value.
|
||||
*
|
||||
* @param Counter value
|
||||
*/
|
||||
void write(long counter) {
|
||||
_counter = counter;
|
||||
}
|
||||
|
||||
/** Sets the counter value at actual encoder position to given value as assign operator.
|
||||
*
|
||||
* @param Counter value
|
||||
*/
|
||||
int operator= (long counter) { // Assign-Operator
|
||||
write(counter);
|
||||
return counter;
|
||||
}
|
||||
|
||||
void setLimit(long limitMin, long limitMax)
|
||||
{
|
||||
_limitMin = limitMin;
|
||||
_limitMax = limitMax;
|
||||
}
|
||||
|
||||
/** Sets the flag for zeroing on next high on index pin while AB lines triggers next counting. The trigger calls tha callback function in which the counter can be set to zero or the actual counter can be latched in for later offset calculation
|
||||
*
|
||||
* @param Flag for triggering. Set to 1 for call the attached callback. It is reseted after this call
|
||||
*/
|
||||
void setIndexTrigger(bool bIndexTrigger=true) {
|
||||
if (_pinI < 0)
|
||||
bIndexTrigger = false;
|
||||
_bIndexTrigger = bIndexTrigger;
|
||||
}
|
||||
|
||||
bool hasChanged(){
|
||||
return _bHasChanged;
|
||||
}
|
||||
|
||||
void loop();
|
||||
|
||||
protected:
|
||||
|
||||
/** Polls the state machine and updates the counter value.
|
||||
*/
|
||||
void processStateMachine();
|
||||
|
||||
/** Entry point for arduino interrupts - route to class instances
|
||||
*/
|
||||
static void ISR();
|
||||
|
||||
protected:
|
||||
|
||||
volatile long _counter;
|
||||
volatile bool _bHasChanged;
|
||||
volatile bool _bIndexTrigger;
|
||||
|
||||
int16_t _pinA;
|
||||
int16_t _pinB;
|
||||
int16_t _pinI;
|
||||
long _limitMin;
|
||||
long _limitMax;
|
||||
uint16_t _state;
|
||||
uint16_t _eMode;
|
||||
|
||||
private:
|
||||
static uint16_t __stateLUT[32];
|
||||
static QEIx4* __instance[4];
|
||||
uint16_t _eventMask;
|
||||
};
|
||||
|
||||
#endif // QEIX4_H
|
||||
@@ -0,0 +1,28 @@
|
||||
# MechInputs Library (https://github.com/jkDesignDE/MechInputs)
|
||||
|
||||
Arduino library for reading and debouncing mechanical inputs Like buttons, switches and encoders.
|
||||
|
||||
After downloading, rename folder to 'MechInputs' and install in Arduino Libraries folder. Restart Arduino IDE, then open File->Sketchbook->Library->MechInputs->* sketches.
|
||||
|
||||
# QEI (quadrature encoder interface) library, for decoding AB signals from a rotary encoder
|
||||
|
||||
Use cases:
|
||||
- Rotary encoder in closed loop motor regulation
|
||||
- Hand wheel
|
||||
- Input device for motion control (MoCo)
|
||||
|
||||
|
||||
A class to decode pulses on a rotary encoder with AB signals (quadrature encoder).
|
||||
It uses all 4 edges of the AB signals to increase the counter resolution 4 times of cycles per rotation/revolution (CPR) (e.g. an encoder with 500 CPR get 2000 counts per rotation)
|
||||
|
||||
In opposite to most common QEI implementation this is resistant to jitter and chatter on AB signals and motor vibrations.
|
||||
Whes reaching the next position the edge that triggerd this position (state) is ignored to aboid oscillating up/down counts.
|
||||
|
||||
It can also be used in polling mode i.g. in idle routines if interrupts are not desired.
|
||||
At this mode be sure that the sampling frequency is heigher than the maximum rotation speed (expeced counts per second)
|
||||
|
||||
The internal state machine is based on a look up table (LUT) to minimize interrupt retention time and get all necessary flags at once.
|
||||
|
||||
The library is designed to support closed loop speed- and motion-controller for also slow and smooth motions like movie camera motion control.
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
name=MechInputs
|
||||
version=0.0.1
|
||||
author=Jochen Krapf
|
||||
maintainer=Jochen Krapf <jk@nerd2nerd.org>
|
||||
sentence=Library for Reading and Debouncing Mechanical Inputs Like Buttons, Switches and Encoders with Arduino-Based Controllers.
|
||||
paragraph=Library for Reading and Debouncing Mechanical Inputs Like Buttons, Switches and Encoders with Arduino-Based Controllers.
|
||||
category=Input
|
||||
url=https://github.com/jkDesignDE/MechInputs
|
||||
architectures=esp8266,avr
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,81 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <SensorSerial.h>
|
||||
|
||||
|
||||
SensorSerial::SensorSerial(int receivePin, int transmitPin, bool inverse_logic, unsigned int buffSize) : ESPeasySoftwareSerial(receivePin, transmitPin, inverse_logic, buffSize)
|
||||
{
|
||||
//boolean sws = isValidGPIOpin(receivePin);
|
||||
_hw = receivePin < 0;
|
||||
}
|
||||
|
||||
void SensorSerial::begin(long speed)
|
||||
{
|
||||
if (_hw)
|
||||
Serial.begin(speed);
|
||||
else
|
||||
ESPeasySoftwareSerial::begin(speed);
|
||||
}
|
||||
|
||||
int SensorSerial::peek()
|
||||
{
|
||||
if (_hw)
|
||||
return Serial.peek();
|
||||
else
|
||||
return ESPeasySoftwareSerial::peek();
|
||||
}
|
||||
|
||||
size_t SensorSerial::write(uint8_t byte)
|
||||
{
|
||||
if (_hw)
|
||||
return Serial.write(byte);
|
||||
else
|
||||
return ESPeasySoftwareSerial::write(byte);
|
||||
}
|
||||
|
||||
int SensorSerial::read()
|
||||
{
|
||||
if (_hw)
|
||||
return Serial.read();
|
||||
else
|
||||
return ESPeasySoftwareSerial::read();
|
||||
}
|
||||
|
||||
int SensorSerial::available()
|
||||
{
|
||||
if (_hw)
|
||||
return Serial.available();
|
||||
else
|
||||
return ESPeasySoftwareSerial::available();
|
||||
}
|
||||
|
||||
void SensorSerial::flush()
|
||||
{
|
||||
if (_hw)
|
||||
Serial.flush();
|
||||
else
|
||||
ESPeasySoftwareSerial::flush();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _SENSORSERIAL_H_
|
||||
#define _SENSORSERIAL_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
class SensorSerial : public ESPeasySoftwareSerial
|
||||
{
|
||||
public:
|
||||
SensorSerial(int receivePin, int transmitPin = -1, bool inverse_logic = false, unsigned int buffSize = 64);
|
||||
|
||||
void begin(long speed);
|
||||
|
||||
int peek();
|
||||
|
||||
virtual size_t write(uint8_t byte);
|
||||
|
||||
virtual int read();
|
||||
|
||||
virtual int available();
|
||||
|
||||
virtual void flush();
|
||||
|
||||
protected:
|
||||
boolean _hw;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include "SensorSerialBuffer.h"
|
||||
|
||||
CSensorSerialBuffer::CSensorSerialBuffer()
|
||||
{
|
||||
_writeIndex = 0;
|
||||
_packetLength = 0;
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CSensorSerialBuffer::Clear ()
|
||||
{
|
||||
for (byte i=0; i<SERIALBUFFER_SIZE; i++)
|
||||
_buffer[i] = 0;
|
||||
}
|
||||
|
||||
void CSensorSerialBuffer::AddData (byte b)
|
||||
{
|
||||
_buffer[_writeIndex] = b;
|
||||
_writeIndex++;
|
||||
_writeIndex &= SERIALBUFFER_MASK;
|
||||
}
|
||||
|
||||
void CSensorSerialBuffer::SetPacketLength (byte len)
|
||||
{
|
||||
_packetLength = len;
|
||||
}
|
||||
|
||||
byte& CSensorSerialBuffer::operator[] (byte x)
|
||||
{
|
||||
x += _writeIndex;
|
||||
x -= _packetLength;
|
||||
x &= SERIALBUFFER_MASK;
|
||||
return _buffer[x];
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _SENSORSERIALBUFFER_H_
|
||||
#define _SENSORSERIALBUFFER_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define SERIALBUFFER_SIZE 32
|
||||
#define SERIALBUFFER_MASK 31
|
||||
|
||||
class CSensorSerialBuffer
|
||||
{
|
||||
public:
|
||||
CSensorSerialBuffer();
|
||||
|
||||
void Clear ();
|
||||
|
||||
void AddData (byte b);
|
||||
|
||||
void SetPacketLength (byte len);
|
||||
|
||||
byte& operator[] (byte x);
|
||||
|
||||
private:
|
||||
byte _buffer[SERIALBUFFER_SIZE];
|
||||
byte _writeIndex;
|
||||
byte _packetLength;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,188 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include "jkSDS011.h"
|
||||
|
||||
CjkSDS011::CjkSDS011(int16_t pinRX, int16_t pinTX)
|
||||
{
|
||||
_sws = ! ( pinRX < 0 || pinRX == 3 );
|
||||
_pm2_5 = NAN;
|
||||
_pm10_ = NAN;
|
||||
_available = false;
|
||||
_pm2_5avr = 0;
|
||||
_pm10_avr = 0;
|
||||
_avr = 0;
|
||||
_data.SetPacketLength(10);
|
||||
_command.SetPacketLength(19);
|
||||
_working_period = -1;
|
||||
_sleepmode_active = false;
|
||||
_serial = new ESPeasySoftwareSerial(pinRX, pinTX);
|
||||
_serial->begin(9600);
|
||||
}
|
||||
|
||||
CjkSDS011::~CjkSDS011() {
|
||||
delete _serial;
|
||||
}
|
||||
|
||||
void CjkSDS011::SendCommand(byte byte1, byte byte2, byte byte3) {
|
||||
_command[0] = 0xAA; // Head
|
||||
_command[1] = 0xB4; // Command ID
|
||||
_command[2] = byte1; // Data Byte 1
|
||||
_command[3] = byte2; // Data Byte 2
|
||||
_command[4] = byte3; // Data Byte 3
|
||||
_command[5] = 0; // Data Byte 4
|
||||
_command[6] = 0; // Data Byte 5
|
||||
_command[7] = 0; // Data Byte 6
|
||||
_command[8] = 0; // Data Byte 7
|
||||
_command[9] = 0; // Data Byte 8
|
||||
_command[10] = 0; // Data Byte 9
|
||||
_command[11] = 0; // Data Byte 10
|
||||
_command[12] = 0; // Data Byte 11
|
||||
_command[13] = 0; // Data Byte 12
|
||||
_command[14] = 0; // Data Byte 13
|
||||
_command[15] = 0xFF; // Device ID byte 1, FF: All sensor response
|
||||
_command[16] = 0xFF; // Device ID byte 2, FF: All sensor response
|
||||
|
||||
byte checksum = 0;
|
||||
for (byte i=2; i< 17; ++i) {
|
||||
checksum += _command[i];
|
||||
}
|
||||
_command[17] = checksum; // Checksum
|
||||
_command[18] = 0xAB; // Tail
|
||||
|
||||
for (int i = 0; i < 19; ++i) {
|
||||
_serial->write(_command[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CjkSDS011::SetSleepMode(bool enabled) {
|
||||
byte databyte3 = enabled ? 0 : 1;
|
||||
SendCommand(6, 1, databyte3);
|
||||
}
|
||||
|
||||
void CjkSDS011::SetWorkingPeriod(int minutes) {
|
||||
// Data byte 1: 8
|
||||
// Data byte 2: 0: query the current mode
|
||||
// 1: set mode
|
||||
// Data byte 3: 0:continuous(default)
|
||||
// 1-30minute:work 30 seconds and sleep n*60-30 seconds
|
||||
if (minutes < 0 || minutes > 30) return;
|
||||
// Working period is stored in the flash of the sensor. Only write to change.
|
||||
const int currentWorkingPeriod = GetWorkingPeriod();
|
||||
if (minutes != currentWorkingPeriod)
|
||||
SendCommand(8, 1, minutes);
|
||||
}
|
||||
|
||||
int CjkSDS011::GetWorkingPeriod() {
|
||||
// Data byte 1: 8
|
||||
// Data byte 2: 0: query the current mode
|
||||
// 1: set mode
|
||||
// Data byte 3: 0:continuous(default)
|
||||
// 1-30minute:work 30 seconds and sleep n*60-30 seconds
|
||||
SendCommand(8, 0, 0);
|
||||
Process();
|
||||
return _working_period;
|
||||
}
|
||||
|
||||
void CjkSDS011::ParseCommandReply() {
|
||||
switch(_data[2]) {
|
||||
case 6: // Enable/Disable sleep mode.
|
||||
if (_data[3] == 0)
|
||||
_sleepmode_active = _data[4];
|
||||
break;
|
||||
case 8: // Set/Get working period
|
||||
if (_data[3] == 0)
|
||||
_working_period = _data[4];
|
||||
break;
|
||||
default:
|
||||
// Not implemented.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CjkSDS011::Process()
|
||||
{
|
||||
while (_serial->available())
|
||||
{
|
||||
_data.AddData(_serial->read());
|
||||
|
||||
if (_data[0] == 0xAA && _data[9] == 0xAB) // correct packet frame?
|
||||
{
|
||||
byte checksum = 0;
|
||||
for (byte i=2; i<= 7; i++)
|
||||
checksum += _data[i];
|
||||
if (checksum != _data[8])
|
||||
continue;
|
||||
|
||||
switch(_data[1]) {
|
||||
case 0xC0: // SDS011 or SDS018?
|
||||
_pm2_5 = (float)((_data[3] << 8) | _data[2]) * 0.1;
|
||||
_pm10_ = (float)((_data[5] << 8) | _data[4]) * 0.1;
|
||||
_available = true;
|
||||
break;
|
||||
case 0xCF: // SDS198?
|
||||
_pm2_5 = (float)((_data[5] << 8) | _data[4]);
|
||||
_pm10_ = (float)((_data[3] << 8) | _data[2]);
|
||||
_available = true;
|
||||
break;
|
||||
case 0xC5: // Reply on command ID 0xB4
|
||||
ParseCommandReply();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_available) {
|
||||
_pm2_5avr += _pm2_5;
|
||||
_pm10_avr += _pm10_;
|
||||
_avr++;
|
||||
_data.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean CjkSDS011::available()
|
||||
{
|
||||
boolean ret = _available;
|
||||
_available = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
boolean CjkSDS011::ReadAverage(float &pm25, float &pm10)
|
||||
{
|
||||
if (_avr)
|
||||
{
|
||||
pm25 = _pm2_5avr / _avr;
|
||||
pm10 = _pm10_avr / _avr;
|
||||
_pm2_5avr = 0;
|
||||
_pm10_avr = 0;
|
||||
_avr = 0;
|
||||
return true;
|
||||
}
|
||||
pm25 = NAN;
|
||||
pm10 = NAN;
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
Arduino library to ...
|
||||
|
||||
Written by Jochen Krapf,
|
||||
contributions by ... and other members of the open
|
||||
source community.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the MechInputs library.
|
||||
|
||||
MechInputs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
MechInputs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with MechInputs. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _jkSDS011_H_
|
||||
#define _jkSDS011_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
//#include "SensorSerial.h"
|
||||
#include "SensorSerialBuffer.h"
|
||||
#include "ESPeasySoftwareSerial.h"
|
||||
|
||||
class CjkSDS011
|
||||
{
|
||||
public:
|
||||
CjkSDS011(int16_t pinRX, int16_t pinTX);
|
||||
virtual ~CjkSDS011();
|
||||
|
||||
void Process();
|
||||
|
||||
boolean available();
|
||||
|
||||
float GetPM2_5() { return _pm2_5; };
|
||||
float GetPM10_() { return _pm10_; };
|
||||
|
||||
// Return true when there are valid samples.
|
||||
boolean ReadAverage(float &pm25, float &pm10);
|
||||
|
||||
void SetSleepMode(bool enabled);
|
||||
|
||||
// Set interval to get new data, 0 .. 30 minutes.
|
||||
// Minutes = 0 => continous mode.
|
||||
// The setting is still effective after power off(factory default is continuous measurement)
|
||||
void SetWorkingPeriod(int minutes);
|
||||
|
||||
// Get the working period in minutes (0 = continuous reading)
|
||||
// Negative return value indicates error during communication.
|
||||
int GetWorkingPeriod();
|
||||
|
||||
private:
|
||||
void SendCommand(byte byte1, byte byte2, byte byte3);
|
||||
void ParseCommandReply();
|
||||
|
||||
// SensorSerial _serial;
|
||||
ESPeasySoftwareSerial *_serial;
|
||||
CSensorSerialBuffer _data;
|
||||
CSensorSerialBuffer _command;
|
||||
float _pm2_5;
|
||||
float _pm10_;
|
||||
float _pm2_5avr;
|
||||
float _pm10_avr;
|
||||
uint16_t _avr;
|
||||
boolean _available;
|
||||
boolean _sws;
|
||||
int _working_period;
|
||||
boolean _sleepmode_active;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
name=SerialSensors
|
||||
version=0.0.1
|
||||
author=Jochen Krapf
|
||||
maintainer=Jochen Krapf <jk@nerd2nerd.org>
|
||||
sentence=Library for Reading and Serial Data from Sensor Devices.
|
||||
paragraph=Library for Reading and Serial Data from Sensor Devices.
|
||||
category=Input
|
||||
url=https://github.com/jkDesignDE/SerialSensors
|
||||
architectures=esp8266,avr
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
|
||||
ESPeasySoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266.
|
||||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// The Arduino standard GPIO routines are not enough,
|
||||
// must use some from the Espressif SDK as well
|
||||
extern "C" {
|
||||
#include "gpio.h"
|
||||
}
|
||||
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
#define MAX_PIN 15
|
||||
#define USABLE_PINS 10
|
||||
#define NR_CONCURRENT_SOFT_SERIALS 3
|
||||
|
||||
// As the Arduino attachInterrupt has no parameter, lists of objects
|
||||
// and callbacks corresponding to each possible GPIO pins have to be defined
|
||||
static ESPeasySoftwareSerial *ObjList[NR_CONCURRENT_SOFT_SERIALS];
|
||||
static uint8_t PinControllerMap[NR_CONCURRENT_SOFT_SERIALS]={}; // Zero all elements
|
||||
|
||||
void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); };
|
||||
/*void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); };
|
||||
// Pin 6 to 11 can not be used
|
||||
void ICACHE_RAM_ATTR sws_isr_12() { ObjList[6]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_13() { ObjList[7]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_14() { ObjList[8]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_15() { ObjList[9]->rxRead(); };
|
||||
*/
|
||||
|
||||
static void (*ISRList[NR_CONCURRENT_SOFT_SERIALS])() = {
|
||||
sws_isr_0,
|
||||
sws_isr_1,
|
||||
sws_isr_2 /*,
|
||||
sws_isr_3,
|
||||
sws_isr_4,
|
||||
sws_isr_5,
|
||||
// Pin 6 to 11 can not be used
|
||||
sws_isr_12,
|
||||
sws_isr_13,
|
||||
sws_isr_14,
|
||||
sws_isr_15
|
||||
*/
|
||||
};
|
||||
|
||||
ESPeasySoftwareSerial::ESPeasySoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic, uint16_t buffSize) {
|
||||
m_rxValid = m_txValid = m_txEnableValid = false;
|
||||
m_buffer = NULL;
|
||||
m_invert = inverse_logic;
|
||||
if (isValidGPIOpin(receivePin)) {
|
||||
m_rxPin = receivePin;
|
||||
m_buffSize = buffSize;
|
||||
m_buffer = (uint8_t*)malloc(m_buffSize);
|
||||
if (m_buffer != NULL) {
|
||||
m_rxValid = true;
|
||||
m_inPos = m_outPos = 0;
|
||||
pinMode(m_rxPin, INPUT);
|
||||
const uint8_t index = pinToIndex(m_rxPin);
|
||||
if (index == NR_CONCURRENT_SOFT_SERIALS) {
|
||||
return; // Not possible to add software Serial.
|
||||
}
|
||||
ObjList[index] = this;
|
||||
enableRx(true);
|
||||
}
|
||||
}
|
||||
if (isValidGPIOpin(transmitPin)) {
|
||||
m_txValid = true;
|
||||
m_txPin = transmitPin;
|
||||
pinMode(m_txPin, OUTPUT);
|
||||
digitalWrite(m_txPin, !m_invert);
|
||||
}
|
||||
// Default speed
|
||||
begin(9600);
|
||||
}
|
||||
|
||||
ESPeasySoftwareSerial::~ESPeasySoftwareSerial() {
|
||||
enableRx(false);
|
||||
if (m_rxValid) {
|
||||
const uint8_t index = pinToIndex(m_rxPin);
|
||||
if (index < NR_CONCURRENT_SOFT_SERIALS) {
|
||||
PinControllerMap[index] = 0;
|
||||
ObjList[index] = NULL;
|
||||
}
|
||||
}
|
||||
if (m_buffer)
|
||||
free(m_buffer);
|
||||
}
|
||||
|
||||
bool ESPeasySoftwareSerial::isValidGPIOpin(uint8_t pin) {
|
||||
if (pin >= 0 && pin <= 5) {
|
||||
return true;
|
||||
}
|
||||
if (pin >= 12 && pin <= MAX_PIN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t ESPeasySoftwareSerial::pinToIndex(uint8_t pin) {
|
||||
// Pin will be stored in the map, only "1" will be added,
|
||||
// to allow simple initialize to 0 and still use GPIO-0.
|
||||
const uint8_t stored_pin = pin + 1;
|
||||
for (unsigned i = 0; i < NR_CONCURRENT_SOFT_SERIALS; ++i) {
|
||||
if (PinControllerMap[i] == stored_pin) return i;
|
||||
}
|
||||
// Not found, add as first free option.
|
||||
for (unsigned i = 0; i < NR_CONCURRENT_SOFT_SERIALS; ++i) {
|
||||
if (PinControllerMap[i] == 0) {
|
||||
PinControllerMap[i] = stored_pin;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// No more controllers available.
|
||||
return NR_CONCURRENT_SOFT_SERIALS;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::begin(long speed) {
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bitTime = ESP.getCpuFreqMHz()*1000000/speed;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::setTransmitEnablePin(uint8_t transmitEnablePin) {
|
||||
if (isValidGPIOpin(transmitEnablePin)) {
|
||||
m_txEnableValid = true;
|
||||
m_txEnablePin = transmitEnablePin;
|
||||
pinMode(m_txEnablePin, OUTPUT);
|
||||
digitalWrite(m_txEnablePin, LOW);
|
||||
} else {
|
||||
m_txEnableValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::enableRx(bool on) {
|
||||
if (m_rxValid) {
|
||||
if (on) {
|
||||
attachInterrupt(m_rxPin, ISRList[pinToIndex(m_rxPin)], m_invert ? RISING : FALLING);
|
||||
} else {
|
||||
detachInterrupt(m_rxPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::read() {
|
||||
if (!m_rxValid || (m_inPos == m_outPos)) return -1;
|
||||
uint8_t ch = m_buffer[m_outPos];
|
||||
m_outPos = (m_outPos+1) % m_buffSize;
|
||||
return ch;
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::available() {
|
||||
if (!m_rxValid) return 0;
|
||||
int avail = m_inPos - m_outPos;
|
||||
if (avail < 0) avail += m_buffSize;
|
||||
return avail;
|
||||
}
|
||||
|
||||
#define WAIT { while (ESP.getCycleCount()-start < wait); wait += m_bitTime; }
|
||||
|
||||
size_t ESPeasySoftwareSerial::write(uint8_t b) {
|
||||
if (!m_txValid) return 0;
|
||||
|
||||
if (m_invert) b = ~b;
|
||||
// Disable interrupts in order to get a clean transmit
|
||||
cli();
|
||||
if (m_txEnableValid) digitalWrite(m_txEnablePin, HIGH);
|
||||
unsigned long wait = m_bitTime;
|
||||
digitalWrite(m_txPin, HIGH);
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
// Start bit;
|
||||
digitalWrite(m_txPin, LOW);
|
||||
WAIT;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
digitalWrite(m_txPin, (b & 1) ? HIGH : LOW);
|
||||
WAIT;
|
||||
b >>= 1;
|
||||
}
|
||||
// Stop bit
|
||||
digitalWrite(m_txPin, HIGH);
|
||||
WAIT;
|
||||
if (m_txEnableValid) digitalWrite(m_txEnablePin, LOW);
|
||||
sei();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::flush() {
|
||||
m_inPos = m_outPos = 0;
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::peek() {
|
||||
if (!m_rxValid || (m_inPos == m_outPos)) return -1;
|
||||
return m_buffer[m_outPos];
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR ESPeasySoftwareSerial::rxRead() {
|
||||
// Advance the starting point for the samples but compensate for the
|
||||
// initial delay which occurs before the interrupt is delivered
|
||||
unsigned long wait = m_bitTime + m_bitTime/3 - 500;
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
uint8_t rec = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
WAIT;
|
||||
rec >>= 1;
|
||||
if (digitalRead(m_rxPin))
|
||||
rec |= 0x80;
|
||||
}
|
||||
if (m_invert) rec = ~rec;
|
||||
// Stop bit
|
||||
WAIT;
|
||||
// Store the received value in the buffer unless we have an overflow
|
||||
uint16_t next = (m_inPos+1) % m_buffSize;
|
||||
if (next != m_inPos) {
|
||||
m_buffer[m_inPos] = rec;
|
||||
m_inPos = next;
|
||||
}
|
||||
// Must clear this bit in the interrupt register,
|
||||
// it gets set even when interrupts are disabled
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rxPin);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
ESPeasySoftwareSerial.h
|
||||
|
||||
ESPeasySoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266.
|
||||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ESPeasySoftwareSerial_h
|
||||
#define ESPeasySoftwareSerial_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Stream.h>
|
||||
|
||||
|
||||
// This class is compatible with the corresponding AVR one,
|
||||
// the constructor however has an optional rx buffer size.
|
||||
// Speed up to 115200 can be used.
|
||||
|
||||
|
||||
class ESPeasySoftwareSerial : public Stream
|
||||
{
|
||||
public:
|
||||
ESPeasySoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false, uint16_t buffSize = 64);
|
||||
virtual ~ESPeasySoftwareSerial();
|
||||
|
||||
void begin(long speed);
|
||||
void setTransmitEnablePin(uint8_t transmitEnablePin);
|
||||
|
||||
int peek();
|
||||
|
||||
virtual size_t write(uint8_t byte);
|
||||
virtual int read();
|
||||
virtual int available();
|
||||
virtual void flush();
|
||||
operator bool() {return m_rxValid || m_txValid;}
|
||||
|
||||
// Disable or enable interrupts on the rx pin
|
||||
void enableRx(bool on);
|
||||
|
||||
void rxRead();
|
||||
|
||||
using Print::write;
|
||||
|
||||
private:
|
||||
bool isValidGPIOpin(uint8_t pin);
|
||||
uint8_t pinToIndex(uint8_t pin);
|
||||
|
||||
// Member variables
|
||||
uint8_t m_rxPin, m_txPin, m_txEnablePin;
|
||||
bool m_rxValid, m_txValid, m_txEnableValid;
|
||||
bool m_invert;
|
||||
unsigned long m_bitTime;
|
||||
uint16_t m_inPos, m_outPos;
|
||||
uint16_t m_buffSize;
|
||||
uint8_t *m_buffer;
|
||||
|
||||
};
|
||||
|
||||
// If only one tx or rx wanted then use this as parameter for the unused pin
|
||||
#define SW_SERIAL_UNUSED_PIN -1
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
# EspESPeasySoftwareSerial
|
||||
|
||||
Implementation of the Arduino software serial library for the ESP8266
|
||||
|
||||
Same functionality as the corresponding AVR library but several instances can be active at the same time.
|
||||
Speed up to 115200 baud is supported. The constructor also has an optional input buffer size.
|
||||
|
||||
Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt
|
||||
timings. This may lead to bit errors when having heavy data traffic in high baud rates.
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
ESPeasySoftwareSerial swSer(14, 12, false, 256);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
swSer.begin(115200);
|
||||
|
||||
Serial.println("\nSoftware serial test started");
|
||||
|
||||
for (char ch = ' '; ch <= 'z'; ch++) {
|
||||
swSer.write(ch);
|
||||
}
|
||||
swSer.println("");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (swSer.available() > 0) {
|
||||
Serial.write(swSer.read());
|
||||
}
|
||||
while (Serial.available() > 0) {
|
||||
swSer.write(Serial.read());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for ESPeasySoftwareSerial
|
||||
# (esp8266)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ESPeasySoftwareSerial KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
read KEYWORD2
|
||||
write KEYWORD2
|
||||
available KEYWORD2
|
||||
flush KEYWORD2
|
||||
overflow KEYWORD2
|
||||
peek KEYWORD2
|
||||
listen KEYWORD2
|
||||
end KEYWORD2
|
||||
isListening KEYWORD2
|
||||
stopListening KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "EspESPeasySoftwareSerial",
|
||||
"version": "3.3.1",
|
||||
"keywords": [
|
||||
"serial", "io", "softwareserial"
|
||||
],
|
||||
"description": "Implementation of the Arduino software serial for ESP8266. Adjusted to reduce memory footprint for ESPeasy",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/plerup/espsoftwareserial"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif8266"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=ESPeasySoftwareSerial
|
||||
version=1.0
|
||||
author=Peter Lerup
|
||||
maintainer=Peter Lerup <peter@lerup.com>
|
||||
sentence=Implementation of the Arduino software serial for ESP8266.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=
|
||||
architectures=esp8266
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
License Information
|
||||
-------------------
|
||||
|
||||
The hardware is released under [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/).
|
||||
|
||||
All other code is open source so please feel free to do anything you want with it; you buy me a beer if you use this and we meet someday ([Beerware license](http://en.wikipedia.org/wiki/Beerware)).
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
SparkFun APDS9960 RGB and Gesture Sensor Arduino Library
|
||||
=========================================================
|
||||
|
||||

|
||||
|
||||
[*Avago APDS-9960 Breakout Board (SEN-12787)*](https://www.sparkfun.com/products/12787)
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
* Download the Git repository as a ZIP ("Download ZIP" button)
|
||||
* Unzip
|
||||
* Copy the entire library directory (APDS-9960_RGB_and_Gesture_Sensor_Arduino_Library
|
||||
) to \<Arduino installation directory\>/libraries
|
||||
* Open the Arduino program
|
||||
* Select File -> Examples -> SparkFun_APDS9960 -> GestureTest
|
||||
* Plug in your Arduino and APDS-9960 with the following connections
|
||||
|
||||
*-OR-*
|
||||
|
||||
* Use the library manager
|
||||
|
||||
| Arduino Pin | APDS-9960 Board | Function |
|
||||
|---|---|---|
|
||||
| 3.3V | VCC | Power |
|
||||
| GND | GND | Ground |
|
||||
| A4 | SDA | I2C Data |
|
||||
| A5 | SCL | I2C Clock |
|
||||
| 2 | INT | Interrupt |
|
||||
|
||||
* Go to Tools -> Board and select your Arduino board
|
||||
* Go to Tools -> Serial Port and select the COM port of your Arduino board
|
||||
* Click "Upload"
|
||||
* Go to Tools -> Serial Monitor
|
||||
* Ensure the baud rate is set at 9600 baud
|
||||
* Swipe your hand over the sensor in various directions!
|
||||
|
||||
Repository Contents
|
||||
-------------------
|
||||
|
||||
* **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE.
|
||||
* **/src** - Source files for the library (.cpp, .h).
|
||||
* **library.properties** - General library properties for the Arduino package manager.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
* **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library.
|
||||
* **[Product Repository](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor)** - Main repository (including hardware files) for the SparkFun_APDS9960 RGB and Gesture Sensor.
|
||||
* **[Hookup Guide](https://learn.sparkfun.com/tutorials/apds-9960-rgb-and-gesture-sensor-hookup-guide)** - Basic hookup guide for the sensor.
|
||||
|
||||
Products that use this Library
|
||||
---------------------------------
|
||||
|
||||
* [SEN-12787](https://www.sparkfun.com/products/12787)- Avago APDS-9960
|
||||
|
||||
Version History
|
||||
---------------
|
||||
* [V_1.4.1](https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library/tree/V_1.4.1) - Removing blank files, updating library.properties file.
|
||||
* [V_1.4.0](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor_Arduino_Library/tree/V_1.4.0) - Updated to new library structure
|
||||
* V_1.3.0 - Implemented disableProximitySensor(). Thanks to jmg5150 for catching that!
|
||||
* V_1.2.0 - Added pinMode line to GestureTest demo to fix interrupt bug with some Arduinos
|
||||
* V_1.1.0 - Updated GestureTest demo to not freeze with fast swipes
|
||||
* V_1.0.0: Initial release
|
||||
* Ambient and RGB light sensing implemented
|
||||
* Ambient light interrupts working
|
||||
* Proximity sensing implemented
|
||||
* Proximity interrupts working
|
||||
* Gesture (UP, DOWN, LEFT, RIGHT, NEAR, FAR) sensing implemented
|
||||
|
||||
License Information
|
||||
-------------------
|
||||
|
||||
This product is _**open source**_!
|
||||
|
||||
The **code** is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round!
|
||||
|
||||
Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release anything derivative under the same license.
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
|
||||
- Your friends at SparkFun.
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/****************************************************************
|
||||
AmbientLightInterrupt.ino
|
||||
APDS-9960 RGB and Gesture Sensor
|
||||
Shawn Hymel @ SparkFun Electronics
|
||||
October 24, 2014
|
||||
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
|
||||
|
||||
Tests the ambient light interrupt abilities of the APDS-9960.
|
||||
Configures the APDS-9960 over I2C and waits for an external
|
||||
interrupt based on high or low light conditions. Try covering
|
||||
the sensor with your hand or bringing the sensor close to a
|
||||
bright light source. You might need to adjust the LIGHT_INT_HIGH
|
||||
and LIGHT_INT_LOW values to get the interrupt to work correctly.
|
||||
|
||||
Hardware Connections:
|
||||
|
||||
IMPORTANT: The APDS-9960 can only accept 3.3V!
|
||||
|
||||
Arduino Pin APDS-9960 Board Function
|
||||
|
||||
3.3V VCC Power
|
||||
GND GND Ground
|
||||
A4 SDA I2C Data
|
||||
A5 SCL I2C Clock
|
||||
2 INT Interrupt
|
||||
13 - LED
|
||||
|
||||
Resources:
|
||||
Include Wire.h and SparkFun_APDS-9960.h
|
||||
|
||||
Development environment specifics:
|
||||
Written in Arduino 1.0.5
|
||||
Tested with SparkFun Arduino Pro Mini 3.3V
|
||||
|
||||
This code is beerware; if you see me (or any other SparkFun
|
||||
employee) at the local, and you've found our code helpful, please
|
||||
buy us a round!
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
****************************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SparkFun_APDS9960.h>
|
||||
|
||||
// Pins
|
||||
#define APDS9960_INT 2 // Needs to be an interrupt pin
|
||||
#define LED_PIN 13 // LED for showing interrupt
|
||||
|
||||
// Constants
|
||||
#define LIGHT_INT_HIGH 1000 // High light level for interrupt
|
||||
#define LIGHT_INT_LOW 10 // Low light level for interrupt
|
||||
|
||||
// Global variables
|
||||
SparkFun_APDS9960 apds = SparkFun_APDS9960();
|
||||
uint16_t ambient_light = 0;
|
||||
uint16_t red_light = 0;
|
||||
uint16_t green_light = 0;
|
||||
uint16_t blue_light = 0;
|
||||
int isr_flag = 0;
|
||||
uint16_t threshold = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Set LED as output
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(APDS9960_INT, INPUT);
|
||||
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("-------------------------------------"));
|
||||
Serial.println(F("SparkFun APDS-9960 - Light Interrupts"));
|
||||
Serial.println(F("-------------------------------------"));
|
||||
|
||||
// Initialize interrupt service routine
|
||||
attachInterrupt(0, interruptRoutine, FALLING);
|
||||
|
||||
// Initialize APDS-9960 (configure I2C and initial values)
|
||||
if ( apds.init() ) {
|
||||
Serial.println(F("APDS-9960 initialization complete"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during APDS-9960 init!"));
|
||||
}
|
||||
|
||||
// Set high and low interrupt thresholds
|
||||
if ( !apds.setLightIntLowThreshold(LIGHT_INT_LOW) ) {
|
||||
Serial.println(F("Error writing low threshold"));
|
||||
}
|
||||
if ( !apds.setLightIntHighThreshold(LIGHT_INT_HIGH) ) {
|
||||
Serial.println(F("Error writing high threshold"));
|
||||
}
|
||||
|
||||
// Start running the APDS-9960 light sensor (no interrupts)
|
||||
if ( apds.enableLightSensor(false) ) {
|
||||
Serial.println(F("Light sensor is now running"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during light sensor init!"));
|
||||
}
|
||||
|
||||
// Read high and low interrupt thresholds
|
||||
if ( !apds.getLightIntLowThreshold(threshold) ) {
|
||||
Serial.println(F("Error reading low threshold"));
|
||||
} else {
|
||||
Serial.print(F("Low Threshold: "));
|
||||
Serial.println(threshold);
|
||||
}
|
||||
if ( !apds.getLightIntHighThreshold(threshold) ) {
|
||||
Serial.println(F("Error reading high threshold"));
|
||||
} else {
|
||||
Serial.print(F("High Threshold: "));
|
||||
Serial.println(threshold);
|
||||
}
|
||||
|
||||
// Enable interrupts
|
||||
if ( !apds.setAmbientLightIntEnable(1) ) {
|
||||
Serial.println(F("Error enabling interrupts"));
|
||||
}
|
||||
|
||||
// Wait for initialization and calibration to finish
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// If interrupt occurs, print out the light levels
|
||||
if ( isr_flag == 1 ) {
|
||||
|
||||
// Read the light levels (ambient, red, green, blue) and print
|
||||
if ( !apds.readAmbientLight(ambient_light) ||
|
||||
!apds.readRedLight(red_light) ||
|
||||
!apds.readGreenLight(green_light) ||
|
||||
!apds.readBlueLight(blue_light) ) {
|
||||
Serial.println("Error reading light values");
|
||||
} else {
|
||||
Serial.print("Interrupt! Ambient: ");
|
||||
Serial.print(ambient_light);
|
||||
Serial.print(" R: ");
|
||||
Serial.print(red_light);
|
||||
Serial.print(" G: ");
|
||||
Serial.print(green_light);
|
||||
Serial.print(" B: ");
|
||||
Serial.println(blue_light);
|
||||
}
|
||||
|
||||
// Turn on LED for a half a second
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
// Reset flag and clear APDS-9960 interrupt (IMPORTANT!)
|
||||
isr_flag = 0;
|
||||
if ( !apds.clearAmbientLightInt() ) {
|
||||
Serial.println("Error clearing interrupt");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void interruptRoutine() {
|
||||
isr_flag = 1;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/****************************************************************
|
||||
ColorSensor.ino
|
||||
APDS-9960 RGB and Gesture Sensor
|
||||
Shawn Hymel @ SparkFun Electronics
|
||||
October 15, 2014
|
||||
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
|
||||
|
||||
Tests the color and ambient light sensing abilities of the
|
||||
APDS-9960. Configures APDS-9960 over I2C and polls the sensor for
|
||||
ambient light and color levels, which are displayed over the
|
||||
serial console.
|
||||
|
||||
Hardware Connections:
|
||||
|
||||
IMPORTANT: The APDS-9960 can only accept 3.3V!
|
||||
|
||||
Arduino Pin APDS-9960 Board Function
|
||||
|
||||
3.3V VCC Power
|
||||
GND GND Ground
|
||||
A4 SDA I2C Data
|
||||
A5 SCL I2C Clock
|
||||
|
||||
Resources:
|
||||
Include Wire.h and SparkFun_APDS-9960.h
|
||||
|
||||
Development environment specifics:
|
||||
Written in Arduino 1.0.5
|
||||
Tested with SparkFun Arduino Pro Mini 3.3V
|
||||
|
||||
This code is beerware; if you see me (or any other SparkFun
|
||||
employee) at the local, and you've found our code helpful, please
|
||||
buy us a round!
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
****************************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SparkFun_APDS9960.h>
|
||||
|
||||
// Global Variables
|
||||
SparkFun_APDS9960 apds = SparkFun_APDS9960();
|
||||
uint16_t ambient_light = 0;
|
||||
uint16_t red_light = 0;
|
||||
uint16_t green_light = 0;
|
||||
uint16_t blue_light = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("--------------------------------"));
|
||||
Serial.println(F("SparkFun APDS-9960 - ColorSensor"));
|
||||
Serial.println(F("--------------------------------"));
|
||||
|
||||
// Initialize APDS-9960 (configure I2C and initial values)
|
||||
if ( apds.init() ) {
|
||||
Serial.println(F("APDS-9960 initialization complete"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during APDS-9960 init!"));
|
||||
}
|
||||
|
||||
// Start running the APDS-9960 light sensor (no interrupts)
|
||||
if ( apds.enableLightSensor(false) ) {
|
||||
Serial.println(F("Light sensor is now running"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during light sensor init!"));
|
||||
}
|
||||
|
||||
// Wait for initialization and calibration to finish
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Read the light levels (ambient, red, green, blue)
|
||||
if ( !apds.readAmbientLight(ambient_light) ||
|
||||
!apds.readRedLight(red_light) ||
|
||||
!apds.readGreenLight(green_light) ||
|
||||
!apds.readBlueLight(blue_light) ) {
|
||||
Serial.println("Error reading light values");
|
||||
} else {
|
||||
Serial.print("Ambient: ");
|
||||
Serial.print(ambient_light);
|
||||
Serial.print(" Red: ");
|
||||
Serial.print(red_light);
|
||||
Serial.print(" Green: ");
|
||||
Serial.print(green_light);
|
||||
Serial.print(" Blue: ");
|
||||
Serial.println(blue_light);
|
||||
}
|
||||
|
||||
// Wait 1 second before next reading
|
||||
delay(1000);
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/****************************************************************
|
||||
GestureTest.ino
|
||||
APDS-9960 RGB and Gesture Sensor
|
||||
Shawn Hymel @ SparkFun Electronics
|
||||
May 30, 2014
|
||||
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
|
||||
|
||||
Tests the gesture sensing abilities of the APDS-9960. Configures
|
||||
APDS-9960 over I2C and waits for gesture events. Calculates the
|
||||
direction of the swipe (up, down, left, right) and displays it
|
||||
on a serial console.
|
||||
|
||||
To perform a NEAR gesture, hold your hand
|
||||
far above the sensor and move it close to the sensor (within 2
|
||||
inches). Hold your hand there for at least 1 second and move it
|
||||
away.
|
||||
|
||||
To perform a FAR gesture, hold your hand within 2 inches of the
|
||||
sensor for at least 1 second and then move it above (out of
|
||||
range) of the sensor.
|
||||
|
||||
Hardware Connections:
|
||||
|
||||
IMPORTANT: The APDS-9960 can only accept 3.3V!
|
||||
|
||||
Arduino Pin APDS-9960 Board Function
|
||||
|
||||
3.3V VCC Power
|
||||
GND GND Ground
|
||||
A4 SDA I2C Data
|
||||
A5 SCL I2C Clock
|
||||
2 INT Interrupt
|
||||
|
||||
Resources:
|
||||
Include Wire.h and SparkFun_APDS-9960.h
|
||||
|
||||
Development environment specifics:
|
||||
Written in Arduino 1.0.5
|
||||
Tested with SparkFun Arduino Pro Mini 3.3V
|
||||
|
||||
This code is beerware; if you see me (or any other SparkFun
|
||||
employee) at the local, and you've found our code helpful, please
|
||||
buy us a round!
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
****************************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SparkFun_APDS9960.h>
|
||||
|
||||
// Pins
|
||||
#define APDS9960_INT 2 // Needs to be an interrupt pin
|
||||
|
||||
// Constants
|
||||
|
||||
// Global Variables
|
||||
SparkFun_APDS9960 apds = SparkFun_APDS9960();
|
||||
int isr_flag = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Set interrupt pin as input
|
||||
pinMode(APDS9960_INT, INPUT);
|
||||
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("--------------------------------"));
|
||||
Serial.println(F("SparkFun APDS-9960 - GestureTest"));
|
||||
Serial.println(F("--------------------------------"));
|
||||
|
||||
// Initialize interrupt service routine
|
||||
attachInterrupt(0, interruptRoutine, FALLING);
|
||||
|
||||
// Initialize APDS-9960 (configure I2C and initial values)
|
||||
if ( apds.init() ) {
|
||||
Serial.println(F("APDS-9960 initialization complete"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during APDS-9960 init!"));
|
||||
}
|
||||
|
||||
// Start running the APDS-9960 gesture sensor engine
|
||||
if ( apds.enableGestureSensor(true) ) {
|
||||
Serial.println(F("Gesture sensor is now running"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during gesture sensor init!"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if( isr_flag == 1 ) {
|
||||
detachInterrupt(0);
|
||||
handleGesture();
|
||||
isr_flag = 0;
|
||||
attachInterrupt(0, interruptRoutine, FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
void interruptRoutine() {
|
||||
isr_flag = 1;
|
||||
}
|
||||
|
||||
void handleGesture() {
|
||||
if ( apds.isGestureAvailable() ) {
|
||||
switch ( apds.readGesture() ) {
|
||||
case DIR_UP:
|
||||
Serial.println("UP");
|
||||
break;
|
||||
case DIR_DOWN:
|
||||
Serial.println("DOWN");
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
Serial.println("LEFT");
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
Serial.println("RIGHT");
|
||||
break;
|
||||
case DIR_NEAR:
|
||||
Serial.println("NEAR");
|
||||
break;
|
||||
case DIR_FAR:
|
||||
Serial.println("FAR");
|
||||
break;
|
||||
default:
|
||||
Serial.println("NONE");
|
||||
}
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/****************************************************************
|
||||
ProximityInterrupt.ino
|
||||
APDS-9960 RGB and Gesture Sensor
|
||||
Shawn Hymel @ SparkFun Electronics
|
||||
October 24, 2014
|
||||
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
|
||||
|
||||
Tests the proximity interrupt abilities of the APDS-9960.
|
||||
Configures the APDS-9960 over I2C and waits for an external
|
||||
interrupt based on high or low proximity conditions. Move your
|
||||
hand near the sensor and watch the LED on pin 13.
|
||||
|
||||
Hardware Connections:
|
||||
|
||||
IMPORTANT: The APDS-9960 can only accept 3.3V!
|
||||
|
||||
Arduino Pin APDS-9960 Board Function
|
||||
|
||||
3.3V VCC Power
|
||||
GND GND Ground
|
||||
A4 SDA I2C Data
|
||||
A5 SCL I2C Clock
|
||||
2 INT Interrupt
|
||||
13 - LED
|
||||
|
||||
Resources:
|
||||
Include Wire.h and SparkFun_APDS-9960.h
|
||||
|
||||
Development environment specifics:
|
||||
Written in Arduino 1.0.5
|
||||
Tested with SparkFun Arduino Pro Mini 3.3V
|
||||
|
||||
This code is beerware; if you see me (or any other SparkFun
|
||||
employee) at the local, and you've found our code helpful, please
|
||||
buy us a round!
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
****************************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SparkFun_APDS9960.h>
|
||||
|
||||
// Pins
|
||||
#define APDS9960_INT 2 // Needs to be an interrupt pin
|
||||
#define LED_PIN 13 // LED for showing interrupt
|
||||
|
||||
// Constants
|
||||
#define PROX_INT_HIGH 50 // Proximity level for interrupt
|
||||
#define PROX_INT_LOW 0 // No far interrupt
|
||||
|
||||
// Global variables
|
||||
SparkFun_APDS9960 apds = SparkFun_APDS9960();
|
||||
uint8_t proximity_data = 0;
|
||||
int isr_flag = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Set LED as output
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(APDS9960_INT, INPUT);
|
||||
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("---------------------------------------"));
|
||||
Serial.println(F("SparkFun APDS-9960 - ProximityInterrupt"));
|
||||
Serial.println(F("---------------------------------------"));
|
||||
|
||||
// Initialize interrupt service routine
|
||||
attachInterrupt(0, interruptRoutine, FALLING);
|
||||
|
||||
// Initialize APDS-9960 (configure I2C and initial values)
|
||||
if ( apds.init() ) {
|
||||
Serial.println(F("APDS-9960 initialization complete"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during APDS-9960 init!"));
|
||||
}
|
||||
|
||||
// Adjust the Proximity sensor gain
|
||||
if ( !apds.setProximityGain(PGAIN_2X) ) {
|
||||
Serial.println(F("Something went wrong trying to set PGAIN"));
|
||||
}
|
||||
|
||||
// Set proximity interrupt thresholds
|
||||
if ( !apds.setProximityIntLowThreshold(PROX_INT_LOW) ) {
|
||||
Serial.println(F("Error writing low threshold"));
|
||||
}
|
||||
if ( !apds.setProximityIntHighThreshold(PROX_INT_HIGH) ) {
|
||||
Serial.println(F("Error writing high threshold"));
|
||||
}
|
||||
|
||||
// Start running the APDS-9960 proximity sensor (interrupts)
|
||||
if ( apds.enableProximitySensor(true) ) {
|
||||
Serial.println(F("Proximity sensor is now running"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during sensor init!"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// If interrupt occurs, print out the proximity level
|
||||
if ( isr_flag == 1 ) {
|
||||
|
||||
// Read proximity level and print it out
|
||||
if ( !apds.readProximity(proximity_data) ) {
|
||||
Serial.println("Error reading proximity value");
|
||||
} else {
|
||||
Serial.print("Proximity detected! Level: ");
|
||||
Serial.println(proximity_data);
|
||||
}
|
||||
|
||||
// Turn on LED for a half a second
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
// Reset flag and clear APDS-9960 interrupt (IMPORTANT!)
|
||||
isr_flag = 0;
|
||||
if ( !apds.clearProximityInt() ) {
|
||||
Serial.println("Error clearing interrupt");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void interruptRoutine() {
|
||||
isr_flag = 1;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/****************************************************************
|
||||
ProximityTest.ino
|
||||
APDS-9960 RGB and Gesture Sensor
|
||||
Shawn Hymel @ SparkFun Electronics
|
||||
October 28, 2014
|
||||
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
|
||||
|
||||
Tests the proximity sensing abilities of the APDS-9960.
|
||||
Configures the APDS-9960 over I2C and polls for the distance to
|
||||
the object nearest the sensor.
|
||||
|
||||
Hardware Connections:
|
||||
|
||||
IMPORTANT: The APDS-9960 can only accept 3.3V!
|
||||
|
||||
Arduino Pin APDS-9960 Board Function
|
||||
|
||||
3.3V VCC Power
|
||||
GND GND Ground
|
||||
A4 SDA I2C Data
|
||||
A5 SCL I2C Clock
|
||||
|
||||
Resources:
|
||||
Include Wire.h and SparkFun_APDS-9960.h
|
||||
|
||||
Development environment specifics:
|
||||
Written in Arduino 1.0.5
|
||||
Tested with SparkFun Arduino Pro Mini 3.3V
|
||||
|
||||
This code is beerware; if you see me (or any other SparkFun
|
||||
employee) at the local, and you've found our code helpful, please
|
||||
buy us a round!
|
||||
|
||||
Distributed as-is; no warranty is given.
|
||||
****************************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SparkFun_APDS9960.h>
|
||||
|
||||
// Global Variables
|
||||
SparkFun_APDS9960 apds = SparkFun_APDS9960();
|
||||
uint8_t proximity_data = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F("SparkFun APDS-9960 - ProximitySensor"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
|
||||
// Initialize APDS-9960 (configure I2C and initial values)
|
||||
if ( apds.init() ) {
|
||||
Serial.println(F("APDS-9960 initialization complete"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during APDS-9960 init!"));
|
||||
}
|
||||
|
||||
// Adjust the Proximity sensor gain
|
||||
if ( !apds.setProximityGain(PGAIN_2X) ) {
|
||||
Serial.println(F("Something went wrong trying to set PGAIN"));
|
||||
}
|
||||
|
||||
// Start running the APDS-9960 proximity sensor (no interrupts)
|
||||
if ( apds.enableProximitySensor(false) ) {
|
||||
Serial.println(F("Proximity sensor is now running"));
|
||||
} else {
|
||||
Serial.println(F("Something went wrong during sensor init!"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Read the proximity value
|
||||
if ( !apds.readProximity(proximity_data) ) {
|
||||
Serial.println("Error reading proximity value");
|
||||
} else {
|
||||
Serial.print("Proximity: ");
|
||||
Serial.println(proximity_data);
|
||||
}
|
||||
|
||||
// Wait 250 ms before next reading
|
||||
delay(250);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=SparkFun APDS9960 RGB and Gesture Sensor
|
||||
version=1.4.2
|
||||
author=SparkFun Electronics <techsupport@sparkfun.com>
|
||||
maintainer=SparkFun Electronics <sparkfun.com>
|
||||
sentence=Library for the Avago APDS-9960 sensor
|
||||
paragraph=This library works with the SparkFun Breakout board for the Avago APDS-9960 proximity, light, RGB, and gesture sensor, made by SparkFun Electronics.
|
||||
category=Sensors
|
||||
url=https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library
|
||||
architectures=*
|
||||
@@ -0,0 +1,5 @@
|
||||
This folder should contain the .cpp and .h files for the library.
|
||||
|
||||
If backward compatibility is needed, source code should be placed in the library root folder and in a "utilyt" folder.
|
||||
|
||||
Check out the [library specification](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification) for more details.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
* @file SparkFun_APDS-9960.h
|
||||
* @brief Library for the SparkFun APDS-9960 breakout board
|
||||
* @author Shawn Hymel (SparkFun Electronics)
|
||||
*
|
||||
* @copyright This code is public domain but you buy me a beer if you use
|
||||
* this and we meet someday (Beerware license).
|
||||
*
|
||||
* This library interfaces the Avago APDS-9960 to Arduino over I2C. The library
|
||||
* relies on the Arduino Wire (I2C) library. to use the library, instantiate an
|
||||
* APDS9960 object, call init(), and call the appropriate functions.
|
||||
*/
|
||||
|
||||
#ifndef SparkFun_APDS9960_H
|
||||
#define SparkFun_APDS9960_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/* Debug */
|
||||
#define DEBUG 0
|
||||
|
||||
/* APDS-9960 I2C address */
|
||||
#define APDS9960_I2C_ADDR 0x39
|
||||
|
||||
/* Gesture parameters */
|
||||
#define GESTURE_THRESHOLD_OUT 10
|
||||
#define GESTURE_SENSITIVITY_1 50
|
||||
#define GESTURE_SENSITIVITY_2 20
|
||||
|
||||
/* Error code for returned values */
|
||||
#define ERROR 0xFF
|
||||
|
||||
/* Acceptable device IDs */
|
||||
#define APDS9960_ID_1 0xAB
|
||||
#define APDS9960_ID_2 0x9C
|
||||
|
||||
/* Misc parameters */
|
||||
#define FIFO_PAUSE_TIME 30 // Wait period (ms) between FIFO reads
|
||||
|
||||
/* APDS-9960 register addresses */
|
||||
#define APDS9960_ENABLE 0x80
|
||||
#define APDS9960_ATIME 0x81
|
||||
#define APDS9960_WTIME 0x83
|
||||
#define APDS9960_AILTL 0x84
|
||||
#define APDS9960_AILTH 0x85
|
||||
#define APDS9960_AIHTL 0x86
|
||||
#define APDS9960_AIHTH 0x87
|
||||
#define APDS9960_PILT 0x89
|
||||
#define APDS9960_PIHT 0x8B
|
||||
#define APDS9960_PERS 0x8C
|
||||
#define APDS9960_CONFIG1 0x8D
|
||||
#define APDS9960_PPULSE 0x8E
|
||||
#define APDS9960_CONTROL 0x8F
|
||||
#define APDS9960_CONFIG2 0x90
|
||||
#define APDS9960_ID 0x92
|
||||
#define APDS9960_STATUS 0x93
|
||||
#define APDS9960_CDATAL 0x94
|
||||
#define APDS9960_CDATAH 0x95
|
||||
#define APDS9960_RDATAL 0x96
|
||||
#define APDS9960_RDATAH 0x97
|
||||
#define APDS9960_GDATAL 0x98
|
||||
#define APDS9960_GDATAH 0x99
|
||||
#define APDS9960_BDATAL 0x9A
|
||||
#define APDS9960_BDATAH 0x9B
|
||||
#define APDS9960_PDATA 0x9C
|
||||
#define APDS9960_POFFSET_UR 0x9D
|
||||
#define APDS9960_POFFSET_DL 0x9E
|
||||
#define APDS9960_CONFIG3 0x9F
|
||||
#define APDS9960_GPENTH 0xA0
|
||||
#define APDS9960_GEXTH 0xA1
|
||||
#define APDS9960_GCONF1 0xA2
|
||||
#define APDS9960_GCONF2 0xA3
|
||||
#define APDS9960_GOFFSET_U 0xA4
|
||||
#define APDS9960_GOFFSET_D 0xA5
|
||||
#define APDS9960_GOFFSET_L 0xA7
|
||||
#define APDS9960_GOFFSET_R 0xA9
|
||||
#define APDS9960_GPULSE 0xA6
|
||||
#define APDS9960_GCONF3 0xAA
|
||||
#define APDS9960_GCONF4 0xAB
|
||||
#define APDS9960_GFLVL 0xAE
|
||||
#define APDS9960_GSTATUS 0xAF
|
||||
#define APDS9960_IFORCE 0xE4
|
||||
#define APDS9960_PICLEAR 0xE5
|
||||
#define APDS9960_CICLEAR 0xE6
|
||||
#define APDS9960_AICLEAR 0xE7
|
||||
#define APDS9960_GFIFO_U 0xFC
|
||||
#define APDS9960_GFIFO_D 0xFD
|
||||
#define APDS9960_GFIFO_L 0xFE
|
||||
#define APDS9960_GFIFO_R 0xFF
|
||||
|
||||
/* Bit fields */
|
||||
#define APDS9960_PON 0b00000001
|
||||
#define APDS9960_AEN 0b00000010
|
||||
#define APDS9960_PEN 0b00000100
|
||||
#define APDS9960_WEN 0b00001000
|
||||
#define APSD9960_AIEN 0b00010000
|
||||
#define APDS9960_PIEN 0b00100000
|
||||
#define APDS9960_GEN 0b01000000
|
||||
#define APDS9960_GVALID 0b00000001
|
||||
|
||||
/* On/Off definitions */
|
||||
#define OFF 0
|
||||
#define ON 1
|
||||
|
||||
/* Acceptable parameters for setMode */
|
||||
#define POWER 0
|
||||
#define AMBIENT_LIGHT 1
|
||||
#define PROXIMITY 2
|
||||
#define WAIT 3
|
||||
#define AMBIENT_LIGHT_INT 4
|
||||
#define PROXIMITY_INT 5
|
||||
#define GESTURE 6
|
||||
#define ALL 7
|
||||
|
||||
/* LED Drive values */
|
||||
#define LED_DRIVE_100MA 0
|
||||
#define LED_DRIVE_50MA 1
|
||||
#define LED_DRIVE_25MA 2
|
||||
#define LED_DRIVE_12_5MA 3
|
||||
|
||||
/* Proximity Gain (PGAIN) values */
|
||||
#define PGAIN_1X 0
|
||||
#define PGAIN_2X 1
|
||||
#define PGAIN_4X 2
|
||||
#define PGAIN_8X 3
|
||||
|
||||
/* ALS Gain (AGAIN) values */
|
||||
#define AGAIN_1X 0
|
||||
#define AGAIN_4X 1
|
||||
#define AGAIN_16X 2
|
||||
#define AGAIN_64X 3
|
||||
|
||||
/* Gesture Gain (GGAIN) values */
|
||||
#define GGAIN_1X 0
|
||||
#define GGAIN_2X 1
|
||||
#define GGAIN_4X 2
|
||||
#define GGAIN_8X 3
|
||||
|
||||
/* LED Boost values */
|
||||
#define LED_BOOST_100 0
|
||||
#define LED_BOOST_150 1
|
||||
#define LED_BOOST_200 2
|
||||
#define LED_BOOST_300 3
|
||||
|
||||
/* Gesture wait time values */
|
||||
#define GWTIME_0MS 0
|
||||
#define GWTIME_2_8MS 1
|
||||
#define GWTIME_5_6MS 2
|
||||
#define GWTIME_8_4MS 3
|
||||
#define GWTIME_14_0MS 4
|
||||
#define GWTIME_22_4MS 5
|
||||
#define GWTIME_30_8MS 6
|
||||
#define GWTIME_39_2MS 7
|
||||
|
||||
/* Default values */
|
||||
#define DEFAULT_ATIME 219 // 103ms
|
||||
#define DEFAULT_WTIME 246 // 27ms
|
||||
#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses
|
||||
#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses
|
||||
#define DEFAULT_POFFSET_UR 0 // 0 offset
|
||||
#define DEFAULT_POFFSET_DL 0 // 0 offset
|
||||
#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor
|
||||
#define DEFAULT_LDRIVE LED_DRIVE_100MA
|
||||
#define DEFAULT_PGAIN PGAIN_4X
|
||||
#define DEFAULT_AGAIN AGAIN_4X
|
||||
#define DEFAULT_PILT 0 // Low proximity threshold
|
||||
#define DEFAULT_PIHT 50 // High proximity threshold
|
||||
#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration
|
||||
#define DEFAULT_AIHT 0
|
||||
#define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int.
|
||||
#define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost
|
||||
#define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI
|
||||
#define DEFAULT_GPENTH 40 // Threshold for entering gesture mode
|
||||
#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode
|
||||
#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit
|
||||
#define DEFAULT_GGAIN GGAIN_4X
|
||||
#define DEFAULT_GLDRIVE LED_DRIVE_100MA
|
||||
#define DEFAULT_GWTIME GWTIME_2_8MS
|
||||
#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode
|
||||
#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses
|
||||
#define DEFAULT_GCONF3 0 // All photodiodes active during gesture
|
||||
#define DEFAULT_GIEN 0 // Disable gesture interrupts
|
||||
|
||||
/* Direction definitions */
|
||||
enum {
|
||||
DIR_NONE,
|
||||
DIR_LEFT,
|
||||
DIR_RIGHT,
|
||||
DIR_UP,
|
||||
DIR_DOWN,
|
||||
DIR_NEAR,
|
||||
DIR_FAR,
|
||||
DIR_ALL
|
||||
};
|
||||
|
||||
/* State definitions */
|
||||
|
||||
enum {
|
||||
N_A_STATE, // NA_STATE - collision with ESP8266WiFi.h
|
||||
NEAR_STATE,
|
||||
FAR_STATE,
|
||||
ALL_STATE
|
||||
};
|
||||
|
||||
|
||||
/* Container for gesture data */
|
||||
typedef struct gesture_data_type {
|
||||
uint8_t u_data[32];
|
||||
uint8_t d_data[32];
|
||||
uint8_t l_data[32];
|
||||
uint8_t r_data[32];
|
||||
uint8_t index;
|
||||
uint8_t total_gestures;
|
||||
uint8_t in_threshold;
|
||||
uint8_t out_threshold;
|
||||
} gesture_data_type;
|
||||
|
||||
/* APDS9960 Class */
|
||||
class SparkFun_APDS9960 {
|
||||
public:
|
||||
|
||||
/* Initialization methods */
|
||||
SparkFun_APDS9960();
|
||||
~SparkFun_APDS9960();
|
||||
bool init();
|
||||
uint8_t getMode();
|
||||
bool setMode(uint8_t mode, uint8_t enable);
|
||||
|
||||
/* Turn the APDS-9960 on and off */
|
||||
bool enablePower();
|
||||
bool disablePower();
|
||||
|
||||
/* Enable or disable specific sensors */
|
||||
bool enableLightSensor(bool interrupts = false);
|
||||
bool disableLightSensor();
|
||||
bool enableProximitySensor(bool interrupts = false);
|
||||
bool disableProximitySensor();
|
||||
bool enableGestureSensor(bool interrupts = true);
|
||||
bool disableGestureSensor();
|
||||
|
||||
/* LED drive strength control */
|
||||
uint8_t getLEDDrive();
|
||||
bool setLEDDrive(uint8_t drive);
|
||||
uint8_t getGestureLEDDrive();
|
||||
bool setGestureLEDDrive(uint8_t drive);
|
||||
|
||||
/* Gain control */
|
||||
uint8_t getAmbientLightGain();
|
||||
bool setAmbientLightGain(uint8_t gain);
|
||||
uint8_t getProximityGain();
|
||||
bool setProximityGain(uint8_t gain);
|
||||
uint8_t getGestureGain();
|
||||
bool setGestureGain(uint8_t gain);
|
||||
|
||||
/* Get and set light interrupt thresholds */
|
||||
bool getLightIntLowThreshold(uint16_t &threshold);
|
||||
bool setLightIntLowThreshold(uint16_t threshold);
|
||||
bool getLightIntHighThreshold(uint16_t &threshold);
|
||||
bool setLightIntHighThreshold(uint16_t threshold);
|
||||
|
||||
/* Get and set proximity interrupt thresholds */
|
||||
bool getProximityIntLowThreshold(uint8_t &threshold);
|
||||
bool setProximityIntLowThreshold(uint8_t threshold);
|
||||
bool getProximityIntHighThreshold(uint8_t &threshold);
|
||||
bool setProximityIntHighThreshold(uint8_t threshold);
|
||||
|
||||
/* Get and set interrupt enables */
|
||||
uint8_t getAmbientLightIntEnable();
|
||||
bool setAmbientLightIntEnable(uint8_t enable);
|
||||
uint8_t getProximityIntEnable();
|
||||
bool setProximityIntEnable(uint8_t enable);
|
||||
uint8_t getGestureIntEnable();
|
||||
bool setGestureIntEnable(uint8_t enable);
|
||||
|
||||
/* Clear interrupts */
|
||||
bool clearAmbientLightInt();
|
||||
bool clearProximityInt();
|
||||
|
||||
/* Ambient light methods */
|
||||
bool readAmbientLight(uint16_t &val);
|
||||
bool readRedLight(uint16_t &val);
|
||||
bool readGreenLight(uint16_t &val);
|
||||
bool readBlueLight(uint16_t &val);
|
||||
|
||||
/* Proximity methods */
|
||||
bool readProximity(uint8_t &val);
|
||||
|
||||
/* Gesture methods */
|
||||
bool isGestureAvailable();
|
||||
int readGesture();
|
||||
int readGestureNonBlocking();
|
||||
|
||||
private:
|
||||
|
||||
/* Gesture processing */
|
||||
void resetGestureParameters();
|
||||
bool processGestureData();
|
||||
bool decodeGesture();
|
||||
|
||||
/* Proximity Interrupt Threshold */
|
||||
uint8_t getProxIntLowThresh();
|
||||
bool setProxIntLowThresh(uint8_t threshold);
|
||||
uint8_t getProxIntHighThresh();
|
||||
bool setProxIntHighThresh(uint8_t threshold);
|
||||
|
||||
/* LED Boost Control */
|
||||
uint8_t getLEDBoost();
|
||||
bool setLEDBoost(uint8_t boost);
|
||||
|
||||
/* Proximity photodiode select */
|
||||
uint8_t getProxGainCompEnable();
|
||||
bool setProxGainCompEnable(uint8_t enable);
|
||||
uint8_t getProxPhotoMask();
|
||||
bool setProxPhotoMask(uint8_t mask);
|
||||
|
||||
/* Gesture threshold control */
|
||||
uint8_t getGestureEnterThresh();
|
||||
bool setGestureEnterThresh(uint8_t threshold);
|
||||
uint8_t getGestureExitThresh();
|
||||
bool setGestureExitThresh(uint8_t threshold);
|
||||
|
||||
/* Gesture LED, gain, and time control */
|
||||
uint8_t getGestureWaitTime();
|
||||
bool setGestureWaitTime(uint8_t time);
|
||||
|
||||
/* Gesture mode */
|
||||
uint8_t getGestureMode();
|
||||
bool setGestureMode(uint8_t mode);
|
||||
|
||||
/* Raw I2C Commands */
|
||||
bool wireWriteByte(uint8_t val);
|
||||
bool wireWriteDataByte(uint8_t reg, uint8_t val);
|
||||
bool wireWriteDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
|
||||
bool wireReadDataByte(uint8_t reg, uint8_t &val);
|
||||
int wireReadDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
|
||||
|
||||
/* Members */
|
||||
gesture_data_type gesture_data_;
|
||||
int gesture_ud_delta_;
|
||||
int gesture_lr_delta_;
|
||||
int gesture_ud_count_;
|
||||
int gesture_lr_count_;
|
||||
int gesture_near_count_;
|
||||
int gesture_far_count_;
|
||||
int gesture_state_;
|
||||
int gesture_motion_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,810 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
|
||||
bool OLEDDisplay::init() {
|
||||
if (!this->connect()) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
|
||||
return false;
|
||||
}
|
||||
this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
|
||||
if(!this->buffer) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
|
||||
if(!this->buffer_back) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n");
|
||||
free(this->buffer);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
sendInitCommands();
|
||||
resetDisplay();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OLEDDisplay::end() {
|
||||
if (this->buffer) free(this->buffer);
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
if (this->buffer_back) free(this->buffer_back);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OLEDDisplay::resetDisplay(void) {
|
||||
clear();
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
memset(buffer_back, 1, DISPLAY_BUFFER_SIZE);
|
||||
#endif
|
||||
display();
|
||||
}
|
||||
|
||||
void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setPixel(int16_t x, int16_t y) {
|
||||
if (x >= 0 && x < 128 && y >= 0 && y < 64) {
|
||||
switch (color) {
|
||||
case WHITE: buffer[x + (y / 8) * DISPLAY_WIDTH] |= (1 << (y & 7)); break;
|
||||
case BLACK: buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y & 7)); break;
|
||||
case INVERSE: buffer[x + (y / 8) * DISPLAY_WIDTH] ^= (1 << (y & 7)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bresenham's algorithm - thx wikipedia and Adafruit_GFX
|
||||
void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
|
||||
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
_swap_int16_t(x0, y0);
|
||||
_swap_int16_t(x1, y1);
|
||||
}
|
||||
|
||||
if (x0 > x1) {
|
||||
_swap_int16_t(x0, x1);
|
||||
_swap_int16_t(y0, y1);
|
||||
}
|
||||
|
||||
int16_t dx, dy;
|
||||
dx = x1 - x0;
|
||||
dy = abs(y1 - y0);
|
||||
|
||||
int16_t err = dx / 2;
|
||||
int16_t ystep;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
} else {
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
for (; x0<=x1; x0++) {
|
||||
if (steep) {
|
||||
setPixel(y0, x0);
|
||||
} else {
|
||||
setPixel(x0, y0);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawRect(int16_t x, int16_t y, int16_t width, int16_t height) {
|
||||
drawHorizontalLine(x, y, width);
|
||||
drawVerticalLine(x, y, height);
|
||||
drawVerticalLine(x + width - 1, y, height);
|
||||
drawHorizontalLine(x, y + height - 1, width);
|
||||
}
|
||||
|
||||
void OLEDDisplay::fillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height) {
|
||||
for (int16_t x = xMove; x < xMove + width; x++) {
|
||||
drawVerticalLine(x, yMove, height);
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) {
|
||||
int16_t x = 0, y = radius;
|
||||
int16_t dp = 1 - radius;
|
||||
do {
|
||||
if (dp < 0)
|
||||
dp = dp + 2 * (++x) + 3;
|
||||
else
|
||||
dp = dp + 2 * (++x) - 2 * (--y) + 5;
|
||||
|
||||
setPixel(x0 + x, y0 + y); //For the 8 octants
|
||||
setPixel(x0 - x, y0 + y);
|
||||
setPixel(x0 + x, y0 - y);
|
||||
setPixel(x0 - x, y0 - y);
|
||||
setPixel(x0 + y, y0 + x);
|
||||
setPixel(x0 - y, y0 + x);
|
||||
setPixel(x0 + y, y0 - x);
|
||||
setPixel(x0 - y, y0 - x);
|
||||
|
||||
} while (x < y);
|
||||
|
||||
setPixel(x0 + radius, y0);
|
||||
setPixel(x0, y0 + radius);
|
||||
setPixel(x0 - radius, y0);
|
||||
setPixel(x0, y0 - radius);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads) {
|
||||
int16_t x = 0, y = radius;
|
||||
int16_t dp = 1 - radius;
|
||||
while (x < y) {
|
||||
if (dp < 0)
|
||||
dp = dp + 2 * (++x) + 3;
|
||||
else
|
||||
dp = dp + 2 * (++x) - 2 * (--y) + 5;
|
||||
if (quads & 0x1) {
|
||||
setPixel(x0 + x, y0 - y);
|
||||
setPixel(x0 + y, y0 - x);
|
||||
}
|
||||
if (quads & 0x2) {
|
||||
setPixel(x0 - y, y0 - x);
|
||||
setPixel(x0 - x, y0 - y);
|
||||
}
|
||||
if (quads & 0x4) {
|
||||
setPixel(x0 - y, y0 + x);
|
||||
setPixel(x0 - x, y0 + y);
|
||||
}
|
||||
if (quads & 0x8) {
|
||||
setPixel(x0 + x, y0 + y);
|
||||
setPixel(x0 + y, y0 + x);
|
||||
}
|
||||
}
|
||||
if (quads & 0x1 && quads & 0x8) {
|
||||
setPixel(x0 + radius, y0);
|
||||
}
|
||||
if (quads & 0x4 && quads & 0x8) {
|
||||
setPixel(x0, y0 + radius);
|
||||
}
|
||||
if (quads & 0x2 && quads & 0x4) {
|
||||
setPixel(x0 - radius, y0);
|
||||
}
|
||||
if (quads & 0x1 && quads & 0x2) {
|
||||
setPixel(x0, y0 - radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
|
||||
int16_t x = 0, y = radius;
|
||||
int16_t dp = 1 - radius;
|
||||
do {
|
||||
if (dp < 0)
|
||||
dp = dp + 2 * (++x) + 3;
|
||||
else
|
||||
dp = dp + 2 * (++x) - 2 * (--y) + 5;
|
||||
|
||||
drawHorizontalLine(x0 - x, y0 - y, 2*x);
|
||||
drawHorizontalLine(x0 - x, y0 + y, 2*x);
|
||||
drawHorizontalLine(x0 - y, y0 - x, 2*y);
|
||||
drawHorizontalLine(x0 - y, y0 + x, 2*y);
|
||||
|
||||
|
||||
} while (x < y);
|
||||
drawHorizontalLine(x0 - radius, y0, 2 * radius);
|
||||
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
|
||||
if (y < 0 || y >= DISPLAY_HEIGHT) { return; }
|
||||
|
||||
if (x < 0) {
|
||||
length += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if ( (x + length) > DISPLAY_WIDTH) {
|
||||
length = (DISPLAY_WIDTH - x);
|
||||
}
|
||||
|
||||
if (length <= 0) { return; }
|
||||
|
||||
uint8_t * bufferPtr = buffer;
|
||||
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
|
||||
bufferPtr += x;
|
||||
|
||||
uint8_t drawBit = 1 << (y & 7);
|
||||
|
||||
switch (color) {
|
||||
case WHITE: while (length--) {
|
||||
*bufferPtr++ |= drawBit;
|
||||
}; break;
|
||||
case BLACK: drawBit = ~drawBit; while (length--) {
|
||||
*bufferPtr++ &= drawBit;
|
||||
}; break;
|
||||
case INVERSE: while (length--) {
|
||||
*bufferPtr++ ^= drawBit;
|
||||
}; break;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
|
||||
if (x < 0 || x >= DISPLAY_WIDTH) return;
|
||||
|
||||
if (y < 0) {
|
||||
length += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if ( (y + length) > DISPLAY_HEIGHT) {
|
||||
length = (DISPLAY_HEIGHT - y);
|
||||
}
|
||||
|
||||
if (length <= 0) return;
|
||||
|
||||
|
||||
uint8_t yOffset = y & 7;
|
||||
uint8_t drawBit;
|
||||
uint8_t *bufferPtr = buffer;
|
||||
|
||||
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
|
||||
bufferPtr += x;
|
||||
|
||||
if (yOffset) {
|
||||
yOffset = 8 - yOffset;
|
||||
drawBit = ~(0xFF >> (yOffset));
|
||||
|
||||
if (length < yOffset) {
|
||||
drawBit &= (0xFF >> (yOffset - length));
|
||||
}
|
||||
|
||||
switch (color) {
|
||||
case WHITE: *bufferPtr |= drawBit; break;
|
||||
case BLACK: *bufferPtr &= ~drawBit; break;
|
||||
case INVERSE: *bufferPtr ^= drawBit; break;
|
||||
}
|
||||
|
||||
if (length < yOffset) return;
|
||||
|
||||
length -= yOffset;
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
}
|
||||
|
||||
if (length >= 8) {
|
||||
switch (color) {
|
||||
case WHITE:
|
||||
case BLACK:
|
||||
drawBit = (color == WHITE) ? 0xFF : 0x00;
|
||||
do {
|
||||
*bufferPtr = drawBit;
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
length -= 8;
|
||||
} while (length >= 8);
|
||||
break;
|
||||
case INVERSE:
|
||||
do {
|
||||
*bufferPtr = ~(*bufferPtr);
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
length -= 8;
|
||||
} while (length >= 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
drawBit = (1 << (length & 7)) - 1;
|
||||
switch (color) {
|
||||
case WHITE: *bufferPtr |= drawBit; break;
|
||||
case BLACK: *bufferPtr &= ~drawBit; break;
|
||||
case INVERSE: *bufferPtr ^= drawBit; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) {
|
||||
uint16_t radius = height / 2;
|
||||
uint16_t xRadius = x + radius;
|
||||
uint16_t yRadius = y + radius;
|
||||
uint16_t doubleRadius = 2 * radius;
|
||||
uint16_t innerRadius = radius - 2;
|
||||
|
||||
setColor(WHITE);
|
||||
drawCircleQuads(xRadius, yRadius, radius, 0b00000110);
|
||||
drawHorizontalLine(xRadius, y, width - doubleRadius + 1);
|
||||
drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1);
|
||||
drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001);
|
||||
|
||||
uint16_t maxProgressWidth = (width - doubleRadius - 1) * progress / 100;
|
||||
|
||||
fillCircle(xRadius, yRadius, innerRadius);
|
||||
fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3);
|
||||
fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *image) {
|
||||
drawInternal(xMove, yMove, width, height, image, 0, 0);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *xbm) {
|
||||
int16_t widthInXbm = (width + 7) / 8;
|
||||
uint8_t data;
|
||||
|
||||
for(int16_t y = 0; y < height; y++) {
|
||||
for(int16_t x = 0; x < width; x++ ) {
|
||||
if (x & 7) {
|
||||
data >>= 1; // Move a bit
|
||||
} else { // Read new data every 8 bit
|
||||
data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm);
|
||||
}
|
||||
// if there is a bit draw it
|
||||
if (data & 0x01) {
|
||||
setPixel(xMove + x, yMove + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) {
|
||||
uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS);
|
||||
uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
|
||||
uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS) * JUMPTABLE_BYTES;
|
||||
|
||||
uint8_t cursorX = 0;
|
||||
uint8_t cursorY = 0;
|
||||
|
||||
switch (textAlignment) {
|
||||
case TEXT_ALIGN_CENTER_BOTH:
|
||||
yMove -= textHeight >> 1;
|
||||
// Fallthrough
|
||||
case TEXT_ALIGN_CENTER:
|
||||
xMove -= textWidth >> 1; // divide by 2
|
||||
break;
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
xMove -= textWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't draw anything if it is not on the screen.
|
||||
if (xMove + textWidth < 0 || xMove > DISPLAY_WIDTH ) {return;}
|
||||
if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {return;}
|
||||
|
||||
for (uint16_t j = 0; j < textLength; j++) {
|
||||
int16_t xPos = xMove + cursorX;
|
||||
int16_t yPos = yMove + cursorY;
|
||||
|
||||
byte code = text[j];
|
||||
if (code >= firstChar) {
|
||||
byte charCode = code - firstChar;
|
||||
|
||||
// 4 Bytes per char code
|
||||
byte msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress
|
||||
byte lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB /
|
||||
byte charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size
|
||||
byte currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width
|
||||
|
||||
// Test if the char is drawable
|
||||
if (!(msbJumpToChar == 255 && lsbJumpToChar == 255)) {
|
||||
// Get the position of the char data
|
||||
uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ((msbJumpToChar << 8) + lsbJumpToChar);
|
||||
drawInternal(xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize);
|
||||
}
|
||||
|
||||
cursorX += currentCharWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, String strUser) {
|
||||
uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
|
||||
|
||||
// char* text must be freed!
|
||||
char* text = utf8ascii(strUser);
|
||||
|
||||
uint16_t yOffset = 0;
|
||||
// If the string should be centered vertically too
|
||||
// we need to now how heigh the string is.
|
||||
if (textAlignment == TEXT_ALIGN_CENTER_BOTH) {
|
||||
uint16_t lb = 0;
|
||||
// Find number of linebreaks in text
|
||||
for (uint16_t i=0;text[i] != 0; i++) {
|
||||
lb += (text[i] == 10);
|
||||
}
|
||||
// Calculate center
|
||||
yOffset = (lb * lineHeight) / 2;
|
||||
}
|
||||
|
||||
uint16_t line = 0;
|
||||
char* textPart = strtok(text,"\n");
|
||||
while (textPart != NULL) {
|
||||
uint16_t length = strlen(textPart);
|
||||
drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length));
|
||||
textPart = strtok(NULL, "\n");
|
||||
}
|
||||
free(text);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, String strUser) {
|
||||
uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
|
||||
uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
|
||||
|
||||
char* text = utf8ascii(strUser);
|
||||
|
||||
uint16_t length = strlen(text);
|
||||
uint16_t lastDrawnPos = 0;
|
||||
uint16_t lineNumber = 0;
|
||||
uint16_t strWidth = 0;
|
||||
|
||||
uint16_t preferredBreakpoint = 0;
|
||||
uint16_t widthAtBreakpoint = 0;
|
||||
|
||||
for (uint16_t i = 0; i < length; i++) {
|
||||
strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[i] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH);
|
||||
|
||||
// Always try to break on a space or dash
|
||||
if (text[i] == ' ' || text[i]== '-') {
|
||||
preferredBreakpoint = i;
|
||||
widthAtBreakpoint = strWidth;
|
||||
}
|
||||
|
||||
if (strWidth >= maxLineWidth) {
|
||||
if (preferredBreakpoint == 0) {
|
||||
preferredBreakpoint = i;
|
||||
widthAtBreakpoint = strWidth;
|
||||
}
|
||||
drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint);
|
||||
lastDrawnPos = preferredBreakpoint + 1;
|
||||
// It is possible that we did not draw all letters to i so we need
|
||||
// to account for the width of the chars from `i - preferredBreakpoint`
|
||||
// by calculating the width we did not draw yet.
|
||||
strWidth = strWidth - widthAtBreakpoint;
|
||||
preferredBreakpoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw last part if needed
|
||||
if (lastDrawnPos < length) {
|
||||
drawStringInternal(xMove, yMove + lineNumber * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos));
|
||||
}
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
||||
uint16_t OLEDDisplay::getStringWidth(const char* text, uint16_t length) {
|
||||
uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
|
||||
|
||||
uint16_t stringWidth = 0;
|
||||
uint16_t maxWidth = 0;
|
||||
|
||||
while (length--) {
|
||||
stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[length] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH);
|
||||
if (text[length] == 10) {
|
||||
maxWidth = max(maxWidth, stringWidth);
|
||||
stringWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return max(maxWidth, stringWidth);
|
||||
}
|
||||
|
||||
uint16_t OLEDDisplay::getStringWidth(String strUser) {
|
||||
char* text = utf8ascii(strUser);
|
||||
uint16_t length = strlen(text);
|
||||
uint16_t width = getStringWidth(text, length);
|
||||
free(text);
|
||||
return width;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) {
|
||||
this->textAlignment = textAlignment;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setFont(const char *fontData) {
|
||||
this->fontData = fontData;
|
||||
}
|
||||
|
||||
void OLEDDisplay::displayOn(void) {
|
||||
sendCommand(DISPLAYON);
|
||||
}
|
||||
|
||||
void OLEDDisplay::displayOff(void) {
|
||||
sendCommand(DISPLAYOFF);
|
||||
}
|
||||
|
||||
void OLEDDisplay::invertDisplay(void) {
|
||||
sendCommand(INVERTDISPLAY);
|
||||
}
|
||||
|
||||
void OLEDDisplay::normalDisplay(void) {
|
||||
sendCommand(NORMALDISPLAY);
|
||||
}
|
||||
|
||||
void OLEDDisplay::setContrast(char contrast) {
|
||||
sendCommand(SETCONTRAST);
|
||||
sendCommand(contrast);
|
||||
}
|
||||
|
||||
void OLEDDisplay::flipScreenVertically() {
|
||||
sendCommand(SEGREMAP | 0x01);
|
||||
sendCommand(COMSCANDEC); //Rotate screen 180 Deg
|
||||
}
|
||||
|
||||
void OLEDDisplay::clear(void) {
|
||||
memset(buffer, 0, DISPLAY_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
|
||||
uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
|
||||
// Always align left
|
||||
setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
// State values
|
||||
uint16_t length = 0;
|
||||
uint16_t line = 0;
|
||||
uint16_t lastPos = 0;
|
||||
|
||||
for (uint16_t i=0;i<this->logBufferFilled;i++){
|
||||
// Everytime we have a \n print
|
||||
if (this->logBuffer[i] == 10) {
|
||||
length++;
|
||||
// Draw string on line `line` from lastPos to length
|
||||
// Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT
|
||||
drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0);
|
||||
// Remember last pos
|
||||
lastPos = i;
|
||||
// Reset length
|
||||
length = 0;
|
||||
} else {
|
||||
// Count chars until next linebreak
|
||||
length++;
|
||||
}
|
||||
}
|
||||
// Draw the remaining string
|
||||
if (length > 0) {
|
||||
drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
|
||||
if (logBuffer != NULL) free(logBuffer);
|
||||
uint16_t size = lines * chars;
|
||||
if (size > 0) {
|
||||
this->logBufferLine = 0; // Lines printed
|
||||
this->logBufferMaxLines = lines; // Lines max printable
|
||||
this->logBufferSize = size; // Total number of characters the buffer can hold
|
||||
this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
|
||||
if(!this->logBuffer) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t OLEDDisplay::write(uint8_t c) {
|
||||
if (this->logBufferSize > 0) {
|
||||
// Don't waste space on \r\n line endings, dropping \r
|
||||
if (c == 13) return 1;
|
||||
|
||||
bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines;
|
||||
bool bufferNotFull = this->logBufferFilled < this->logBufferSize;
|
||||
|
||||
// Can we write to the buffer?
|
||||
if (bufferNotFull && maxLineNotReached) {
|
||||
this->logBuffer[logBufferFilled] = utf8ascii(c);
|
||||
this->logBufferFilled++;
|
||||
// Keep track of lines written
|
||||
if (c == 10) this->logBufferLine++;
|
||||
} else {
|
||||
// Max line number is reached
|
||||
if (!maxLineNotReached) this->logBufferLine--;
|
||||
|
||||
// Find the end of the first line
|
||||
uint16_t firstLineEnd = 0;
|
||||
for (uint16_t i=0;i<this->logBufferFilled;i++) {
|
||||
if (this->logBuffer[i] == 10){
|
||||
// Include last char too
|
||||
firstLineEnd = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If there was a line ending
|
||||
if (firstLineEnd > 0) {
|
||||
// Calculate the new logBufferFilled value
|
||||
this->logBufferFilled = logBufferFilled - firstLineEnd;
|
||||
// Now we move the lines infront of the buffer
|
||||
memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled);
|
||||
} else {
|
||||
// Let's reuse the buffer if it was full
|
||||
if (!bufferNotFull) {
|
||||
this->logBufferFilled = 0;
|
||||
}// else {
|
||||
// Nothing to do here
|
||||
//}
|
||||
}
|
||||
write(c);
|
||||
}
|
||||
}
|
||||
// We are always writing all uint8_t to the buffer
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t OLEDDisplay::write(const char* str) {
|
||||
if (str == NULL) return 0;
|
||||
size_t length = strlen(str);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
write(str[i]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
// Private functions
|
||||
void OLEDDisplay::sendInitCommands(void) {
|
||||
sendCommand(DISPLAYOFF);
|
||||
sendCommand(SETDISPLAYCLOCKDIV);
|
||||
sendCommand(0xF0); // Increase speed of the display max ~96Hz
|
||||
sendCommand(SETMULTIPLEX);
|
||||
sendCommand(0x3F);
|
||||
sendCommand(SETDISPLAYOFFSET);
|
||||
sendCommand(0x00);
|
||||
sendCommand(SETSTARTLINE);
|
||||
sendCommand(CHARGEPUMP);
|
||||
sendCommand(0x14);
|
||||
sendCommand(MEMORYMODE);
|
||||
sendCommand(0x00);
|
||||
sendCommand(SEGREMAP);
|
||||
sendCommand(COMSCANINC);
|
||||
sendCommand(SETCOMPINS);
|
||||
sendCommand(0x12);
|
||||
sendCommand(SETCONTRAST);
|
||||
sendCommand(0xCF);
|
||||
sendCommand(SETPRECHARGE);
|
||||
sendCommand(0xF1);
|
||||
sendCommand(DISPLAYALLON_RESUME);
|
||||
sendCommand(NORMALDISPLAY);
|
||||
sendCommand(0x2e); // stop scroll
|
||||
sendCommand(DISPLAYON);
|
||||
}
|
||||
|
||||
void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) {
|
||||
if (width < 0 || height < 0) return;
|
||||
if (yMove + height < 0 || yMove > DISPLAY_HEIGHT) return;
|
||||
if (xMove + width < 0 || xMove > DISPLAY_WIDTH) return;
|
||||
|
||||
uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
|
||||
int8_t yOffset = yMove & 7;
|
||||
|
||||
bytesInData = bytesInData == 0 ? width * rasterHeight : bytesInData;
|
||||
|
||||
int16_t initYMove = yMove;
|
||||
int8_t initYOffset = yOffset;
|
||||
|
||||
|
||||
for (uint16_t i = 0; i < bytesInData; i++) {
|
||||
|
||||
// Reset if next horizontal drawing phase is started.
|
||||
if ( i % rasterHeight == 0) {
|
||||
yMove = initYMove;
|
||||
yOffset = initYOffset;
|
||||
}
|
||||
|
||||
byte currentByte = pgm_read_byte(data + offset + i);
|
||||
|
||||
int16_t xPos = xMove + (i / rasterHeight);
|
||||
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * DISPLAY_WIDTH;
|
||||
|
||||
int16_t yScreenPos = yMove + yOffset;
|
||||
int16_t dataPos = xPos + yPos;
|
||||
|
||||
if (dataPos >= 0 && dataPos < DISPLAY_BUFFER_SIZE &&
|
||||
xPos >= 0 && xPos < DISPLAY_WIDTH ) {
|
||||
|
||||
if (yOffset >= 0) {
|
||||
switch (this->color) {
|
||||
case WHITE: buffer[dataPos] |= currentByte << yOffset; break;
|
||||
case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break;
|
||||
case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
|
||||
}
|
||||
if (dataPos < (DISPLAY_BUFFER_SIZE - DISPLAY_WIDTH)) {
|
||||
switch (this->color) {
|
||||
case WHITE: buffer[dataPos + DISPLAY_WIDTH] |= currentByte >> (8 - yOffset); break;
|
||||
case BLACK: buffer[dataPos + DISPLAY_WIDTH] &= ~(currentByte >> (8 - yOffset)); break;
|
||||
case INVERSE: buffer[dataPos + DISPLAY_WIDTH] ^= currentByte >> (8 - yOffset); break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Make new offset position
|
||||
yOffset = -yOffset;
|
||||
|
||||
switch (this->color) {
|
||||
case WHITE: buffer[dataPos] |= currentByte >> yOffset; break;
|
||||
case BLACK: buffer[dataPos] &= ~(currentByte >> yOffset); break;
|
||||
case INVERSE: buffer[dataPos] ^= currentByte >> yOffset; break;
|
||||
}
|
||||
|
||||
// Prepare for next iteration by moving one block up
|
||||
yMove -= 8;
|
||||
|
||||
// and setting the new yOffset
|
||||
yOffset = 8 - yOffset;
|
||||
}
|
||||
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
uint8_t OLEDDisplay::utf8ascii(byte ascii) {
|
||||
static uint8_t LASTCHAR;
|
||||
|
||||
if ( ascii < 128 ) { // Standard ASCII-set 0..0x7F handling
|
||||
LASTCHAR = 0;
|
||||
return ascii;
|
||||
}
|
||||
|
||||
uint8_t last = LASTCHAR; // get last char
|
||||
LASTCHAR = ascii;
|
||||
|
||||
switch (last) { // conversion depnding on first UTF8-character
|
||||
case 0xC2: return (ascii); break;
|
||||
case 0xC3: return (ascii | 0xC0); break;
|
||||
case 0x82: if (ascii == 0xAC) return (0x80); // special case Euro-symbol
|
||||
}
|
||||
|
||||
return 0; // otherwise: return zero, if character has to be ignored
|
||||
}
|
||||
|
||||
// You need to free the char!
|
||||
char* OLEDDisplay::utf8ascii(String str) {
|
||||
uint16_t k = 0;
|
||||
uint16_t length = str.length() + 1;
|
||||
|
||||
// Copy the string into a char array
|
||||
char* s = (char*) malloc(length * sizeof(char));
|
||||
if(!s) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][utf8ascii] Can't allocate another char array. Drop support for UTF-8.\n");
|
||||
return (char*) str.c_str();
|
||||
}
|
||||
str.toCharArray(s, length);
|
||||
|
||||
length--;
|
||||
|
||||
for (uint16_t i=0; i < length; i++) {
|
||||
char c = utf8ascii(s[i]);
|
||||
if (c!=0) {
|
||||
s[k++]=c;
|
||||
}
|
||||
}
|
||||
|
||||
s[k]=0;
|
||||
|
||||
// This will leak 's' be sure to free it in the calling function.
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef OLEDDISPLAY_h
|
||||
#define OLEDDISPLAY_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "OLEDDisplayFonts.h"
|
||||
|
||||
//#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ )
|
||||
|
||||
#ifndef DEBUG_OLEDDISPLAY
|
||||
#define DEBUG_OLEDDISPLAY(...)
|
||||
#endif
|
||||
|
||||
// Use DOUBLE BUFFERING by default
|
||||
#ifndef OLEDDISPLAY_REDUCE_MEMORY
|
||||
#define OLEDDISPLAY_DOUBLE_BUFFER
|
||||
#endif
|
||||
|
||||
|
||||
// Display settings
|
||||
#define DISPLAY_WIDTH 128
|
||||
#define DISPLAY_HEIGHT 64
|
||||
#define DISPLAY_BUFFER_SIZE 1024
|
||||
|
||||
// Header Values
|
||||
#define JUMPTABLE_BYTES 4
|
||||
|
||||
#define JUMPTABLE_LSB 1
|
||||
#define JUMPTABLE_SIZE 2
|
||||
#define JUMPTABLE_WIDTH 3
|
||||
#define JUMPTABLE_START 4
|
||||
|
||||
#define WIDTH_POS 0
|
||||
#define HEIGHT_POS 1
|
||||
#define FIRST_CHAR_POS 2
|
||||
#define CHAR_NUM_POS 3
|
||||
|
||||
|
||||
// Display commands
|
||||
#define CHARGEPUMP 0x8D
|
||||
#define COLUMNADDR 0x21
|
||||
#define COMSCANDEC 0xC8
|
||||
#define COMSCANINC 0xC0
|
||||
#define DISPLAYALLON 0xA5
|
||||
#define DISPLAYALLON_RESUME 0xA4
|
||||
#define DISPLAYOFF 0xAE
|
||||
#define DISPLAYON 0xAF
|
||||
#define EXTERNALVCC 0x1
|
||||
#define INVERTDISPLAY 0xA7
|
||||
#define MEMORYMODE 0x20
|
||||
#define NORMALDISPLAY 0xA6
|
||||
#define PAGEADDR 0x22
|
||||
#define SEGREMAP 0xA0
|
||||
#define SETCOMPINS 0xDA
|
||||
#define SETCONTRAST 0x81
|
||||
#define SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SETDISPLAYOFFSET 0xD3
|
||||
#define SETHIGHCOLUMN 0x10
|
||||
#define SETLOWCOLUMN 0x00
|
||||
#define SETMULTIPLEX 0xA8
|
||||
#define SETPRECHARGE 0xD9
|
||||
#define SETSEGMENTREMAP 0xA1
|
||||
#define SETSTARTLINE 0x40
|
||||
#define SETVCOMDETECT 0xDB
|
||||
#define SWITCHCAPVCC 0x2
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; }
|
||||
#endif
|
||||
|
||||
enum OLEDDISPLAY_COLOR {
|
||||
BLACK = 0,
|
||||
WHITE = 1,
|
||||
INVERSE = 2
|
||||
};
|
||||
|
||||
enum OLEDDISPLAY_TEXT_ALIGNMENT {
|
||||
TEXT_ALIGN_LEFT = 0,
|
||||
TEXT_ALIGN_RIGHT = 1,
|
||||
TEXT_ALIGN_CENTER = 2,
|
||||
TEXT_ALIGN_CENTER_BOTH = 3
|
||||
};
|
||||
|
||||
|
||||
class OLEDDisplay : public Print {
|
||||
public:
|
||||
|
||||
virtual ~OLEDDisplay() {}
|
||||
|
||||
// Initialize the display
|
||||
bool init();
|
||||
|
||||
// Free the memory used by the display
|
||||
void end();
|
||||
|
||||
// Cycle through the initialization
|
||||
void resetDisplay(void);
|
||||
|
||||
/* Drawing functions */
|
||||
// Sets the color of all pixel operations
|
||||
void setColor(OLEDDISPLAY_COLOR color);
|
||||
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int16_t x, int16_t y);
|
||||
|
||||
// Draw a line from position 0 to position 1
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
|
||||
|
||||
// Draw the border of a rectangle at the given location
|
||||
void drawRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Fill the rectangle
|
||||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Draw the border of a circle
|
||||
void drawCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw all Quadrants specified in the quads bit mask
|
||||
void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads);
|
||||
|
||||
// Fill circle
|
||||
void fillCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw a line horizontally
|
||||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draw a lin vertically
|
||||
void drawVerticalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
|
||||
// a unsigned byte value between 0 and 100
|
||||
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
|
||||
|
||||
// Draw a bitmap in the internal image format
|
||||
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const char *image);
|
||||
|
||||
// Draw a XBM
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const char *xbm);
|
||||
|
||||
/* Text functions */
|
||||
|
||||
// Draws a string at the given location
|
||||
void drawString(int16_t x, int16_t y, String text);
|
||||
|
||||
// Draws a String with a maximum width at the given location.
|
||||
// If the given String is wider than the specified width
|
||||
// The text will be wrapped to the next line at a space or dash
|
||||
void drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, String text);
|
||||
|
||||
// Returns the width of the const char* with the current
|
||||
// font settings
|
||||
uint16_t getStringWidth(const char* text, uint16_t length);
|
||||
|
||||
// Convencience method for the const char version
|
||||
uint16_t getStringWidth(String text);
|
||||
|
||||
// Specifies relative to which anchor point
|
||||
// the text is rendered. Available constants:
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
|
||||
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment);
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
void setFont(const char *fontData);
|
||||
|
||||
/* Display functions */
|
||||
|
||||
// Turn the display on
|
||||
void displayOn(void);
|
||||
|
||||
// Turn the display offs
|
||||
void displayOff(void);
|
||||
|
||||
// Inverted display mode
|
||||
void invertDisplay(void);
|
||||
|
||||
// Normal display mode
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
void setContrast(char contrast);
|
||||
|
||||
// Turn the display upside down
|
||||
void flipScreenVertically();
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) = 0;
|
||||
|
||||
// Clear the local pixel buffer
|
||||
void clear(void);
|
||||
|
||||
// Log buffer implementation
|
||||
|
||||
// This will define the lines and characters you can
|
||||
// print to the screen. When you exeed the buffer size (lines * chars)
|
||||
// the output may be truncated due to the size constraint.
|
||||
bool setLogBuffer(uint16_t lines, uint16_t chars);
|
||||
|
||||
// Draw the log buffer at position (x, y)
|
||||
void drawLogBuffer(uint16_t x, uint16_t y);
|
||||
|
||||
// Implementent needed function to be compatible with Print class
|
||||
size_t write(uint8_t c);
|
||||
size_t write(const char* s);
|
||||
|
||||
uint8_t *buffer;
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t *buffer_back;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
OLEDDISPLAY_TEXT_ALIGNMENT textAlignment = TEXT_ALIGN_LEFT;
|
||||
OLEDDISPLAY_COLOR color = WHITE;
|
||||
|
||||
const char *fontData = ArialMT_Plain_10;
|
||||
|
||||
// State values for logBuffer
|
||||
uint16_t logBufferSize = 0;
|
||||
uint16_t logBufferFilled = 0;
|
||||
uint16_t logBufferLine = 0;
|
||||
uint16_t logBufferMaxLines = 0;
|
||||
char *logBuffer = NULL;
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
virtual void sendCommand(uint8_t com) {};
|
||||
|
||||
// Connect to the display
|
||||
virtual bool connect() { return false; };
|
||||
|
||||
// Send all the init commands
|
||||
void sendInitCommands();
|
||||
|
||||
// converts utf8 characters to extended ascii
|
||||
static char* utf8ascii(String s);
|
||||
static byte utf8ascii(byte ascii);
|
||||
|
||||
void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline));
|
||||
|
||||
void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OLEDDisplayUi.h"
|
||||
|
||||
OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
|
||||
this->display = display;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::init() {
|
||||
this->display->init();
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::setTargetFPS(uint8_t fps){
|
||||
float oldInterval = this->updateInterval;
|
||||
this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
|
||||
|
||||
// Calculate new ticksPerFrame
|
||||
float changeRatio = oldInterval / (float) this->updateInterval;
|
||||
this->ticksPerFrame *= changeRatio;
|
||||
this->ticksPerTransition *= changeRatio;
|
||||
}
|
||||
|
||||
// -/------ Automatic controll ------\-
|
||||
|
||||
void OLEDDisplayUi::enableAutoTransition(){
|
||||
this->autoTransition = true;
|
||||
}
|
||||
void OLEDDisplayUi::disableAutoTransition(){
|
||||
this->autoTransition = false;
|
||||
}
|
||||
void OLEDDisplayUi::setAutoTransitionForwards(){
|
||||
this->state.frameTransitionDirection = 1;
|
||||
this->lastTransitionDirection = 1;
|
||||
}
|
||||
void OLEDDisplayUi::setAutoTransitionBackwards(){
|
||||
this->state.frameTransitionDirection = -1;
|
||||
this->lastTransitionDirection = -1;
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerFrame(uint16_t time){
|
||||
this->ticksPerFrame = (int) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerTransition(uint16_t time){
|
||||
this->ticksPerTransition = (int) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
|
||||
// -/------ Customize indicator position and style -------\-
|
||||
void OLEDDisplayUi::enableIndicator(){
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::disableIndicator(){
|
||||
this->state.isIndicatorDrawen = false;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::enableAllIndicators(){
|
||||
this->shouldDrawIndicators = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::disableAllIndicators(){
|
||||
this->shouldDrawIndicators = false;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) {
|
||||
this->indicatorPosition = pos;
|
||||
}
|
||||
void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) {
|
||||
this->indicatorDirection = dir;
|
||||
}
|
||||
void OLEDDisplayUi::setActiveSymbol(const char* symbol) {
|
||||
this->activeSymbol = symbol;
|
||||
}
|
||||
void OLEDDisplayUi::setInactiveSymbol(const char* symbol) {
|
||||
this->inactiveSymbol = symbol;
|
||||
}
|
||||
|
||||
|
||||
// -/----- Frame settings -----\-
|
||||
void OLEDDisplayUi::setFrameAnimation(AnimationDirection dir) {
|
||||
this->frameAnimationDirection = dir;
|
||||
}
|
||||
void OLEDDisplayUi::setFrames(FrameCallback* frameFunctions, uint8_t frameCount) {
|
||||
this->frameFunctions = frameFunctions;
|
||||
this->frameCount = frameCount;
|
||||
this->resetState();
|
||||
}
|
||||
|
||||
// -/----- Overlays ------\-
|
||||
void OLEDDisplayUi::setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount){
|
||||
this->overlayFunctions = overlayFunctions;
|
||||
this->overlayCount = overlayCount;
|
||||
}
|
||||
|
||||
// -/----- Loading Process -----\-
|
||||
|
||||
void OLEDDisplayUi::setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction) {
|
||||
this->loadingDrawFunction = loadingDrawFunction;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::runLoadingProcess(LoadingStage* stages, uint8_t stagesCount) {
|
||||
uint8_t progress = 0;
|
||||
uint8_t increment = 100 / stagesCount;
|
||||
|
||||
for (uint8_t i = 0; i < stagesCount; i++) {
|
||||
display->clear();
|
||||
this->loadingDrawFunction(this->display, &stages[i], progress);
|
||||
display->display();
|
||||
|
||||
stages[i].callback();
|
||||
|
||||
progress += increment;
|
||||
yield();
|
||||
}
|
||||
|
||||
display->clear();
|
||||
this->loadingDrawFunction(this->display, &stages[stagesCount-1], progress);
|
||||
display->display();
|
||||
|
||||
delay(150);
|
||||
}
|
||||
|
||||
// -/----- Manuel control -----\-
|
||||
void OLEDDisplayUi::nextFrame() {
|
||||
if (this->state.frameState != IN_TRANSITION) {
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.frameTransitionDirection = 1;
|
||||
}
|
||||
}
|
||||
void OLEDDisplayUi::previousFrame() {
|
||||
if (this->state.frameState != IN_TRANSITION) {
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.frameTransitionDirection = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::switchToFrame(uint8_t frame) {
|
||||
if (frame >= this->frameCount) return;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
if (frame == this->state.currentFrame) return;
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = frame;
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::transitionToFrame(uint8_t frame) {
|
||||
if (frame >= this->frameCount) return;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
if (frame == this->state.currentFrame) return;
|
||||
this->nextFrameNumber = frame;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.frameTransitionDirection = frame < this->state.currentFrame ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
// -/----- State information -----\-
|
||||
OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
|
||||
return &this->state;
|
||||
}
|
||||
|
||||
|
||||
int8_t OLEDDisplayUi::update(){
|
||||
long frameStart = millis();
|
||||
int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
|
||||
if ( timeBudget <= 0) {
|
||||
// Implement frame skipping to ensure time budget is keept
|
||||
if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil(-timeBudget / this->updateInterval);
|
||||
|
||||
this->state.lastUpdate = frameStart;
|
||||
this->tick();
|
||||
}
|
||||
return this->updateInterval - (millis() - frameStart);
|
||||
}
|
||||
|
||||
|
||||
void OLEDDisplayUi::tick() {
|
||||
this->state.ticksSinceLastStateSwitch++;
|
||||
|
||||
switch (this->state.frameState) {
|
||||
case IN_TRANSITION:
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = getNextFrameNumber();
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->nextFrameNumber = -1;
|
||||
}
|
||||
break;
|
||||
case FIXED:
|
||||
// Revert manuelControll
|
||||
if (this->state.manuelControll) {
|
||||
this->state.frameTransitionDirection = this->lastTransitionDirection;
|
||||
this->state.manuelControll = false;
|
||||
}
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){
|
||||
if (this->autoTransition){
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
}
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this->display->clear();
|
||||
this->drawFrame();
|
||||
if (shouldDrawIndicators) {
|
||||
this->drawIndicator();
|
||||
}
|
||||
this->drawOverlays();
|
||||
this->display->display();
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::resetState() {
|
||||
this->state.lastUpdate = 0;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = 0;
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawFrame(){
|
||||
switch (this->state.frameState){
|
||||
case IN_TRANSITION: {
|
||||
float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
|
||||
int16_t x, y, x1, y1;
|
||||
switch(this->frameAnimationDirection){
|
||||
case SLIDE_LEFT:
|
||||
x = -128 * progress;
|
||||
y = 0;
|
||||
x1 = x + 128;
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_RIGHT:
|
||||
x = 128 * progress;
|
||||
y = 0;
|
||||
x1 = x - 128;
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_UP:
|
||||
x = 0;
|
||||
y = -64 * progress;
|
||||
x1 = 0;
|
||||
y1 = y + 64;
|
||||
break;
|
||||
case SLIDE_DOWN:
|
||||
x = 0;
|
||||
y = 64 * progress;
|
||||
x1 = 0;
|
||||
y1 = y - 64;
|
||||
break;
|
||||
}
|
||||
|
||||
// Invert animation if direction is reversed.
|
||||
int8_t dir = this->state.frameTransitionDirection >= 0 ? 1 : -1;
|
||||
x *= dir; y *= dir; x1 *= dir; y1 *= dir;
|
||||
|
||||
bool drawenCurrentFrame;
|
||||
|
||||
|
||||
// Prope each frameFunction for the indicator Drawen state
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y);
|
||||
drawenCurrentFrame = this->state.isIndicatorDrawen;
|
||||
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1);
|
||||
|
||||
// Build up the indicatorDrawState
|
||||
if (drawenCurrentFrame && !this->state.isIndicatorDrawen) {
|
||||
// Drawen now but not next
|
||||
this->indicatorDrawState = 2;
|
||||
} else if (!drawenCurrentFrame && this->state.isIndicatorDrawen) {
|
||||
// Not drawen now but next
|
||||
this->indicatorDrawState = 1;
|
||||
} else if (!drawenCurrentFrame && !this->state.isIndicatorDrawen) {
|
||||
// Not drawen in both frames
|
||||
this->indicatorDrawState = 3;
|
||||
}
|
||||
|
||||
// If the indicator isn't draw in the current frame
|
||||
// reflect it in state.isIndicatorDrawen
|
||||
if (!drawenCurrentFrame) this->state.isIndicatorDrawen = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case FIXED:
|
||||
// Always assume that the indicator is drawn!
|
||||
// And set indicatorDrawState to "not known yet"
|
||||
this->indicatorDrawState = 0;
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawIndicator() {
|
||||
|
||||
// Only draw if the indicator is invisible
|
||||
// for both frames or
|
||||
// the indiactor is shown and we are IN_TRANSITION
|
||||
if (this->indicatorDrawState == 3 || (!this->state.isIndicatorDrawen && this->state.frameState != IN_TRANSITION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t posOfHighlightFrame;
|
||||
float indicatorFadeProgress = 0;
|
||||
|
||||
// if the indicator needs to be slided in we want to
|
||||
// highlight the next frame in the transition
|
||||
uint8_t frameToHighlight = this->indicatorDrawState == 1 ? this->getNextFrameNumber() : this->state.currentFrame;
|
||||
|
||||
// Calculate the frame that needs to be highlighted
|
||||
// based on the Direction the indiactor is drawn
|
||||
switch (this->indicatorDirection){
|
||||
case LEFT_RIGHT:
|
||||
posOfHighlightFrame = frameToHighlight;
|
||||
break;
|
||||
case RIGHT_LEFT:
|
||||
posOfHighlightFrame = this->frameCount - frameToHighlight;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (this->indicatorDrawState) {
|
||||
case 1: // Indicator was not drawn in this frame but will be in next
|
||||
// Slide IN
|
||||
indicatorFadeProgress = 1 - ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
|
||||
break;
|
||||
case 2: // Indicator was drawn in this frame but not in next
|
||||
// Slide OUT
|
||||
indicatorFadeProgress = ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t frameStartPos = (12 * frameCount / 2);
|
||||
const char *image;
|
||||
uint16_t x,y;
|
||||
for (byte i = 0; i < this->frameCount; i++) {
|
||||
|
||||
switch (this->indicatorPosition){
|
||||
case TOP:
|
||||
y = 0 - (8 * indicatorFadeProgress);
|
||||
x = 64 - frameStartPos + 12 * i;
|
||||
break;
|
||||
case BOTTOM:
|
||||
y = 56 + (8 * indicatorFadeProgress);
|
||||
x = 64 - frameStartPos + 12 * i;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = 120 + (8 * indicatorFadeProgress);
|
||||
y = 32 - frameStartPos + 2 + 12 * i;
|
||||
break;
|
||||
case LEFT:
|
||||
x = 0 - (8 * indicatorFadeProgress);
|
||||
y = 32 - frameStartPos + 2 + 12 * i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (posOfHighlightFrame == i) {
|
||||
image = this->activeSymbol;
|
||||
} else {
|
||||
image = this->inactiveSymbol;
|
||||
}
|
||||
|
||||
this->display->drawFastImage(x, y, 8, 8, image);
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawOverlays() {
|
||||
for (uint8_t i=0;i<this->overlayCount;i++){
|
||||
(this->overlayFunctions[i])(this->display, &this->state);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t OLEDDisplayUi::getNextFrameNumber(){
|
||||
if (this->nextFrameNumber != -1) return this->nextFrameNumber;
|
||||
return (this->state.currentFrame + this->frameCount + this->state.frameTransitionDirection) % this->frameCount;
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OLEDDISPLAYUI_h
|
||||
#define OLEDDISPLAYUI_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "OLEDDisplay.h"
|
||||
|
||||
//#define DEBUG_OLEDDISPLAYUI(...) Serial.printf( __VA_ARGS__ )
|
||||
|
||||
#ifndef DEBUG_OLEDDISPLAYUI
|
||||
#define DEBUG_OLEDDISPLAYUI(...)
|
||||
#endif
|
||||
|
||||
enum AnimationDirection {
|
||||
SLIDE_UP,
|
||||
SLIDE_DOWN,
|
||||
SLIDE_LEFT,
|
||||
SLIDE_RIGHT
|
||||
};
|
||||
|
||||
enum IndicatorPosition {
|
||||
TOP,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
LEFT
|
||||
};
|
||||
|
||||
enum IndicatorDirection {
|
||||
LEFT_RIGHT,
|
||||
RIGHT_LEFT
|
||||
};
|
||||
|
||||
enum FrameState {
|
||||
IN_TRANSITION,
|
||||
FIXED
|
||||
};
|
||||
|
||||
|
||||
const char ANIMATION_activeSymbol[] PROGMEM = {
|
||||
0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
|
||||
};
|
||||
|
||||
const char ANIMATION_inactiveSymbol[] PROGMEM = {
|
||||
0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
|
||||
};
|
||||
|
||||
|
||||
// Structure of the UiState
|
||||
struct OLEDDisplayUiState {
|
||||
uint64_t lastUpdate = 0;
|
||||
uint16_t ticksSinceLastStateSwitch = 0;
|
||||
|
||||
FrameState frameState = FIXED;
|
||||
uint8_t currentFrame = 0;
|
||||
|
||||
bool isIndicatorDrawen = true;
|
||||
|
||||
// Normal = 1, Inverse = -1;
|
||||
int8_t frameTransitionDirection = 1;
|
||||
|
||||
bool manuelControll = false;
|
||||
|
||||
// Custom data that can be used by the user
|
||||
void* userData = NULL;
|
||||
};
|
||||
|
||||
struct LoadingStage {
|
||||
const char* process;
|
||||
void (*callback)();
|
||||
};
|
||||
|
||||
typedef void (*FrameCallback)(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
|
||||
typedef void (*OverlayCallback)(OLEDDisplay *display, OLEDDisplayUiState* state);
|
||||
typedef void (*LoadingDrawFunction)(OLEDDisplay *display, LoadingStage* stage, uint8_t progress);
|
||||
|
||||
class OLEDDisplayUi {
|
||||
private:
|
||||
OLEDDisplay *display;
|
||||
|
||||
// Symbols for the Indicator
|
||||
IndicatorPosition indicatorPosition = BOTTOM;
|
||||
IndicatorDirection indicatorDirection = LEFT_RIGHT;
|
||||
|
||||
const char* activeSymbol = ANIMATION_activeSymbol;
|
||||
const char* inactiveSymbol = ANIMATION_inactiveSymbol;
|
||||
|
||||
bool shouldDrawIndicators = true;
|
||||
|
||||
// Values for the Frames
|
||||
AnimationDirection frameAnimationDirection = SLIDE_RIGHT;
|
||||
|
||||
int8_t lastTransitionDirection = 1;
|
||||
|
||||
uint16_t ticksPerFrame = 151; // ~ 5000ms at 30 FPS
|
||||
uint16_t ticksPerTransition = 15; // ~ 500ms at 30 FPS
|
||||
|
||||
bool autoTransition = true;
|
||||
|
||||
FrameCallback* frameFunctions;
|
||||
uint8_t frameCount = 0;
|
||||
|
||||
// Internally used to transition to a specific frame
|
||||
int8_t nextFrameNumber = -1;
|
||||
|
||||
// Values for Overlays
|
||||
OverlayCallback* overlayFunctions;
|
||||
uint8_t overlayCount = 0;
|
||||
|
||||
// Will the Indicator be drawen
|
||||
// 3 Not drawn in both frames
|
||||
// 2 Drawn this frame but not next
|
||||
// 1 Not drown this frame but next
|
||||
// 0 Not known yet
|
||||
uint8_t indicatorDrawState = 1;
|
||||
|
||||
// Loading screen
|
||||
LoadingDrawFunction loadingDrawFunction = [](OLEDDisplay *display, LoadingStage* stage, uint8_t progress) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(64, 18, stage->process);
|
||||
display->drawProgressBar(4, 32, 120, 8, progress);
|
||||
};
|
||||
|
||||
// UI State
|
||||
OLEDDisplayUiState state;
|
||||
|
||||
// Bookeeping for update
|
||||
uint8_t updateInterval = 33;
|
||||
|
||||
uint8_t getNextFrameNumber();
|
||||
void drawIndicator();
|
||||
void drawFrame();
|
||||
void drawOverlays();
|
||||
void tick();
|
||||
void resetState();
|
||||
|
||||
public:
|
||||
|
||||
OLEDDisplayUi(OLEDDisplay *display);
|
||||
|
||||
/**
|
||||
* Initialise the display
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Configure the internal used target FPS
|
||||
*/
|
||||
void setTargetFPS(uint8_t fps);
|
||||
|
||||
// Automatic Controll
|
||||
/**
|
||||
* Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`.
|
||||
*/
|
||||
void enableAutoTransition();
|
||||
|
||||
/**
|
||||
* Disable automatic transition to next frame.
|
||||
*/
|
||||
void disableAutoTransition();
|
||||
|
||||
/**
|
||||
* Set the direction if the automatic transitioning
|
||||
*/
|
||||
void setAutoTransitionForwards();
|
||||
void setAutoTransitionBackwards();
|
||||
|
||||
/**
|
||||
* Set the approx. time a frame is displayed
|
||||
*/
|
||||
void setTimePerFrame(uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the approx. time a transition will take
|
||||
*/
|
||||
void setTimePerTransition(uint16_t time);
|
||||
|
||||
// Customize indicator position and style
|
||||
|
||||
/**
|
||||
* Draw the indicator.
|
||||
* This is the defaut state for all frames if
|
||||
* the indicator was hidden on the previous frame
|
||||
* it will be slided in.
|
||||
*/
|
||||
void enableIndicator();
|
||||
|
||||
/**
|
||||
* Don't draw the indicator.
|
||||
* This will slide out the indicator
|
||||
* when transitioning to the next frame.
|
||||
*/
|
||||
void disableIndicator();
|
||||
|
||||
/**
|
||||
* Enable drawing of indicators
|
||||
*/
|
||||
void enableAllIndicators();
|
||||
|
||||
/**
|
||||
* Disable draw of indicators.
|
||||
*/
|
||||
void disableAllIndicators();
|
||||
|
||||
/**
|
||||
* Set the position of the indicator bar.
|
||||
*/
|
||||
void setIndicatorPosition(IndicatorPosition pos);
|
||||
|
||||
/**
|
||||
* Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
|
||||
*/
|
||||
void setIndicatorDirection(IndicatorDirection dir);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbol(const char* symbol);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbol(const char* symbol);
|
||||
|
||||
|
||||
// Frame settings
|
||||
|
||||
/**
|
||||
* Configure what animation is used to transition from one frame to another
|
||||
*/
|
||||
void setFrameAnimation(AnimationDirection dir);
|
||||
|
||||
/**
|
||||
* Add frame drawing functions
|
||||
*/
|
||||
void setFrames(FrameCallback* frameFunctions, uint8_t frameCount);
|
||||
|
||||
// Overlay
|
||||
|
||||
/**
|
||||
* Add overlays drawing functions that are draw independent of the Frames
|
||||
*/
|
||||
void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount);
|
||||
|
||||
|
||||
// Loading animation
|
||||
/**
|
||||
* Set the function that will draw each step
|
||||
* in the loading animation
|
||||
*/
|
||||
void setLoadingDrawFunction(LoadingDrawFunction loadingFunction);
|
||||
|
||||
|
||||
/**
|
||||
* Run the loading process
|
||||
*/
|
||||
void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount);
|
||||
|
||||
|
||||
// Manual Control
|
||||
void nextFrame();
|
||||
void previousFrame();
|
||||
|
||||
/**
|
||||
* Switch without transition to frame `frame`.
|
||||
*/
|
||||
void switchToFrame(uint8_t frame);
|
||||
|
||||
/**
|
||||
* Transition to frame `frame`, when the `frame` number is bigger than the current
|
||||
* frame the forward animation will be used, otherwise the backwards animation is used.
|
||||
*/
|
||||
void transitionToFrame(uint8_t frame);
|
||||
|
||||
// State Info
|
||||
OLEDDisplayUiState* getUiState();
|
||||
|
||||
int8_t update();
|
||||
};
|
||||
#endif
|
||||
@@ -1,20 +1,34 @@
|
||||
# esp8266-oled-ssd1306
|
||||
esp8266-oled-ssd1306 [](https://travis-ci.org/squix78/esp8266-oled-ssd1306)
|
||||
============
|
||||
|
||||
> We just released version 3.0.0. Please have a look at our [upgrade guide](UPGRADE-3.0.md)
|
||||
|
||||
This is a driver for the SSD1306 based 128x64 pixel OLED display running on the Arduino/ESP8266 platform.
|
||||
Can be used with either the I2C or SPI version of the display
|
||||
|
||||
You can either download this library as a zip file and unpack it to your Arduino/libraries folder or (once it has been added) choose it from the Arduino library manager.
|
||||
|
||||
It is also available as a platformio library. Just execute the following command:
|
||||
```
|
||||
platformio lib install 562
|
||||
```
|
||||
|
||||
## Credits
|
||||
Many thanks go to Fabrice Weinberg (@FWeinb) for optimizing and refactoring the UI library.
|
||||
The init sequence for the SSD1306 was inspired by Adafruits library for the same display.
|
||||
This library has initially been written by Daniel Eichhorn (@squix78). Many thanks go to Fabrice Weinberg (@FWeinb) for optimizing and refactoring many aspects of the library. Also many thanks to the many committers who helped to add new features and who fixed many bugs.
|
||||
The init sequence for the SSD1306 was inspired by Adafruit's library for the same display.
|
||||
|
||||
## Usage
|
||||
|
||||
The SSD1306Demo is a very comprehensive example demonstrating the most important features of the library.
|
||||
Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the ESP8266 Weather Station library (https://github.com/squix78/esp8266-weather-station) which uses the OLED library to display beautiful weather information.
|
||||
|
||||
## Upgrade
|
||||
|
||||
The API changed a lot with the 3.0 release. If you were using this library with older versions please have a look at the [Upgrade Guide](UPGRADE-3.0.md).
|
||||
|
||||
## Features
|
||||
|
||||
* Draw pixels at given coordinates
|
||||
* Draw lines from given coordinates to given coordinates
|
||||
* Draw or fill a rectangle with given dimensions
|
||||
* Draw Text at given coordinates:
|
||||
* Define Alignment: Left, Right and Center
|
||||
@@ -32,20 +46,72 @@ Fonts are defined in a proprietary but open format. You can create new font file
|
||||
of open sourced Fonts from this web app: http://oleddisplay.squix.ch
|
||||
Choose the font family, style and size, check the preview image and if you like what you see click the "Create" button. This will create the font array in a text area form where you can copy and paste it into a new or existing header file.
|
||||
|
||||
|
||||

|
||||
|
||||
## Hardware Abstraction
|
||||
|
||||
The library supports different protocols to access the OLED display. Currently there is support for I2C using the built in Wire.h library, I2C by using the much faster BRZO I2C library [https://github.com/pasko-zh/brzo_i2c] written in assembler and it also supports displays which come with the SPI interface.
|
||||
|
||||
### I2C with Wire.h
|
||||
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SSD1306.h"
|
||||
|
||||
SSD1306 display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
or for a SH1106:
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SH1106.h"
|
||||
|
||||
SH1106 display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
|
||||
### I2C with brzo_i2c
|
||||
|
||||
```C++
|
||||
#include <brzo_i2c.h>
|
||||
#include "SSD1306Brzo.h"
|
||||
|
||||
SSD1306Brzo display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
or for the SH1106:
|
||||
```C++
|
||||
#include <brzo_i2c.h>
|
||||
#include "SH1106Brzo.h"
|
||||
|
||||
SH1106Brzo display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
|
||||
### SPI
|
||||
|
||||
```C++
|
||||
#include <SPI.h>
|
||||
#include "SSD1306Spi.h"
|
||||
|
||||
SSD1306Spi display(RES, DC, CS);
|
||||
```
|
||||
or for the SH1106:
|
||||
```C++
|
||||
#include <SPI.h>
|
||||
#include "SH1106Spi.h"
|
||||
|
||||
SH1106Spi display(RES, DC, CS);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Display Control
|
||||
|
||||
```C++
|
||||
// Create the display object connected to pin sda and sdc
|
||||
SSD1306(int i2cAddress, int sda, int sdc);
|
||||
|
||||
// Initialize the display
|
||||
void init();
|
||||
|
||||
// Free the memory used by the display
|
||||
void end();
|
||||
|
||||
// Cycle through the initialization
|
||||
void resetDisplay(void);
|
||||
|
||||
@@ -64,101 +130,227 @@ void clear(void);
|
||||
// Write the buffer to the display memory
|
||||
void display(void);
|
||||
|
||||
// Inverted display mode
|
||||
void invertDisplay(void);
|
||||
|
||||
// Normal display mode
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
void setContrast(char contrast);
|
||||
|
||||
// Turn the display upside down
|
||||
void flipScreenVertically();
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
void sendCommand(unsigned char com);
|
||||
|
||||
// Send all the init commands
|
||||
void sendInitCommands(void);
|
||||
```
|
||||
|
||||
## Pixel drawing
|
||||
|
||||
```C++
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int x, int y);
|
||||
|
||||
// Draw 8 bits at the given position
|
||||
void setChar(int x, int y, unsigned char data);
|
||||
/* Drawing functions */
|
||||
// Sets the color of all pixel operations
|
||||
void setColor(OLEDDISPLAY_COLOR color);
|
||||
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int16_t x, int16_t y);
|
||||
|
||||
// Draw a line from position 0 to position 1
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
|
||||
|
||||
// Draw the border of a rectangle at the given location
|
||||
void drawRect(int x, int y, int width, int height);
|
||||
void drawRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Fill the rectangle
|
||||
void fillRect(int x, int y, int width, int height);
|
||||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Draw a bitmap with the given dimensions
|
||||
void drawBitmap(int x, int y, int width, int height, const char *bitmap);
|
||||
// Draw the border of a circle
|
||||
void drawCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw an XBM image with the given dimensions
|
||||
void drawXbm(int x, int y, int width, int height, const char *xbm);
|
||||
// Fill circle
|
||||
void fillCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Sets the color of all pixel operations
|
||||
void setColor(int color);
|
||||
// Draw a line horizontally
|
||||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draw a lin vertically
|
||||
void drawVerticalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
|
||||
// a unsigned byte value between 0 and 100
|
||||
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
|
||||
|
||||
// Draw a bitmap in the internal image format
|
||||
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const char *image);
|
||||
|
||||
// Draw a XBM
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const char* xbm);
|
||||
```
|
||||
|
||||
## Text operations
|
||||
|
||||
``` C++
|
||||
// Draws a string at the given location
|
||||
void drawString(int x, int y, String text);
|
||||
void drawString(int16_t x, int16_t y, String text);
|
||||
|
||||
// Draws a String with a maximum width at the given location.
|
||||
// If the given String is wider than the specified width
|
||||
// The text will be wrapped to the next line at a space or dash
|
||||
void drawStringMaxWidth(int x, int y, int maxLineWidth, String text);
|
||||
void drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text);
|
||||
|
||||
// Returns the width of the String with the current
|
||||
// Returns the width of the const char* with the current
|
||||
// font settings
|
||||
int getStringWidth(String text);
|
||||
uint16_t getStringWidth(const char* text, uint16_t length);
|
||||
|
||||
// Convencience method for the const char version
|
||||
uint16_t getStringWidth(String text);
|
||||
|
||||
// Specifies relative to which anchor point
|
||||
// the text is rendered. Available constants:
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT
|
||||
void setTextAlignment(int textAlignment);
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
|
||||
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment);
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// defined in SSD1306Fonts.h:
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
// Or create one with the font tool at http://oleddisplay.squix.ch
|
||||
void setFont(const char *fontData);
|
||||
void setFont(const char* fontData);
|
||||
```
|
||||
|
||||
## Frame Transition Functions
|
||||
## Ui Library (OLEDDisplayUi)
|
||||
|
||||
The Ui Library is used to provide a basic set of Ui elements called, `Frames` and `Overlays`. A `Frame` is used to provide
|
||||
information the default behaviour is to display a `Frame` for a defined time and than move to the next. The library also provides an `Indicator` that will be updated accordingly. An `Overlay` on the other hand is a pieces of information (e.g. a clock) that is displayed always at the same position.
|
||||
|
||||
The Frame Transition functions are a set of functions on top of the basic library. They allow you to easily write frames which will be shifted in regular intervals. The frame animation (including the frame indicators) will only be activated if you define callback functions with setFrameCallacks(..). If no callback methods are defined no indicators will be displayed.
|
||||
|
||||
```C++
|
||||
// Sets the callback methods of the format void method(x,y). As soon as you define the callbacks
|
||||
// the library is in "frame mode" and indicators will be drawn.
|
||||
void setFrameCallbacks(int frameCount, void (*frameCallbacks[])(SSD1306 *display, SSD1306UiState* state,int x, int y));
|
||||
/**
|
||||
* Initialise the display
|
||||
*/
|
||||
void init();
|
||||
|
||||
// Tells the framework to move to the next tick. The
|
||||
// current visible frame callback will be called once
|
||||
// per tick
|
||||
void nextFrameTick(void);
|
||||
/**
|
||||
* Configure the internal used target FPS
|
||||
*/
|
||||
void setTargetFPS(uint8_t fps);
|
||||
|
||||
// Draws the frame indicators. In a normal setup
|
||||
// the framework does this for you
|
||||
void drawIndicators(int frameCount, int activeFrame);
|
||||
/**
|
||||
* Enable automatic transition to next frame after the some time can be configured with
|
||||
* `setTimePerFrame` and `setTimePerTransition`.
|
||||
*/
|
||||
void enableAutoTransition();
|
||||
|
||||
// defines how many ticks a frame should remain visible
|
||||
// This does not include the transition
|
||||
void setFrameWaitTicks(int frameWaitTicks);
|
||||
/**
|
||||
* Disable automatic transition to next frame.
|
||||
*/
|
||||
void disableAutoTransition();
|
||||
|
||||
// Defines how many ticks should be used for a transition
|
||||
void setFrameTransitionTicks(int frameTransitionTicks);
|
||||
/**
|
||||
* Set the direction if the automatic transitioning
|
||||
*/
|
||||
void setAutoTransitionForwards();
|
||||
void setAutoTransitionBackwards();
|
||||
|
||||
// Returns the current state of the internal state machine
|
||||
// Possible values: FRAME_STATE_FIX, FRAME_STATE_TRANSITION
|
||||
// You can use this to detect when there is no transition
|
||||
// on the way to execute operations that would
|
||||
int getFrameState();
|
||||
/**
|
||||
* Set the approx. time a frame is displayed
|
||||
*/
|
||||
void setTimePerFrame(uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the approx. time a transition will take
|
||||
*/
|
||||
void setTimePerTransition(uint16_t time);
|
||||
|
||||
/**
|
||||
* Draw the indicator.
|
||||
* This is the default state for all frames if
|
||||
* the indicator was hidden on the previous frame
|
||||
* it will be slided in.
|
||||
*/
|
||||
void enableIndicator();
|
||||
|
||||
/**
|
||||
* Don't draw the indicator.
|
||||
* This will slide out the indicator
|
||||
* when transitioning to the next frame.
|
||||
*/
|
||||
void disableIndicator();
|
||||
|
||||
/**
|
||||
* Enable drawing of all indicators.
|
||||
*/
|
||||
void enableAllIndicators();
|
||||
|
||||
/**
|
||||
* Disable drawing of all indicators.
|
||||
*/
|
||||
void disableAllIndicators();
|
||||
|
||||
/**
|
||||
* Set the position of the indicator bar.
|
||||
*/
|
||||
void setIndicatorPosition(IndicatorPosition pos);
|
||||
|
||||
/**
|
||||
* Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
|
||||
*/
|
||||
void setIndicatorDirection(IndicatorDirection dir);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbol(const char* symbol);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbol(const char* symbol);
|
||||
|
||||
/**
|
||||
* Configure what animation is used to transition from one frame to another
|
||||
*/
|
||||
void setFrameAnimation(AnimationDirection dir);
|
||||
|
||||
/**
|
||||
* Add frame drawing functions
|
||||
*/
|
||||
void setFrames(FrameCallback* frameFunctions, uint8_t frameCount);
|
||||
|
||||
/**
|
||||
* Add overlays drawing functions that are draw independent of the Frames
|
||||
*/
|
||||
void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount);
|
||||
|
||||
/**
|
||||
* Set the function that will draw each step
|
||||
* in the loading animation
|
||||
*/
|
||||
void setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction);
|
||||
|
||||
/**
|
||||
* Run the loading process
|
||||
*/
|
||||
void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount);
|
||||
|
||||
// Manuell Controll
|
||||
void nextFrame();
|
||||
void previousFrame();
|
||||
|
||||
/**
|
||||
* Switch without transition to frame `frame`.
|
||||
*/
|
||||
void switchToFrame(uint8_t frame);
|
||||
|
||||
/**
|
||||
* Transition to frame `frame`, when the `frame` number is bigger than the current
|
||||
* frame the forward animation will be used, otherwise the backwards animation is used.
|
||||
*/
|
||||
void transitionToFrame(uint8_t frame);
|
||||
|
||||
// State Info
|
||||
OLEDDisplayUiState* getUiState();
|
||||
|
||||
// This needs to be called in the main loop
|
||||
// the returned value is the remaining time (in ms)
|
||||
// you have to draw after drawing to keep the frame budget.
|
||||
int8_t update();
|
||||
```
|
||||
|
||||
## Example: SSD1306Demo
|
||||
@@ -187,3 +379,15 @@ This frame demonstrates the text alignment. The coordinates in the frame show re
|
||||

|
||||
|
||||
This shows how to use define a maximum width after which the driver automatically wraps a word to the next line. This comes in very handy if you have longer texts to display.
|
||||
|
||||
### SPI version
|
||||
|
||||

|
||||
|
||||
This shows the code working on the SPI version of the display. See demo code for ESP8266 pins used.
|
||||
|
||||
## Project using this library
|
||||
|
||||
* [QRCode ESP8266](https://github.com/anunpanya/ESP8266_QRcode) (by @anunpanya)
|
||||
* [Scan I2C](https://github.com/hallard/Scan-I2C-WiFi) (by @hallard)
|
||||
* [Weather Station](https://github.com/squix78/esp8266-weather-station) (by @squix)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SH1106_h
|
||||
#define SH1106_h
|
||||
#include "SH1106Wire.h"
|
||||
|
||||
// For make SH1106 an alias for SH1106Wire
|
||||
typedef SH1106Wire SH1106;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SH1106Brzo_h
|
||||
#define SH1106Brzo_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <brzo_i2c.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SH1106Brzo : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
brzo_i2c_setup(_sda, _scl, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
byte k = 0;
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
|
||||
if (k == 16) {
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k != 0) {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
k = 0;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
if (k != 0) {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
}
|
||||
brzo_i2c_end_transaction();
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
uint8_t command[2] = {0x80 /* command mode */, com};
|
||||
brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED);
|
||||
brzo_i2c_write(command, 2, true);
|
||||
brzo_i2c_end_transaction();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SH1106Spi_h
|
||||
#define SH1106Spi_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
class SH1106Spi : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _rst;
|
||||
uint8_t _dc;
|
||||
|
||||
public:
|
||||
|
||||
SH1106Spi(uint8_t _rst, uint8_t _dc) {
|
||||
this->_rst = _rst;
|
||||
this->_dc = _dc;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
pinMode(_dc, OUTPUT);
|
||||
pinMode(_rst, OUTPUT);
|
||||
|
||||
SPI.begin ();
|
||||
SPI.setClockDivider (SPI_CLOCK_DIV2);
|
||||
|
||||
// Pulse Reset low for 10ms
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(10);
|
||||
digitalWrite(_rst, HIGH);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
#else
|
||||
for (uint8_t y=0; y<DISPLAY_HEIGHT/8; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(0x02);
|
||||
sendCommand(0x10);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
for( uint8_t x=0; x < DISPLAY_WIDTH; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
digitalWrite(_dc, LOW);
|
||||
SPI.transfer(com);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SH1106Wire_h
|
||||
#define SH1106Wire_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define SH1106_SET_PUMP_VOLTAGE 0X30
|
||||
#define SH1106_SET_PUMP_MODE 0XAD
|
||||
#define SH1106_PUMP_ON 0X8B
|
||||
#define SH1106_PUMP_OFF 0X8A
|
||||
//--------------------------------------
|
||||
|
||||
class SH1106Wire : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
Wire.begin(this->_sda, this->_scl);
|
||||
// Let's use ~700khz if ESP8266 is in 160Mhz mode
|
||||
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
|
||||
Wire.setClock(700000);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
byte k = 0;
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
if (k == 0) {
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x40);
|
||||
}
|
||||
Wire.write(buffer[x + y * DISPLAY_WIDTH]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
Wire.endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k != 0) {
|
||||
Wire.endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
||||
Wire.endTransmission();
|
||||
}
|
||||
#else
|
||||
uint8_t * p = &buffer[0];
|
||||
for (uint8_t y=0; y<8; y++) {
|
||||
sendCommand(0xB0+y);
|
||||
sendCommand(0x02);
|
||||
sendCommand(0x10);
|
||||
for( uint8_t x=0; x<8; x++) {
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x40);
|
||||
for (uint8_t k = 0; k < 16; k++) {
|
||||
Wire.write(*p++);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x80);
|
||||
Wire.write(command);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,363 +0,0 @@
|
||||
/**The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 by Daniel Eichhorn
|
||||
|
||||
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.
|
||||
|
||||
See more at http://blog.squix.ch
|
||||
|
||||
Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#include "../esp8266-oled-ssd1306/SSD1306.h"
|
||||
#include <Wire.h>
|
||||
|
||||
|
||||
SSD1306::SSD1306(int i2cAddress, int sda, int sdc) {
|
||||
myI2cAddress = i2cAddress;
|
||||
mySda = sda;
|
||||
mySdc = sdc;
|
||||
}
|
||||
|
||||
void SSD1306::init() {
|
||||
Wire.begin(mySda, mySdc);
|
||||
Wire.setClock(400000);
|
||||
sendInitCommands();
|
||||
resetDisplay();
|
||||
}
|
||||
|
||||
// Local override of init to avoid having to pass the sda and sdc in global section.
|
||||
|
||||
void SSD1306::init(int i2cAddress) {
|
||||
myI2cAddress = i2cAddress;
|
||||
|
||||
Wire.setClock(400000);
|
||||
sendInitCommands();
|
||||
resetDisplay();
|
||||
}
|
||||
|
||||
void SSD1306::resetDisplay(void) {
|
||||
displayOff();
|
||||
clear();
|
||||
display();
|
||||
displayOn();
|
||||
}
|
||||
|
||||
void SSD1306::reconnect() {
|
||||
Wire.begin(mySda, mySdc);
|
||||
}
|
||||
|
||||
void SSD1306::displayOn(void) {
|
||||
sendCommand(0xaf); //display on
|
||||
}
|
||||
|
||||
void SSD1306::displayOff(void) {
|
||||
sendCommand(0xae); //display off
|
||||
}
|
||||
|
||||
void SSD1306::setContrast(char contrast) {
|
||||
sendCommand(0x81);
|
||||
sendCommand(contrast);
|
||||
}
|
||||
|
||||
void SSD1306::flipScreenVertically() {
|
||||
sendCommand(0xA0 | 0x1); //SEGREMAP //Rotate screen 180 deg
|
||||
sendCommand(0xC8); //COMSCANDEC Rotate screen 180 Deg
|
||||
}
|
||||
|
||||
void SSD1306::clear(void) {
|
||||
memset(buffer, 0, (128 * 64 / 8));
|
||||
}
|
||||
|
||||
void SSD1306::display(void) {
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
for (uint16_t i=0; i<(128*64/8); i++) {
|
||||
// send a bunch of data in one xmission
|
||||
Wire.beginTransmission(myI2cAddress);
|
||||
Wire.write(0x40);
|
||||
for (uint8_t x=0; x<16; x++) {
|
||||
Wire.write(buffer[i]);
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
yield();
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SSD1306::setPixel(int x, int y) {
|
||||
if (x >= 0 && x < 128 && y >= 0 && y < 64) {
|
||||
|
||||
switch (myColor) {
|
||||
case WHITE: buffer[x + (y/8)*128] |= (1 << (y&7)); break;
|
||||
case BLACK: buffer[x + (y/8)*128] &= ~(1 << (y&7)); break;
|
||||
case INVERSE: buffer[x + (y/8)*128] ^= (1 << (y&7)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::setChar(int x, int y, unsigned char data) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (bitRead(data, i)) {
|
||||
setPixel(x,y + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
byte SSD1306::utf8ascii(byte ascii) {
|
||||
if ( ascii<128 ) { // Standard ASCII-set 0..0x7F handling
|
||||
lastChar=0;
|
||||
return( ascii );
|
||||
}
|
||||
|
||||
// get previous input
|
||||
byte last = lastChar; // get last char
|
||||
lastChar=ascii; // remember actual character
|
||||
|
||||
switch (last) // conversion depnding on first UTF8-character
|
||||
{ case 0xC2: return (ascii); break;
|
||||
case 0xC3: return (ascii | 0xC0); break;
|
||||
case 0x82: if(ascii==0xAC) return(0x80); // special case Euro-symbol
|
||||
}
|
||||
|
||||
return (0); // otherwise: return zero, if character has to be ignored
|
||||
}
|
||||
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
String SSD1306::utf8ascii(String s) {
|
||||
String r= "";
|
||||
char c;
|
||||
for (int i=0; i<s.length(); i++)
|
||||
{
|
||||
c = utf8ascii(s.charAt(i));
|
||||
if (c!=0) r+=c;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void SSD1306::drawString(int x, int y, String text) {
|
||||
text = utf8ascii(text);
|
||||
unsigned char currentByte;
|
||||
int charX, charY;
|
||||
int currentBitCount;
|
||||
int charCode;
|
||||
int currentCharWidth;
|
||||
int currentCharStartPos;
|
||||
int cursorX = 0;
|
||||
int numberOfChars = pgm_read_byte(myFontData + CHAR_NUM_POS);
|
||||
// iterate over string
|
||||
int firstChar = pgm_read_byte(myFontData + FIRST_CHAR_POS);
|
||||
int charHeight = pgm_read_byte(myFontData + HEIGHT_POS);
|
||||
int currentCharByteNum = 0;
|
||||
int startX = 0;
|
||||
int startY = y;
|
||||
|
||||
if (myTextAlignment == TEXT_ALIGN_LEFT) {
|
||||
startX = x;
|
||||
} else if (myTextAlignment == TEXT_ALIGN_CENTER) {
|
||||
int width = getStringWidth(text);
|
||||
startX = x - width / 2;
|
||||
} else if (myTextAlignment == TEXT_ALIGN_RIGHT) {
|
||||
int width = getStringWidth(text);
|
||||
startX = x - width;
|
||||
}
|
||||
|
||||
for (int j=0; j < text.length(); j++) {
|
||||
|
||||
charCode = text.charAt(j)-0x20;
|
||||
|
||||
currentCharWidth = pgm_read_byte(myFontData + CHAR_WIDTH_START_POS + charCode);
|
||||
// Jump to font data beginning
|
||||
currentCharStartPos = CHAR_WIDTH_START_POS + numberOfChars;
|
||||
|
||||
for (int m = 0; m < charCode; m++) {
|
||||
|
||||
currentCharStartPos += pgm_read_byte(myFontData + CHAR_WIDTH_START_POS + m) * charHeight / 8 + 1;
|
||||
}
|
||||
|
||||
currentCharByteNum = ((charHeight * currentCharWidth) / 8) + 1;
|
||||
// iterate over all bytes of character
|
||||
for (int i = 0; i < currentCharByteNum; i++) {
|
||||
|
||||
currentByte = pgm_read_byte(myFontData + currentCharStartPos + i);
|
||||
//Serial.println(String(charCode) + ", " + String(currentCharWidth) + ", " + String(currentByte));
|
||||
// iterate over all bytes of character
|
||||
for(int bit = 0; bit < 8; bit++) {
|
||||
//int currentBit = bitRead(currentByte, bit);
|
||||
|
||||
currentBitCount = i * 8 + bit;
|
||||
|
||||
charX = currentBitCount % currentCharWidth;
|
||||
charY = currentBitCount / currentCharWidth;
|
||||
|
||||
if (bitRead(currentByte, bit)) {
|
||||
setPixel(startX + cursorX + charX, startY + charY);
|
||||
}
|
||||
|
||||
}
|
||||
yield();
|
||||
}
|
||||
cursorX += currentCharWidth;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::drawStringMaxWidth(int x, int y, int maxLineWidth, String text) {
|
||||
int currentLineWidth = 0;
|
||||
int startsAt = 0;
|
||||
int endsAt = 0;
|
||||
int lineNumber = 0;
|
||||
char currentChar = ' ';
|
||||
int lineHeight = pgm_read_byte(myFontData + HEIGHT_POS);
|
||||
String currentLine = "";
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
currentChar = text.charAt(i);
|
||||
if (currentChar == ' ' || currentChar == '-') {
|
||||
String lineCandidate = text.substring(startsAt, i);
|
||||
if (getStringWidth(lineCandidate) <= maxLineWidth) {
|
||||
endsAt = i;
|
||||
} else {
|
||||
|
||||
drawString(x, y + lineNumber * lineHeight, text.substring(startsAt, endsAt));
|
||||
lineNumber++;
|
||||
startsAt = endsAt + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
drawString(x, y + lineNumber * lineHeight, text.substring(startsAt));
|
||||
}
|
||||
|
||||
int SSD1306::getStringWidth(String text) {
|
||||
text = utf8ascii(text);
|
||||
int stringWidth = 0;
|
||||
char charCode;
|
||||
for (int j=0; j < text.length(); j++) {
|
||||
charCode = text.charAt(j)-0x20;
|
||||
stringWidth += pgm_read_byte(myFontData + CHAR_WIDTH_START_POS + charCode);
|
||||
}
|
||||
return stringWidth;
|
||||
}
|
||||
|
||||
void SSD1306::setTextAlignment(int textAlignment) {
|
||||
myTextAlignment = textAlignment;
|
||||
}
|
||||
|
||||
void SSD1306::setFont(const char *fontData) {
|
||||
myFontData = fontData;
|
||||
}
|
||||
|
||||
void SSD1306::drawBitmap(int x, int y, int width, int height, const char *bitmap) {
|
||||
for (int i = 0; i < width * height / 8; i++ ){
|
||||
unsigned char charColumn = 255 - pgm_read_byte(bitmap + i);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int targetX = i % width + x;
|
||||
int targetY = (i / (width)) * 8 + j + y;
|
||||
if (bitRead(charColumn, j)) {
|
||||
setPixel(targetX, targetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::setColor(int color) {
|
||||
myColor = color;
|
||||
}
|
||||
|
||||
void SSD1306::drawRect(int x, int y, int width, int height) {
|
||||
for (int i = x; i < x + width; i++) {
|
||||
setPixel(i, y);
|
||||
setPixel(i, y + height);
|
||||
}
|
||||
for (int i = y; i < y + height; i++) {
|
||||
setPixel(x, i);
|
||||
setPixel(x + width, i);
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::fillRect(int x, int y, int width, int height) {
|
||||
for (int i = x; i < x + width; i++) {
|
||||
for (int j = y; j < y + height; j++) {
|
||||
setPixel(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::drawXbm(int x, int y, int width, int height, const char *xbm) {
|
||||
if (width % 8 != 0) {
|
||||
width = ((width / 8) + 1) * 8;
|
||||
}
|
||||
for (int i = 0; i < width * height / 8; i++ ){
|
||||
unsigned char charColumn = pgm_read_byte(xbm + i);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int targetX = (i * 8 + j) % width + x;
|
||||
int targetY = (8 * i / (width)) + y;
|
||||
if (bitRead(charColumn, j)) {
|
||||
setPixel(targetX, targetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::sendCommand(unsigned char com) {
|
||||
Wire.beginTransmission(myI2cAddress); //begin transmitting
|
||||
Wire.write(0x80); //command mode
|
||||
Wire.write(com);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
}
|
||||
|
||||
void SSD1306::sendInitCommands(void) {
|
||||
sendCommand(DISPLAYOFF);
|
||||
sendCommand(NORMALDISPLAY);
|
||||
sendCommand(SETDISPLAYCLOCKDIV);
|
||||
sendCommand(0x80);
|
||||
sendCommand(SETMULTIPLEX);
|
||||
sendCommand(0x3F);
|
||||
sendCommand(SETDISPLAYOFFSET);
|
||||
sendCommand(0x00);
|
||||
sendCommand(SETSTARTLINE | 0x00);
|
||||
sendCommand(CHARGEPUMP);
|
||||
sendCommand(0x14);
|
||||
sendCommand(MEMORYMODE);
|
||||
sendCommand(0x00);
|
||||
sendCommand(SEGREMAP);
|
||||
sendCommand(COMSCANINC);
|
||||
sendCommand(SETCOMPINS);
|
||||
sendCommand(0x12);
|
||||
sendCommand(SETCONTRAST);
|
||||
sendCommand(0xCF);
|
||||
sendCommand(SETPRECHARGE);
|
||||
sendCommand(0xF1);
|
||||
sendCommand(SETVCOMDETECT);
|
||||
sendCommand(0x40);
|
||||
sendCommand(DISPLAYALLON_RESUME);
|
||||
sendCommand(NORMALDISPLAY);
|
||||
sendCommand(0x2e); // stop scroll
|
||||
sendCommand(DISPLAYON);
|
||||
}
|
||||
@@ -1,176 +1,36 @@
|
||||
/**The MIT License (MIT)
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
Copyright (c) 2015 by Daniel Eichhorn
|
||||
#ifndef SSD1306_h
|
||||
#define SSD1306_h
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
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:
|
||||
// For legacy support make SSD1306 an alias for SSD1306
|
||||
typedef SSD1306Wire SSD1306;
|
||||
|
||||
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.
|
||||
|
||||
See more at http://blog.squix.ch
|
||||
|
||||
Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "SSD1306Fonts.h"
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define INVERSE 2
|
||||
|
||||
#define WIDTH_POS 0
|
||||
#define HEIGHT_POS 1
|
||||
#define FIRST_CHAR_POS 2
|
||||
#define CHAR_NUM_POS 3
|
||||
#define CHAR_WIDTH_START_POS 4
|
||||
|
||||
#define TEXT_ALIGN_LEFT 0
|
||||
#define TEXT_ALIGN_CENTER 1
|
||||
#define TEXT_ALIGN_RIGHT 2
|
||||
|
||||
#define CHARGEPUMP 0x8D
|
||||
#define COLUMNADDR 0x21
|
||||
#define COMSCANDEC 0xC8
|
||||
#define COMSCANINC 0xC0
|
||||
#define DISPLAYALLON 0xA5
|
||||
#define DISPLAYALLON_RESUME 0xA4
|
||||
#define DISPLAYOFF 0xAE
|
||||
#define DISPLAYON 0xAF
|
||||
#define EXTERNALVCC 0x1
|
||||
#define INVERTDISPLAY 0xA7
|
||||
#define MEMORYMODE 0x20
|
||||
#define NORMALDISPLAY 0xA6
|
||||
#define PAGEADDR 0x22
|
||||
#define SEGREMAP 0xA0
|
||||
#define SETCOMPINS 0xDA
|
||||
#define SETCONTRAST 0x81
|
||||
#define SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SETDISPLAYOFFSET 0xD3
|
||||
#define SETHIGHCOLUMN 0x10
|
||||
#define SETLOWCOLUMN 0x00
|
||||
#define SETMULTIPLEX 0xA8
|
||||
#define SETPRECHARGE 0xD9
|
||||
#define SETSEGMENTREMAP 0xA1
|
||||
#define SETSTARTLINE 0x40
|
||||
#define SETVCOMDETECT 0xDB
|
||||
#define SWITCHCAPVCC 0x2
|
||||
|
||||
class SSD1306 {
|
||||
|
||||
private:
|
||||
int myI2cAddress;
|
||||
int mySda;
|
||||
int mySdc;
|
||||
uint8_t buffer[128 * 64 / 8];
|
||||
int myTextAlignment = TEXT_ALIGN_LEFT;
|
||||
int myColor = WHITE;
|
||||
byte lastChar;
|
||||
const char *myFontData = ArialMT_Plain_10;
|
||||
|
||||
public:
|
||||
// Create the display object connected to pin sda and sdc
|
||||
SSD1306(int i2cAddress, int sda, int sdc);
|
||||
|
||||
// Initialize the display
|
||||
void init();
|
||||
|
||||
// Initialize the display - Neil's version to setting of address
|
||||
void init(int i2cAddress); //local override to allow init to set the address
|
||||
|
||||
// Cycle through the initialization
|
||||
void resetDisplay(void);
|
||||
|
||||
// Connect again to the display through I2C
|
||||
void reconnect(void);
|
||||
|
||||
// Turn the display on
|
||||
void displayOn(void);
|
||||
|
||||
// Turn the display offs
|
||||
void displayOff(void);
|
||||
|
||||
// Clear the local pixel buffer
|
||||
void clear(void);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
void display(void);
|
||||
|
||||
// Set display contrast
|
||||
void setContrast(char contrast);
|
||||
|
||||
// Turn the display upside down
|
||||
void flipScreenVertically();
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
void sendCommand(unsigned char com);
|
||||
|
||||
// Send all the init commands
|
||||
void sendInitCommands(void);
|
||||
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int x, int y);
|
||||
|
||||
// Draw 8 bits at the given position
|
||||
void setChar(int x, int y, unsigned char data);
|
||||
|
||||
// Draw the border of a rectangle at the given location
|
||||
void drawRect(int x, int y, int width, int height);
|
||||
|
||||
// Fill the rectangle
|
||||
void fillRect(int x, int y, int width, int height);
|
||||
|
||||
// Draw a bitmap with the given dimensions
|
||||
void drawBitmap(int x, int y, int width, int height, const char *bitmap);
|
||||
|
||||
// Draw an XBM image with the given dimensions
|
||||
void drawXbm(int x, int y, int width, int height, const char *xbm);
|
||||
|
||||
// Sets the color of all pixel operations
|
||||
void setColor(int color);
|
||||
|
||||
// converts utf8 characters to extended ascii
|
||||
// taken from http://playground.arduino.cc/Main/Utf8ascii
|
||||
byte utf8ascii(byte ascii);
|
||||
|
||||
// converts utf8 string to extended ascii
|
||||
// taken from http://playground.arduino.cc/Main/Utf8ascii
|
||||
String utf8ascii(String s);
|
||||
|
||||
// Draws a string at the given location
|
||||
void drawString(int x, int y, String text);
|
||||
|
||||
// Draws a String with a maximum width at the given location.
|
||||
// If the given String is wider than the specified width
|
||||
// The text will be wrapped to the next line at a space or dash
|
||||
void drawStringMaxWidth(int x, int y, int maxLineWidth, String text);
|
||||
|
||||
// Returns the width of the String with the current
|
||||
// font settings
|
||||
int getStringWidth(String text);
|
||||
|
||||
// Specifies relative to which anchor point
|
||||
// the text is rendered. Available constants:
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT
|
||||
void setTextAlignment(int textAlignment);
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// defined in SSD1306Fonts.h:
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
void setFont(const char *fontData);
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Brzo_h
|
||||
#define SSD1306Brzo_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <brzo_i2c.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SSD1306Brzo : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SSD1306Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
brzo_i2c_setup(_sda, _scl, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
sendCommand(maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
byte k = 0;
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
|
||||
if (k == 16) {
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
brzo_i2c_end_transaction();
|
||||
#else
|
||||
// No double buffering
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i++) {
|
||||
for (uint8_t x=1; x<17; x++) {
|
||||
sendBuffer[x] = buffer[i];
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_end_transaction();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
uint8_t command[2] = {0x80 /* command mode */, com};
|
||||
brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED);
|
||||
brzo_i2c_write(command, 2, true);
|
||||
brzo_i2c_end_transaction();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Spi_h
|
||||
#define SSD1306Spi_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SSD1306Spi : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _rst;
|
||||
uint8_t _dc;
|
||||
uint8_t _cs;
|
||||
|
||||
public:
|
||||
SSD1306Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs) {
|
||||
this->_rst = _rst;
|
||||
this->_dc = _dc;
|
||||
this->_cs = _cs;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
pinMode(_dc, OUTPUT);
|
||||
pinMode(_cs, OUTPUT);
|
||||
pinMode(_rst, OUTPUT);
|
||||
|
||||
SPI.begin ();
|
||||
SPI.setClockDivider (SPI_CLOCK_DIV2);
|
||||
|
||||
// Pulse Reset low for 10ms
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(10);
|
||||
digitalWrite(_rst, HIGH);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
sendCommand(maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
digitalWrite(_cs, LOW);
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#else
|
||||
// No double buffering
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
digitalWrite(_cs, LOW);
|
||||
for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i++) {
|
||||
SPI.transfer(buffer[i]);
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, LOW);
|
||||
digitalWrite(_cs, LOW);
|
||||
SPI.transfer(com);
|
||||
digitalWrite(_cs, HIGH);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,247 +0,0 @@
|
||||
#include "SSD1306Ui.h"
|
||||
|
||||
|
||||
SSD1306Ui::SSD1306Ui(SSD1306 *display) {
|
||||
this->display = display;
|
||||
}
|
||||
|
||||
void SSD1306Ui::init() {
|
||||
this->display->init();
|
||||
}
|
||||
|
||||
void SSD1306Ui::setTargetFPS(byte fps){
|
||||
int oldInterval = this->updateInterval;
|
||||
this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
|
||||
|
||||
// Calculate new ticksPerFrame
|
||||
float changeRatio = oldInterval / this->updateInterval;
|
||||
this->ticksPerFrame *= changeRatio;
|
||||
this->ticksPerTransition *= changeRatio;
|
||||
}
|
||||
|
||||
// -/------ Automatic controll ------\-
|
||||
|
||||
void SSD1306Ui::enableAutoTransition(){
|
||||
this->autoTransition = true;
|
||||
}
|
||||
void SSD1306Ui::disableAutoTransition(){
|
||||
this->autoTransition = false;
|
||||
}
|
||||
void SSD1306Ui::setAutoTransitionForwards(){
|
||||
this->frameTransitionDirection = 1;
|
||||
}
|
||||
void SSD1306Ui::setAutoTransitionBackwards(){
|
||||
this->frameTransitionDirection = 1;
|
||||
}
|
||||
void SSD1306Ui::setTimePerFrame(int time){
|
||||
this->ticksPerFrame = (int) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
void SSD1306Ui::setTimePerTransition(int time){
|
||||
this->ticksPerTransition = (int) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
|
||||
|
||||
// -/------ Customize indicator position and style -------\-
|
||||
void SSD1306Ui::setIndicatorPosition(IndicatorPosition pos) {
|
||||
this->indicatorPosition = pos;
|
||||
this->dirty = true;
|
||||
}
|
||||
void SSD1306Ui::setIndicatorDirection(IndicatorDirection dir) {
|
||||
this->indicatorDirection = dir;
|
||||
}
|
||||
void SSD1306Ui::setActiveSymbole(const char* symbole) {
|
||||
this->activeSymbole = symbole;
|
||||
this->dirty = true;
|
||||
}
|
||||
void SSD1306Ui::setInactiveSymbole(const char* symbole) {
|
||||
this->inactiveSymbole = symbole;
|
||||
this->dirty = true;
|
||||
}
|
||||
|
||||
|
||||
// -/----- Frame settings -----\-
|
||||
void SSD1306Ui::setFrameAnimation(AnimationDirection dir) {
|
||||
this->frameAnimationDirection = dir;
|
||||
}
|
||||
void SSD1306Ui::setFrames(FrameCallback* frameFunctions, int frameCount) {
|
||||
this->frameCount = frameCount;
|
||||
this->frameFunctions = frameFunctions;
|
||||
}
|
||||
|
||||
// -/----- Overlays ------\-
|
||||
void SSD1306Ui::setOverlays(OverlayCallback* overlayFunctions, int overlayCount){
|
||||
this->overlayCount = overlayCount;
|
||||
this->overlayFunctions = overlayFunctions;
|
||||
}
|
||||
|
||||
|
||||
// -/----- Manuel control -----\-
|
||||
void SSD1306Ui::nextFrame() {
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->frameTransitionDirection = 1;
|
||||
}
|
||||
void SSD1306Ui::previousFrame() {
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->frameTransitionDirection = -1;
|
||||
}
|
||||
|
||||
|
||||
// -/----- State information -----\-
|
||||
SSD1306UiState SSD1306Ui::getUiState(){
|
||||
return this->state;
|
||||
}
|
||||
|
||||
|
||||
int SSD1306Ui::update(){
|
||||
int timeBudget = this->updateInterval - (millis() - this->state.lastUpdate);
|
||||
if ( timeBudget <= 0) {
|
||||
// Implement frame skipping to ensure time budget is keept
|
||||
if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil(-timeBudget / this->updateInterval);
|
||||
|
||||
this->state.lastUpdate = millis();
|
||||
this->tick();
|
||||
}
|
||||
return timeBudget;
|
||||
}
|
||||
|
||||
|
||||
void SSD1306Ui::tick() {
|
||||
this->state.ticksSinceLastStateSwitch++;
|
||||
|
||||
switch (this->state.frameState) {
|
||||
case IN_TRANSITION:
|
||||
this->dirty = true;
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = getNextFrameNumber();
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
}
|
||||
break;
|
||||
case FIXED:
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){
|
||||
if (this->autoTransition){
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->dirty = true;
|
||||
}
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->dirty) {
|
||||
this->dirty = false;
|
||||
this->display->clear();
|
||||
this->drawIndicator();
|
||||
this->drawFrame();
|
||||
this->drawOverlays();
|
||||
this->display->display();
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306Ui::drawFrame(){
|
||||
switch (this->state.frameState){
|
||||
case IN_TRANSITION: {
|
||||
float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
|
||||
int x, y, x1, y1;
|
||||
switch(this->frameAnimationDirection){
|
||||
case SLIDE_LEFT:
|
||||
x = -128 * progress;
|
||||
y = 0;
|
||||
x1 = x + 128;
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_RIGHT:
|
||||
x = 128 * progress;
|
||||
y = 0;
|
||||
x1 = x - 128;
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_UP:
|
||||
x = 0;
|
||||
y = -64 * progress;
|
||||
x1 = 0;
|
||||
y1 = y + 64;
|
||||
break;
|
||||
case SLIDE_DOWN:
|
||||
x = 0;
|
||||
y = 64 * progress;
|
||||
x1 = 0;
|
||||
y1 = y - 64;
|
||||
break;
|
||||
}
|
||||
|
||||
// Invert animation if direction is reversed.
|
||||
int dir = frameTransitionDirection >= 0 ? 1 : -1;
|
||||
x *= dir; y *= dir; x1 *= dir; y1 *= dir;
|
||||
|
||||
this->dirty |= (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y);
|
||||
this->dirty |= (this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1);
|
||||
break;
|
||||
}
|
||||
case FIXED:
|
||||
this->dirty |= (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306Ui::drawIndicator() {
|
||||
byte posOfCurrentFrame;
|
||||
|
||||
switch (this->indicatorDirection){
|
||||
case LEFT_RIGHT:
|
||||
posOfCurrentFrame = this->state.currentFrame;
|
||||
break;
|
||||
case RIGHT_LEFT:
|
||||
posOfCurrentFrame = (this->frameCount - 1) - this->state.currentFrame;
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < this->frameCount; i++) {
|
||||
|
||||
const char *image;
|
||||
|
||||
if (posOfCurrentFrame == i) {
|
||||
image = this->activeSymbole;
|
||||
} else {
|
||||
image = this->inactiveSymbole;
|
||||
}
|
||||
|
||||
int x,y;
|
||||
switch (this->indicatorPosition){
|
||||
case TOP:
|
||||
y = 0;
|
||||
x = 64 - (12 * frameCount / 2) + 12 * i;
|
||||
break;
|
||||
case BOTTOM:
|
||||
y = 56;
|
||||
x = 64 - (12 * frameCount / 2) + 12 * i;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = 120;
|
||||
y = 32 - (12 * frameCount / 2) + 12 * i;
|
||||
break;
|
||||
case LEFT:
|
||||
x = 0;
|
||||
y = 32 - (12 * frameCount / 2) + 12 * i;
|
||||
break;
|
||||
}
|
||||
|
||||
this->display->drawXbm(x, y, 8, 8, image);
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306Ui::drawOverlays() {
|
||||
for (int i=0;i<this->overlayCount;i++){
|
||||
this->dirty |= (this->overlayFunctions[i])(this->display, &this->state);
|
||||
}
|
||||
}
|
||||
|
||||
int SSD1306Ui::getNextFrameNumber(){
|
||||
int nextFrame = (this->state.currentFrame + this->frameTransitionDirection) % this->frameCount;
|
||||
if (nextFrame < 0){
|
||||
nextFrame = this->frameCount + nextFrame;
|
||||
}
|
||||
return nextFrame;
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
/**The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 by Fabrice Weinberg
|
||||
|
||||
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.
|
||||
|
||||
Credits for parts of this code go to Daniel Eichhorn
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../esp8266-oled-ssd1306/SSD1306.h"
|
||||
|
||||
enum AnimationDirection {
|
||||
SLIDE_UP,
|
||||
SLIDE_DOWN,
|
||||
SLIDE_LEFT,
|
||||
SLIDE_RIGHT
|
||||
};
|
||||
|
||||
enum IndicatorPosition {
|
||||
TOP,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
LEFT
|
||||
};
|
||||
|
||||
enum IndicatorDirection {
|
||||
LEFT_RIGHT,
|
||||
RIGHT_LEFT
|
||||
};
|
||||
|
||||
enum FrameState {
|
||||
IN_TRANSITION,
|
||||
FIXED
|
||||
};
|
||||
|
||||
const char ANIMATION_activeSymbole[] PROGMEM = {
|
||||
0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
|
||||
};
|
||||
|
||||
const char ANIMATION_inactiveSymbole[] PROGMEM = {
|
||||
0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
|
||||
};
|
||||
|
||||
|
||||
// Structure of the UiState
|
||||
struct SSD1306UiState {
|
||||
int lastUpdate = 0;
|
||||
int ticksSinceLastStateSwitch = 0;
|
||||
|
||||
FrameState frameState = FIXED;
|
||||
int currentFrame = 0;
|
||||
};
|
||||
|
||||
typedef bool (*FrameCallback)(SSD1306 *display, SSD1306UiState* state, int x, int y);
|
||||
typedef bool (*OverlayCallback)(SSD1306 *display, SSD1306UiState* state);
|
||||
|
||||
class SSD1306Ui {
|
||||
private:
|
||||
SSD1306 *display;
|
||||
|
||||
// Global dirty flag to indicate that the display needs to be redraw.
|
||||
bool dirty = true;
|
||||
|
||||
// Symboles for the Indicator
|
||||
IndicatorPosition indicatorPosition = BOTTOM;
|
||||
IndicatorDirection indicatorDirection = LEFT_RIGHT;
|
||||
|
||||
const char* activeSymbole = ANIMATION_activeSymbole;
|
||||
const char* inactiveSymbole = ANIMATION_inactiveSymbole;
|
||||
|
||||
// Values for the Frames
|
||||
AnimationDirection frameAnimationDirection = SLIDE_RIGHT;
|
||||
|
||||
int frameTransitionDirection = 1;
|
||||
|
||||
int ticksPerFrame = 151; // ~ 5000ms at 30 FPS
|
||||
int ticksPerTransition = 15; // ~ 500ms at 30 FPS
|
||||
|
||||
bool autoTransition = true;
|
||||
|
||||
FrameCallback* frameFunctions;
|
||||
int frameCount = 0;
|
||||
|
||||
// Values for Overlays
|
||||
OverlayCallback* overlayFunctions;
|
||||
int overlayCount = 0;
|
||||
|
||||
// UI State
|
||||
SSD1306UiState state;
|
||||
|
||||
// Bookeeping for update
|
||||
int updateInterval = 33;
|
||||
|
||||
int getNextFrameNumber();
|
||||
void drawIndicator();
|
||||
void drawFrame();
|
||||
void drawOverlays();
|
||||
void tick();
|
||||
|
||||
public:
|
||||
|
||||
SSD1306Ui(SSD1306 *display);
|
||||
|
||||
/**
|
||||
* Initialise the display
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Configure the internal used target FPS
|
||||
*/
|
||||
void setTargetFPS(byte fps);
|
||||
|
||||
// Automatic Controll
|
||||
/**
|
||||
* Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`.
|
||||
*/
|
||||
void enableAutoTransition();
|
||||
|
||||
/**
|
||||
* Disable automatic transition to next frame.
|
||||
*/
|
||||
void disableAutoTransition();
|
||||
|
||||
/**
|
||||
* Set the direction if the automatic transitioning
|
||||
*/
|
||||
void setAutoTransitionForwards();
|
||||
void setAutoTransitionBackwards();
|
||||
|
||||
/**
|
||||
* Set the approx. time a frame is displayed
|
||||
*/
|
||||
void setTimePerFrame(int time);
|
||||
|
||||
/**
|
||||
* Set the approx. time a transition will take
|
||||
*/
|
||||
void setTimePerTransition(int time);
|
||||
|
||||
// Customize indicator position and style
|
||||
/**
|
||||
* Set the position of the indicator bar.
|
||||
*/
|
||||
void setIndicatorPosition(IndicatorPosition pos);
|
||||
|
||||
/**
|
||||
* Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
|
||||
*/
|
||||
void setIndicatorDirection(IndicatorDirection dir);
|
||||
|
||||
/**
|
||||
* Set the symbole to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbole(const char* symbole);
|
||||
|
||||
/**
|
||||
* Set the symbole to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbole(const char* symbole);
|
||||
|
||||
// Frame settings
|
||||
|
||||
/**
|
||||
* Configure what animation is used to transition from one frame to another
|
||||
*/
|
||||
void setFrameAnimation(AnimationDirection dir);
|
||||
|
||||
/**
|
||||
* Add frame drawing functions
|
||||
*/
|
||||
void setFrames(FrameCallback* frameFunctions, int frameCount);
|
||||
|
||||
// Overlay
|
||||
|
||||
/**
|
||||
* Add overlays drawing functions that are draw independent of the Frames
|
||||
*/
|
||||
void setOverlays(OverlayCallback* overlayFunctions, int overlayCount);
|
||||
|
||||
// Manuell Controll
|
||||
void nextFrame();
|
||||
void previousFrame();
|
||||
|
||||
// State Info
|
||||
SSD1306UiState getUiState();
|
||||
|
||||
int update();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Wire_h
|
||||
#define SSD1306Wire_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <Wire.h>
|
||||
|
||||
class SSD1306Wire : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SSD1306Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
Wire.begin(this->_sda, this->_scl);
|
||||
// Let's use ~700khz if ESP8266 is in 160Mhz mode
|
||||
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
|
||||
Wire.setClock(700000);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~0;
|
||||
uint8_t maxBoundX = 0;
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == ~0) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
sendCommand(maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
byte k = 0;
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
if (k == 0) {
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x40);
|
||||
}
|
||||
Wire.write(buffer[x + y * DISPLAY_WIDTH]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
Wire.endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
||||
Wire.endTransmission();
|
||||
}
|
||||
#else
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
for (uint16_t i=0; i < DISPLAY_BUFFER_SIZE; i++) {
|
||||
Wire.beginTransmission(this->_address);
|
||||
Wire.write(0x40);
|
||||
for (uint8_t x = 0; x < 16; x++) {
|
||||
Wire.write(buffer[i]);
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
Wire.endTransmission();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x80);
|
||||
Wire.write(command);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
# Upgrade from 2.0 to 3.0
|
||||
|
||||
While developing version 3.0 we made some breaking changes to the public
|
||||
API of this library. This document will help you update your code to work with
|
||||
version 3.0
|
||||
|
||||
## Font Definitions
|
||||
|
||||
To get better performance and a smaller font definition format, we change the memory
|
||||
layout of the font definition format. If you are using custom fonts not included in
|
||||
this library we updated the font generator [here](http://oleddisplay.squix.ch/#/home).
|
||||
Please update your fonts to be working with 3.0 by selecting the respective version in the dropdown.
|
||||
|
||||
|
||||
## Architectural Changes
|
||||
|
||||
To become a more versatile library for the SSD1306 chipset we abstracted the
|
||||
hardware connection into subclasses of the base display class now called `OLEDDisplay`.
|
||||
This library is currently shipping with three implementations:
|
||||
|
||||
* `SSD1306Wire` implementing the I2C protocol using the Wire Library.
|
||||
* `SSD1306Brzo` implementing the I2C protocol using the faster [`brzo_i2c`](https://github.com/pasko-zh/brzo_i2c) library.
|
||||
* `SSD1306Spi` implementing the SPI protocol.
|
||||
|
||||
To keep backwards compatiblity with the old API `SSD1306` is an alias of `SSD1306Wire`.
|
||||
If you are not using the UI components you don't have to change anything to keep your code working.
|
||||
|
||||
## Name Changes
|
||||
|
||||
[Naming things is hard](http://martinfowler.com/bliki/TwoHardThings.html), to better reflect our intention with this library
|
||||
we changed the name of the base class to `OLEDDisplay` and the UI library accordingly to `OLEDDisplayUi`.
|
||||
As a consequence the type definitions of all frame and overlay related functions changed.
|
||||
This means that you have to update all your frame drawing callbacks from:
|
||||
|
||||
```c
|
||||
bool frame1(SSD1306 *display, SSD1306UiState* state, int x, int y);
|
||||
```
|
||||
|
||||
too
|
||||
|
||||
```c
|
||||
void frame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
|
||||
```
|
||||
|
||||
And your overlay drawing functions from:
|
||||
|
||||
```c
|
||||
bool overlay1(SSD1306 *display, SSD1306UiState* state);
|
||||
```
|
||||
|
||||
too
|
||||
|
||||
```c
|
||||
void overlay1(OLEDDisplay *display, OLEDDisplayUiState* state);
|
||||
```
|
||||
|
||||
## New Features
|
||||
|
||||
### Loading Animation
|
||||
|
||||
While using this library ourself we noticed a pattern emerging. We want to drawing
|
||||
a loading progress while connecting to WiFi and updating weather data etc.
|
||||
|
||||
The simplest thing was to add the function `drawProgressBar(x, y, width, height, progress)`
|
||||
,where `progress` is between `0` and `100`, right to the `OLEDDisplay` class.
|
||||
|
||||
But we didn't stop there. We added a new feature to the `OLEDDisplayUi` called `LoadingStages`.
|
||||
You can define your loading process like this:
|
||||
|
||||
```c++
|
||||
LoadingStage loadingStages[] = {
|
||||
{
|
||||
.process = "Connect to WiFi",
|
||||
.callback = []() {
|
||||
// Connect to WiFi
|
||||
}
|
||||
},
|
||||
{
|
||||
.process = "Get time from NTP",
|
||||
.callback = []() {
|
||||
// Get current time via NTP
|
||||
}
|
||||
}
|
||||
// more steps
|
||||
};
|
||||
|
||||
int LOADING_STAGES_COUNT = sizeof(loadingStages) / sizeof(LoadingStage);
|
||||
```
|
||||
|
||||
After defining your array of `LoadingStages` you can then run the loading process by using
|
||||
`ui.runLoadingProcess(loadingStages, LOADING_STAGES_COUNT)`. This will give you a
|
||||
nice little loading animation you can see in the beginning of [this](https://vimeo.com/168362918)
|
||||
video.
|
||||
|
||||
To further customize this you are free to define your own `LoadingDrawFunction` like this:
|
||||
|
||||
```c
|
||||
void myLoadingDraw(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
// stage->process contains the text of the current progress e.q. "Connect to WiFi"
|
||||
display->drawString(64, 18, stage->process);
|
||||
// you could just print the current process without the progress bar
|
||||
display->drawString(64, 28, progress);
|
||||
}
|
||||
```
|
||||
|
||||
After defining a function like that, you can pass it to the Ui library by use
|
||||
`ui.setLoadingDrawFunction(myLoadingDraw)`.
|
||||
|
||||
|
||||
### Text Logging
|
||||
|
||||
It is always useful to display some text on the display without worrying to much
|
||||
where it goes and managing it. In 3.0 we made the `OLEDDisplay` class implement
|
||||
[`Print`](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h)
|
||||
so you can use it like you would use `Serial`. We calls this feature `LogBuffer`
|
||||
and the only thing you have to do is to define how many lines you want to display
|
||||
and how many characters there are on average on each. This is done by calling
|
||||
`setLogBuffer(lines, chars);`. If there is not enough memory the function will
|
||||
return false.
|
||||
|
||||
After that you can draw the `LogBuffer` anywhere you want by calling `drawLogBuffer(x, y)`.
|
||||
(Note: You have to call `display()` to update the screen)
|
||||
We made a [video](https://www.youtube.com/watch?v=8Fiss77A3TE) showing this feature in action.
|
||||
@@ -1,151 +0,0 @@
|
||||
/**The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 by Daniel Eichhorn
|
||||
|
||||
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.
|
||||
|
||||
See more at http://blog.squix.ch
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include "SSD1306.h"
|
||||
#include "SSD1306Ui.h"
|
||||
#include "images.h"
|
||||
|
||||
// Initialize the oled display for address 0x3c
|
||||
// sda-pin=14 and sdc-pin=12
|
||||
SSD1306 display(0x3c, D3, D4);
|
||||
SSD1306Ui ui ( &display );
|
||||
|
||||
// this array keeps function pointers to all frames
|
||||
// frames are the single views that slide from right to left
|
||||
bool (*frames[])(SSD1306 *display, SSD1306UiState* state, int x, int y) = { drawFrame1, drawFrame2, drawFrame3, drawFrame4 };
|
||||
|
||||
// how many frames are there?
|
||||
int frameCount = 4;
|
||||
|
||||
bool (*overlays[])(SSD1306 *display, SSD1306UiState* state) = { msOverlay };
|
||||
int overlaysCount = 1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
ui.setTargetFPS(30);
|
||||
|
||||
ui.setActiveSymbole(activeSymbole);
|
||||
ui.setInactiveSymbole(inactiveSymbole);
|
||||
|
||||
// You can change this to
|
||||
// TOP, LEFT, BOTTOM, RIGHT
|
||||
ui.setIndicatorPosition(BOTTOM);
|
||||
|
||||
// Defines where the first frame is located in the bar.
|
||||
ui.setIndicatorDirection(LEFT_RIGHT);
|
||||
|
||||
// You can change the transition that is used
|
||||
// SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN
|
||||
ui.setFrameAnimation(SLIDE_LEFT);
|
||||
|
||||
// Add frames
|
||||
ui.setFrames(frames, frameCount);
|
||||
|
||||
// Add overlays
|
||||
ui.setOverlays(overlays, overlaysCount);
|
||||
|
||||
// Inital UI takes care of initalising the display too.
|
||||
ui.init();
|
||||
|
||||
display.flipScreenVertically();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int remainingTimeBudget = ui.update();
|
||||
|
||||
if (remainingTimeBudget > 0) {
|
||||
// You can do some work here
|
||||
// Don't do stuff if you are below your
|
||||
// time budget.
|
||||
delay(remainingTimeBudget);
|
||||
}
|
||||
}
|
||||
|
||||
bool msOverlay(SSD1306 *display, SSD1306UiState* state) {
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(128, 0, String(millis()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool drawFrame1(SSD1306 *display, SSD1306UiState* state, int x, int y) {
|
||||
// draw an xbm image.
|
||||
// Please note that everything that should be transitioned
|
||||
// needs to be drawn relative to x and y
|
||||
|
||||
// if this frame need to be refreshed at the targetFPS you need to
|
||||
// return true
|
||||
display->drawXbm(x + 34, y + 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drawFrame2(SSD1306 *display, SSD1306UiState* state, int x, int y) {
|
||||
// Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file
|
||||
// Besides the default fonts there will be a program to convert TrueType fonts into this format
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(0 + x, 10 + y, "Arial 10");
|
||||
|
||||
display->setFont(ArialMT_Plain_16);
|
||||
display->drawString(0 + x, 20 + y, "Arial 16");
|
||||
|
||||
display->setFont(ArialMT_Plain_24);
|
||||
display->drawString(0 + x, 34 + y, "Arial 24");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drawFrame3(SSD1306 *display, SSD1306UiState* state, int x, int y) {
|
||||
// Text alignment demo
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawString(0 + x, 11 + y, "Left aligned (0,10)");
|
||||
|
||||
// The coordinates define the center of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, 22, "Center aligned (64,22)");
|
||||
|
||||
// The coordinates define the right end of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->drawString(128 + x, 33, "Right aligned (128,33)");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drawFrame4(SSD1306 *display, SSD1306UiState* state, int x, int y) {
|
||||
// Demo for drawStringMaxWidth:
|
||||
// with the third parameter you can define the width after which words will be wrapped.
|
||||
// Currently only spaces and "-" are allowed for wrapping
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawStringMaxWidth(0 + x, 10 + y, 128, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore.");
|
||||
return false;
|
||||
}
|
||||
@@ -1,22 +1,28 @@
|
||||
{
|
||||
"name": "ESP8266 Oled Driver for SSD1306 display",
|
||||
"keywords": "Display, ssd1306, arduino, esp8266",
|
||||
"description": "SSD1306 Oled driver which offers scrolling frames, custom fonts, etc",
|
||||
"repository": {
|
||||
"name": "ESP8266_SSD1306",
|
||||
"version": "3.2.7",
|
||||
"keywords": "ssd1306, oled, display, i2c",
|
||||
"description": "A I2C display driver for SSD1306 oled displays connected to an ESP8266 or ESP32",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/squix78/esp8266-oled-ssd1306.git"
|
||||
},
|
||||
"authors": [{
|
||||
"name": "Daniel Eichhorn",
|
||||
"url": "http://blog.squix.ch",
|
||||
"email": "squix78@gmail.com",
|
||||
"maintainer": true
|
||||
},
|
||||
{
|
||||
"name": "Fabrice Weinberg"
|
||||
}
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Daniel Eichhorn",
|
||||
"email": "squix78@gmail.com",
|
||||
"url": "http://blog.squix.ch"
|
||||
},
|
||||
{
|
||||
"name": "Fabrice Weinberg",
|
||||
"email": "fabrice@weinberg.me"
|
||||
}
|
||||
],
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif",
|
||||
"version": "2.0.1"
|
||||
"platforms": [
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user