Compare commits
752 commits
Author | SHA1 | Date | |
---|---|---|---|
1f53447813 | |||
76ccd1ea13 | |||
3f47cb300b | |||
0007835a5a | |||
c8bd1acde2 | |||
9d2f1715df | |||
02177f65e1 | |||
46430fc77a | |||
9da22fbec4 | |||
ca431d2e46 | |||
3d255ed6f8 | |||
1c8b438bca | |||
3de5c47802 | |||
ea04534281 | |||
e62f254e7e | |||
9377759d3b | |||
59b7f37e26 | |||
7fd5b7a6a7 | |||
94f4b19460 | |||
eb68b98cf5 | |||
196b169fbe | |||
d6618ade1a | |||
9b901dd28e | |||
713ffc33f2 | |||
2247c673fc | |||
a44c16a426 | |||
fb5fdca66a | |||
89d650d87b | |||
e0482d6d1b | |||
81598323c6 | |||
6695835808 | |||
b929b419af | |||
80388188f7 | |||
502842a30b | |||
aa9fc5d817 | |||
1ee36e7429 | |||
15039f6b5d | |||
e93083073c | |||
9355f678e3 | |||
4d90cd2e3f | |||
da8cd47dea | |||
e492974415 | |||
96c5d12e2a | |||
965ac84918 | |||
325e41ae6a | |||
a9cb7ab7be | |||
7fffc50d7c | |||
233cb02993 | |||
54b72dcf64 | |||
8c82ce0722 | |||
86596ac92f | |||
259827b031 | |||
3479303454 | |||
3fb61f7695 | |||
dd84558cd6 | |||
297bd14f7b | |||
30de144aea | |||
13c22c0c71 | |||
d4790c8ede | |||
5003aca5c7 | |||
cfeb8036e0 | |||
2036cda4d9 | |||
29190681cc | |||
ba62fd2dd2 | |||
ecdd101586 | |||
25d38eba2c | |||
927c0b8eac | |||
87f433d657 | |||
0b24e047c5 | |||
31ec8687e4 | |||
8b2ee08d55 | |||
aaf1e8b2b1 | |||
6694583291 | |||
fedd9cb0d7 | |||
df2b297d91 | |||
4127d0993b | |||
11525b74ae | |||
8e23d07de4 | |||
5f8be3e6ea | |||
07c21e6e7d | |||
df282f348c | |||
3a560c79f9 | |||
64b2750de3 | |||
a2f8424b74 | |||
f368875ea2 | |||
17e0b6f2cc | |||
2ef7438131 | |||
8c5b66d715 | |||
3f6cb4e795 | |||
7a6bab7b10 | |||
13c4934a37 | |||
75e8c162ed | |||
0c3a9c6b5a | |||
32afc08622 | |||
d62fe15a26 | |||
3b56d718c6 | |||
32bbd0cc71 | |||
7ea0e3b933 | |||
12ee7b7e39 | |||
cc48b88713 | |||
406fb7ea44 | |||
edc7a59091 | |||
d890a492bb | |||
3defa16553 | |||
6141e26999 | |||
dd9ba9e0ef | |||
e3784fa9c7 | |||
954da749eb | |||
6eced34422 | |||
140f43f4c1 | |||
ed638a5f5a | |||
b774d61713 | |||
bfdae2a7a7 | |||
0859e3442c | |||
5e20a17131 | |||
f576ef27ce | |||
c35be7c066 | |||
1a57b55d8f | |||
1384aad51a | |||
181e2c436e | |||
fd442fb9da | |||
4b1580cc70 | |||
a6670d99a8 | |||
38430ac259 | |||
60c6495fa3 | |||
578dbaa431 | |||
223ea26eb4 | |||
c39e10b2e7 | |||
5e15ec6488 | |||
dca85a7b6b | |||
c56142ccec | |||
afde635051 | |||
c7de205029 | |||
1addd8da3a | |||
e24f500e57 | |||
fcc4f6d39f | |||
59dc4413bb | |||
612cb23759 | |||
d94efe528a | |||
5640293e8f | |||
0e861e76a3 | |||
918b20f3cf | |||
3545f1fab5 | |||
2942868799 | |||
362eadd821 | |||
14baf5df6c | |||
c954d22d81 | |||
f36183f2b5 | |||
314c46b91a | |||
6af70ee511 | |||
7000323c74 | |||
ae6375d900 | |||
2137a12971 | |||
4151c09e2c | |||
6677fac2ab | |||
8e07bab71f | |||
85f3814f67 | |||
42dee52e65 | |||
352f078be7 | |||
5ea65cab08 | |||
201a8174c6 | |||
6a9b6ae77b | |||
9fb2352b08 | |||
2f8549aaae | |||
1ec48fcf37 | |||
0812b89909 | |||
d41197e1e7 | |||
52c26d31c4 | |||
5fc05b102b | |||
95b8c2683e | |||
994badaef9 | |||
16e6a20b31 | |||
353cfe723c | |||
938aa0db71 | |||
4f7476c084 | |||
f8a399d346 | |||
aa1670e5d4 | |||
6a1a4b62a0 | |||
f9f923d29c | |||
b708fac68d | |||
9f40b0734c | |||
ceb4fb3298 | |||
1398ff0de6 | |||
c666b18a12 | |||
d2a1f8937e | |||
d8bb685989 | |||
646bb077ef | |||
d66e402cad | |||
5ea437c170 | |||
20820a11e0 | |||
d2a650f514 | |||
79b69334df | |||
0556557d8b | |||
17520dc4e0 | |||
e6dbb8c3f2 | |||
54e676343f | |||
8891a0ec44 | |||
b7b3f0a33a | |||
ed1ae480f1 | |||
fd37296cdf | |||
3b28df58da | |||
47760c57e6 | |||
0fd28e0585 | |||
a152a30958 | |||
e4ab78369e | |||
8f5a033c48 | |||
548bf32990 | |||
e410b2ddd2 | |||
34adab3210 | |||
9226facda8 | |||
fa11a55a45 | |||
5d76c0a6af | |||
dfea93b2ff | |||
cfca07489d | |||
8302b1f762 | |||
ee5cd039a1 | |||
a37fd79426 | |||
916bebd102 | |||
ae79061182 | |||
a5b59e8cbb | |||
6f7e68c3d4 | |||
2fd23f99ed | |||
8b1745214c | |||
28f2b2caa8 | |||
5de29079ae | |||
fd12dcccf0 | |||
c663bb527e | |||
5b288a5777 | |||
34a9135f83 | |||
37ea128d65 | |||
c7de6343d9 | |||
eeb90bab77 | |||
ec34b8640c | |||
3af0cc460c | |||
0190c261e2 | |||
6cf4e147ed | |||
8b887ca429 | |||
a70a51acc2 | |||
1d2447d69d | |||
12e77a1e58 | |||
6c7dc58574 | |||
d3431a0b54 | |||
91fcc28b12 | |||
cf40f59843 | |||
265d4e8723 | |||
28cb276c70 | |||
50a34d1235 | |||
70172a9eb8 | |||
9408743938 | |||
6e67d1415c | |||
c42a75d9d6 | |||
6a2d13216a | |||
542a921e3f | |||
8402b1c151 | |||
e534bcaa25 | |||
349f6bf429 | |||
d408da5be5 | |||
3c8e91d74e | |||
978ef63002 | |||
dfd8fdec4a | |||
9a2494583d | |||
abc5db04b2 | |||
a95b0c9d46 | |||
944f1b06d6 | |||
04bbba6c12 | |||
53dd2e5d16 | |||
068f27d1c2 | |||
79df347afa | |||
9a3c6adf8d | |||
743245e230 | |||
b2a289924b | |||
f2af0c7329 | |||
682df76b79 | |||
5a5ed6b990 | |||
6bdae7d9ec | |||
daf2191555 | |||
de928cd14e | |||
6b40e88ecb | |||
c6165a3bcf | |||
c7daa7c45d | |||
2df628aa4b | |||
9bb1f01905 | |||
7d8254bd81 | |||
b462052bf5 | |||
98e4451518 | |||
e7f270cf37 | |||
a7b230a0b7 | |||
855bc65b8a | |||
1e5163cbb3 | |||
de6477efa8 | |||
0068611b4d | |||
b8c5ee0e2b | |||
c09625704c | |||
f2fe41017b | |||
681c514a18 | |||
535194bcb4 | |||
44d4f855c6 | |||
406d69a27c | |||
6fcdf21552 | |||
c381f81f57 | |||
e60fe15812 | |||
fce1b561da | |||
0c3eeed1bf | |||
c2f9c584b9 | |||
428131e8a8 | |||
836a483f7e | |||
d484585e39 | |||
c493bc6618 | |||
ba9d4ed578 | |||
67ed80e9fe | |||
9b9958fb43 | |||
fd24ecd26e | |||
e8471445ed | |||
0a4938243e | |||
4ff973a0cc | |||
1a309e6632 | |||
a2e70d49f3 | |||
6b41f23d59 | |||
7404e75213 | |||
e3ffbe36c8 | |||
617d42663c | |||
7f09f96e88 | |||
910dc981b5 | |||
500078ef9a | |||
72c6c2c492 | |||
9b6bdd30b8 | |||
6a0d407806 | |||
63e0d930aa | |||
82d03d0ebf | |||
877bf27f5a | |||
b2847f4756 | |||
b97d6878c0 | |||
a1423c28fc | |||
12fe0d8442 | |||
44c7cb348c | |||
b90acf2491 | |||
29e62c4e20 | |||
41163406c2 | |||
235f368340 | |||
65c50195c4 | |||
0980393d22 | |||
3ba9009f50 | |||
560117e8f3 | |||
0097d192be | |||
d4656a26ff | |||
d31ecbf486 | |||
117f737f8d | |||
9dd81946d3 | |||
6730ec16c8 | |||
c30493e535 | |||
98be2c25ea | |||
0f109e3541 | |||
451e2df0f5 | |||
5ff9b7c989 | |||
058ae7bae3 | |||
16afb4b74c | |||
c8be130f2e | |||
301d8d77bb | |||
42f985a297 | |||
1f3387cd44 | |||
050b55adae | |||
a2357e648e | |||
f6c158a139 | |||
e946cd4c13 | |||
df220072f4 | |||
801316badc | |||
7b25177a3d | |||
baaa2c5741 | |||
75d577c9b5 | |||
76e39b2b5d | |||
ff29ab2c94 | |||
64e3ed0281 | |||
b3bf194b88 | |||
000d37a7fc | |||
a8e8f54342 | |||
150aad4ad2 | |||
4b9314cbde | |||
007cf1dbe3 | |||
a8728413b2 | |||
2d52ca9051 | |||
2d3cd057c4 | |||
d742fc4b76 | |||
2b8aeee115 | |||
fb473237ce | |||
9efc5d41c1 | |||
365fe31b02 | |||
aaaa0aa138 | |||
a8c87e3f54 | |||
df95393980 | |||
76ea945fd7 | |||
248a1e3882 | |||
a4b1e0138a | |||
cc0539ee90 | |||
fed6fe019c | |||
13aa2a1415 | |||
d6144bfebe | |||
ed161d1905 | |||
a02be51f08 | |||
9c90608d3c | |||
730d9e2d11 | |||
1dacefce01 | |||
41f8a9c661 | |||
698d8dce90 | |||
824eca3b61 | |||
7a666307cf | |||
079e46f427 | |||
b0a617b534 | |||
9eb0c5466f | |||
6167835689 | |||
e58322260f | |||
d8e0dd7005 | |||
a86f137cf5 | |||
8966f7d509 | |||
0620eb86d0 | |||
0c7328b59d | |||
dfaa8c0f32 | |||
914f5b931b | |||
1b40bccb00 | |||
8bb7d82a2d | |||
21bbe79079 | |||
026b961d5e | |||
5f18fc6955 | |||
42d3b38c9c | |||
f7e987cbeb | |||
1a1aaa883e | |||
ef06560465 | |||
53cf5ab6cf | |||
fbe6ae6a60 | |||
ddbfd6712c | |||
abdf6f8c6b | |||
f0ad042bfc | |||
d5284eebe1 | |||
4f20df042f | |||
fd54bc9ca4 | |||
c46d6afa39 | |||
08abd8807d | |||
b6be226e69 | |||
b17934c491 | |||
cfec3c6e2d | |||
5077010fc0 | |||
16fa63ebac | |||
4461dca8f2 | |||
4ceffb090d | |||
b4fb8c3f52 | |||
b886a1faaf | |||
15bab74093 | |||
465eb28382 | |||
38dbf611e6 | |||
7c0cd36a77 | |||
56f6f87c94 | |||
1efbe0736a | |||
d90e0d622d | |||
c106898d2b | |||
94d764e4cb | |||
4d383eb923 | |||
678891a1a9 | |||
a656cf1dcd | |||
03a4081913 | |||
8905f35d72 | |||
26b1e874d6 | |||
affe81cc6d | |||
a16849120f | |||
1ca7b52217 | |||
46df18ceb1 | |||
a90a6e0f65 | |||
964164b157 | |||
630bd8e9e4 | |||
85d29b6473 | |||
088c7118e0 | |||
4760891bb4 | |||
425f348daa | |||
11b13a7a7e | |||
f2bd00b660 | |||
9906e9736c | |||
e5baf940e7 | |||
1b04a24022 | |||
8b323633cd | |||
35668c8aed | |||
7ea29294d7 | |||
2408af0b93 | |||
fd57fcef72 | |||
a9b36497f6 | |||
3a3091c884 | |||
f7e4fb6499 | |||
cc950ace98 | |||
96f1264120 | |||
fa7920952f | |||
c3f00a7106 | |||
829cd2517d | |||
ab16ebd4ea | |||
09813190aa | |||
171c1290c3 | |||
dd917c3260 | |||
e2edd006d4 | |||
837f70770a | |||
34d64b4eb0 | |||
1093989aef | |||
29c7297591 | |||
45ede69308 | |||
8f85f7fb0a | |||
7cc5312937 | |||
666ca8436b | |||
cead1c7ce0 | |||
ae732f4636 | |||
bd45ee7aea | |||
d85ce4b42b | |||
decc9fcb0f | |||
21bd674622 | |||
db823713eb | |||
0881290bbc | |||
532063c422 | |||
89723ebfa8 | |||
deea693f82 | |||
ba2e08aebf | |||
48fff35bd9 | |||
e9c033688b | |||
15709add91 | |||
1fc136d379 | |||
d5ca328050 | |||
b1e1ef1ffd | |||
558184f106 | |||
3f9e1962a1 | |||
909bdd2d90 | |||
d1bf2bbb69 | |||
a66fb13e4f | |||
795580b6ae | |||
88ae1828f9 | |||
245d801862 | |||
a4986b71dc | |||
b992fc43cc | |||
617dfba4cb | |||
03b7dc8719 | |||
673b167f8f | |||
42c28e0bf7 | |||
277f63d76a | |||
54114b0943 | |||
b33ea9659c | |||
fbd4b0be9c | |||
e645833a99 | |||
8c08364cad | |||
cb41c216e9 | |||
f6fa014a1f | |||
300716164c | |||
c5a9a22e0f | |||
3c142b8bbb | |||
562434e90e | |||
e9196aebb7 | |||
30b8d433f9 | |||
37d8ca16fe | |||
81e6734626 | |||
715cfa3a75 | |||
cd194ae1ab | |||
d00df76ada | |||
892de50059 | |||
c4c92ea630 | |||
fc6055b420 | |||
ff15332aa5 | |||
808a249862 | |||
ab3f3c8644 | |||
2c172bfd31 | |||
30b5333123 | |||
c4d8e6a6e8 | |||
5ac3e3a220 | |||
9e2f71b7d8 | |||
3019a8e3ef | |||
a6a1a7b375 | |||
17c7e35621 | |||
19561efacb | |||
dfa4da2e98 | |||
ee1759ba4a | |||
114d7e883a | |||
408d1cabfe | |||
8ed94bf819 | |||
9f4f828976 | |||
2ae3d60203 | |||
d7a6d8560a | |||
e09abcaa96 | |||
fa53bc3241 | |||
c25dc70d26 | |||
ccaae9cd5c | |||
cead73a4d6 | |||
ff8b6d933b | |||
1aa694bba2 | |||
f61d0b2e1e | |||
4b984153ab | |||
60156d1c48 | |||
d8bc9f761c | |||
77c02d58f8 | |||
6c06f43417 | |||
4643c5d02d | |||
9df7ab3875 | |||
72da6659ed | |||
c5d25f5bfe | |||
f0f5391409 | |||
b6e20bf6c0 | |||
e65dabb119 | |||
87903b2e89 | |||
5991c3e3db | |||
d192553309 | |||
db60afb2fb | |||
df0cc061f6 | |||
a952a96b6e | |||
45dee77092 | |||
b398ab9288 | |||
e88f60feee | |||
478d91ac53 | |||
47d1c2a74d | |||
f48566d51f | |||
0c29b2b7db | |||
2d424bd259 | |||
078faa39d4 | |||
90ed9d14d2 | |||
2a63d0a972 | |||
be01bf77a9 | |||
0a5872e261 | |||
5fcac26e80 | |||
40bd9950d1 | |||
59bd18df7d | |||
598a0da30d | |||
ac79f1b596 | |||
b0c8597dbc | |||
b6e0ef1d95 | |||
f77717158d | |||
f9d67ed10c | |||
f40bf6d803 | |||
59713f6d3b | |||
67dba47c23 | |||
aa568a28a3 | |||
f9abb44d6e | |||
86cd1ec02f | |||
992e54fe25 | |||
bf6f388691 | |||
67783600aa | |||
251abdda29 | |||
d87287b745 | |||
d8d0a507e1 | |||
11b7022ce6 | |||
87028c1f60 | |||
f8c298a495 | |||
51f179eacf | |||
1f586c7735 | |||
7d354d8a37 | |||
2ddd2ba38a | |||
b50f4e2119 | |||
806de3f204 | |||
15167d541e | |||
39a830d9a9 | |||
116ce888c4 | |||
184dee491e | |||
4f05557905 | |||
1b56526fe0 | |||
aac4fcc8e1 | |||
3c0908f2da | |||
1464292188 | |||
d3eb7da297 | |||
0a14fd6a18 | |||
337be76b26 | |||
da39da39dc | |||
afa20ee0ae | |||
aea396e542 | |||
0ef2ce8e5c | |||
7b46026b52 | |||
310234e0dc | |||
7001e8fa33 | |||
a58322a62b | |||
ffae9fce58 | |||
4a981f1c47 | |||
b6bea56c27 | |||
ff227b7a04 | |||
7ee65e72a5 | |||
16c8c3853d | |||
015a6a3c65 | |||
1968ebc626 | |||
58504df2c4 | |||
d5eda89c39 | |||
9c1b87bbb9 | |||
5c3303eef0 | |||
cd715cb222 | |||
2441cc38ee | |||
11d4c9553e | |||
312a88ad39 | |||
243fd6f11e | |||
ae7b37d1c3 | |||
7478d719cf | |||
611e358ad9 | |||
b27469d218 | |||
ec5210b562 | |||
080eadc79b | |||
ef5b9474fd | |||
71f8352876 | |||
c265e72b24 | |||
8628af93e1 | |||
19ec02773f | |||
765129fde2 | |||
32d077790f | |||
cdf4da8461 | |||
797c3da239 | |||
25fb513164 | |||
ae3d5e4966 | |||
6184e5715b | |||
d8d1550400 | |||
7383f6708b | |||
3d10f4d0d1 | |||
0deca185bb | |||
6d30a5b66e | |||
8cdf981c8f | |||
8d5f623b6a | |||
85fb0b1e48 | |||
3783d5f059 | |||
86a6d88799 | |||
46010cbbd6 | |||
20e8eba08b | |||
033adfa678 | |||
057a3c3345 | |||
bba7b84a15 | |||
36e0dcf22f | |||
c8604b5a70 | |||
43b9f7a23d | |||
2a495ace3b | |||
5ee13bf528 | |||
33639c15e1 | |||
618a516182 | |||
b6c7cc8672 | |||
4d93071bf9 | |||
6d0bdab9f0 | |||
7f776ee918 | |||
a6634acc50 | |||
b31a3397e0 | |||
b6f96951be | |||
23394cd1f5 | |||
252454c016 | |||
a2387f43af | |||
641aad70a9 | |||
32ab451fff | |||
a1152fd96e | |||
356ea01a8d | |||
48217bcf80 | |||
104be3acfb | |||
ac235b9c57 | |||
b2040a6cd9 | |||
2e35f2225d | |||
ff022fce05 | |||
538bb6075c | |||
86c4214014 | |||
1f12531618 | |||
65341d8d3b | |||
90885f2168 | |||
e92678a847 | |||
17c93b259e | |||
56807ee75a | |||
2b7e7b8f8c | |||
92b835080b |
7
.gitmodules
vendored
7
.gitmodules
vendored
|
@ -4,16 +4,15 @@
|
|||
[submodule "tools/cc2538-bsl"]
|
||||
path = tools/cc2538-bsl
|
||||
url = https://github.com/JelmerT/cc2538-bsl.git
|
||||
[submodule "cpu/cc26xx-cc13xx/lib/cc26xxware"]
|
||||
path = cpu/cc26xx-cc13xx/lib/cc26xxware
|
||||
url = https://github.com/contiki-os/cc26xxware.git
|
||||
[submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"]
|
||||
path = cpu/cc26xx-cc13xx/lib/cc13xxware
|
||||
url = https://github.com/contiki-os/cc13xxware.git
|
||||
[submodule "platform/stm32nucleo-spirit1/stm32cube-lib"]
|
||||
path = platform/stm32nucleo-spirit1/stm32cube-lib
|
||||
url = https://github.com/STclab/stm32nucleo-spirit1-lib
|
||||
|
||||
[submodule "tools/sensniff"]
|
||||
path = tools/sensniff
|
||||
url = https://github.com/g-oikonomou/sensniff.git
|
||||
[submodule "apps/tinydtls"]
|
||||
path = apps/tinydtls
|
||||
url = https://github.com/iot-lab/armour-tinydtls.git
|
||||
|
|
494
LICENSE
494
LICENSE
|
@ -1,3 +1,37 @@
|
|||
A note on Licensing (2017-03-17):
|
||||
Github has recently (2017-03-01) changed their license terms:
|
||||
https://help.github.com/articles/github-terms-of-service/
|
||||
There were comments that this may violate some GPL and creative commons
|
||||
licenses:
|
||||
http://joeyh.name/blog/entry/removing_everything_from_github/
|
||||
https://www.mirbsd.org/permalinks/wlog-10_e20170301-tg.htm
|
||||
But also voices that don't see a problem:
|
||||
https://www.earth.li/~noodles/blog/2017/03/github-tos-change.html
|
||||
If your're german-speaking you may also want to read the two Heise
|
||||
articles:
|
||||
https://www.heise.de/developer/meldung/GitHub-eckt-mit-neuen-Nutzungsbedingungen-an-3647980.html
|
||||
https://www.heise.de/developer/meldung/FSF-aeussert-sich-zu-den-GitHub-Nutzungsbedingungen-3657040.html
|
||||
|
||||
We trust that the problematic part in section D.5:
|
||||
"If you set your pages and repositories to be viewed publicly, you grant
|
||||
each User of GitHub a nonexclusive, worldwide license to access your
|
||||
Content through the GitHub Service, and to use, display and perform your
|
||||
Content, and to reproduce your Content solely on GitHub as permitted
|
||||
through GitHub's functionality." that the part "solely on GitHub as
|
||||
permitted through GitHub's functionality" also applies to "display and
|
||||
perform your Content". If the latter part of the sentence would stand
|
||||
alone it could be interpreted that we would grant *everybody*
|
||||
essentially an unlimited license (which we cannot because the authors
|
||||
from whom we forked applied other licenses). This interpretation is
|
||||
further supported by the fact that Github writes "You may grant further
|
||||
rights if you adopt a license." that in fact the statements above only
|
||||
apply to the rendering on Github.
|
||||
|
||||
Note that in the following we have two licenses, the 3-clause BSD and
|
||||
the LGPL license in short:
|
||||
- Contiki OS (and our modification to it) are 3-clause BSD
|
||||
- Our Arduino compatibility Layer on top of Contiki OS is LGPL
|
||||
|
||||
Contiki is licensed under the 3-clause BSD license. This license gives
|
||||
everyone the right to use and distribute the code, either in binary or
|
||||
source code format, as long as the copyright license is retained in
|
||||
|
@ -36,3 +70,463 @@ of license. The license text is:
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Arduino-compatibility layer if not otherwise noted is under the
|
||||
following license:
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. 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 not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the 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
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ CONTIKI_SOURCEFILES += $(CONTIKIFILES)
|
|||
CONTIKIDIRS += ${addprefix $(CONTIKI)/core/,dev lib net net/llsec net/mac net/rime \
|
||||
net/rpl sys cfs ctk lib/ctk loader . }
|
||||
|
||||
oname = ${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}}
|
||||
oname = ${patsubst %.cpp,%.o,${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}}}
|
||||
|
||||
CONTIKI_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CONTIKI_SOURCEFILES)}}
|
||||
|
||||
|
@ -156,16 +156,18 @@ endif
|
|||
### Verbosity control. Use make V=1 to get verbose builds.
|
||||
|
||||
ifeq ($(V),1)
|
||||
TRACE_CC =
|
||||
TRACE_LD =
|
||||
TRACE_AR =
|
||||
TRACE_AS =
|
||||
TRACE_CC =
|
||||
TRACE_CXX =
|
||||
TRACE_LD =
|
||||
TRACE_AR =
|
||||
TRACE_AS =
|
||||
Q=
|
||||
else
|
||||
TRACE_CC = @echo " CC " $<
|
||||
TRACE_LD = @echo " LD " $@
|
||||
TRACE_AR = @echo " AR " $@
|
||||
TRACE_AS = @echo " AS " $<
|
||||
TRACE_CC = @echo " CC " $<
|
||||
TRACE_CXX = @echo " CXX " $<
|
||||
TRACE_LD = @echo " LD " $@
|
||||
TRACE_AR = @echo " AR " $@
|
||||
TRACE_AS = @echo " AS " $<
|
||||
Q=@
|
||||
endif
|
||||
|
||||
|
@ -184,8 +186,9 @@ CONTIKI_CPU_DIRS_CONCAT = ${addprefix $(CONTIKI_CPU)/, \
|
|||
SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) \
|
||||
$(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDS) $(EXTERNALDIRS) ${dir $(target_makefile)}
|
||||
|
||||
vpath %.c $(SOURCEDIRS)
|
||||
vpath %.S $(SOURCEDIRS)
|
||||
vpath %.c $(SOURCEDIRS)
|
||||
vpath %.cpp $(SOURCEDIRS)
|
||||
vpath %.S $(SOURCEDIRS)
|
||||
|
||||
CFLAGS += ${addprefix -I,$(SOURCEDIRS) $(CONTIKI)}
|
||||
|
||||
|
@ -203,7 +206,7 @@ endif
|
|||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include ${addprefix $(OBJECTDIR)/,$(CONTIKI_SOURCEFILES:.c=.d) \
|
||||
$(PROJECT_SOURCEFILES:.c=.d)}
|
||||
$(PROJECT_OBJECTFILES:.o=.d)}
|
||||
endif
|
||||
|
||||
### See http://make.paulandlesley.org/autodep.html#advanced
|
||||
|
@ -242,6 +245,13 @@ $(OBJECTDIR)/%.o: %.c | $(OBJECTDIR)
|
|||
@$(FINALIZE_DEPENDENCY)
|
||||
endif
|
||||
|
||||
ifndef CUSTOM_RULE_CPP_TO_OBJECTDIR_O
|
||||
$(OBJECTDIR)/%.o: %.cpp | $(OBJECTDIR)
|
||||
$(TRACE_CXX)
|
||||
$(Q)$(CXX) $(CFLAGS) -MMD -c $< -o $@
|
||||
@$(FINALIZE_DEPENDENCY)
|
||||
endif
|
||||
|
||||
ifndef CUSTOM_RULE_S_TO_OBJECTDIR_O
|
||||
$(OBJECTDIR)/%.o: %.S | $(OBJECTDIR)
|
||||
$(TRACE_AS)
|
||||
|
@ -254,6 +264,12 @@ ifndef CUSTOM_RULE_C_TO_O
|
|||
$(Q)$(CC) $(CFLAGS) -c $< -o $@
|
||||
endif
|
||||
|
||||
ifndef CUSTOM_RULE_CPP_TO_O
|
||||
%.o: %.cpp
|
||||
$(TRACE_CXX)
|
||||
$(Q)$(CXX) $(CFLAGS) -c $< -o $@
|
||||
endif
|
||||
|
||||
|
||||
ifndef CUSTOM_RULE_C_TO_CO
|
||||
%.co: %.c
|
||||
|
@ -288,6 +304,25 @@ endif
|
|||
%.flashprof: %.$(TARGET)
|
||||
$(NM) -S -td --size-sort $< | grep -i " [t] " | cut -d' ' -f2,4
|
||||
|
||||
viewconf:
|
||||
@echo "----------------- Make variables: --------------"
|
||||
@echo "##### \"TARGET\": ________________________________ $(TARGET)"
|
||||
@echo "##### \"BOARD\": _________________________________ $(BOARD)"
|
||||
@echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)"
|
||||
@echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)"
|
||||
@echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)"
|
||||
ifdef MAKE_COAP_DTLS_KEYSTORE
|
||||
@echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)"
|
||||
endif
|
||||
@echo "----------------- C variables: -----------------"
|
||||
$(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\#
|
||||
@echo "------------------------------------------------"
|
||||
@echo "'==' Means the flag is set to a given a value"
|
||||
@echo "'->' Means the flag is unset, but will default to a given value"
|
||||
@echo "'><' Means the flag is unset and has no default value"
|
||||
@echo "To view more Make variables, edit $(CONTIKI)/Makefile.include, rule 'viewconf'"
|
||||
@echo "To view more C variables, edit $(CONTIKI)/tools/viewconf.c"
|
||||
|
||||
# Don't treat %.$(TARGET) as an intermediate file because it is
|
||||
# in fact the primary target.
|
||||
.PRECIOUS: %.$(TARGET)
|
||||
|
@ -297,6 +332,8 @@ endif
|
|||
# the match-anything rule below instead.
|
||||
%: %.c
|
||||
|
||||
%: %.cpp
|
||||
|
||||
# Match-anything pattern rule to allow the project makefiles to
|
||||
# abstract from the actual binary name. It needs to contain some
|
||||
# command in order to be a rule, not just a prerequisite.
|
||||
|
|
11
README.md
11
README.md
|
@ -1,8 +1,6 @@
|
|||
The Contiki Operating System
|
||||
============================
|
||||
|
||||
[![Build Status](https://travis-ci.org/contiki-os/contiki.svg?branch=master)](https://travis-ci.org/contiki-os/contiki/branches)
|
||||
|
||||
Contiki is an open source operating system that runs on tiny low-power
|
||||
microcontrollers and makes it possible to develop applications that
|
||||
make efficient use of the hardware while providing standardized
|
||||
|
@ -17,3 +15,12 @@ and so on.
|
|||
For more information, see the Contiki website:
|
||||
|
||||
[http://contiki-os.org](http://contiki-os.org)
|
||||
|
||||
This fork of the Contiki Operating System adds support for our Merkur
|
||||
Board, adds a lot of examples (with different hardware) and puts an
|
||||
Arduino compatibility layer on top of Contiki-OS that allows Arduino
|
||||
Sketches -- and a lot of drivers for Arduino compatible hardware -- to
|
||||
run under Contiki-OS.
|
||||
|
||||
For the licensing terms (also in the light of recent debates of Github
|
||||
changed Terms of Service on 2017-03-01) see the file LICENSE.
|
||||
|
|
2
apps/arduino/Makefile.arduino
Normal file
2
apps/arduino/Makefile.arduino
Normal file
|
@ -0,0 +1,2 @@
|
|||
arduino_src = arduino-process.c
|
||||
|
4
apps/arduino/Makefile.include
Normal file
4
apps/arduino/Makefile.include
Normal file
|
@ -0,0 +1,4 @@
|
|||
%.cpp: %.pde
|
||||
echo '#include "Arduino.h"' > $@
|
||||
echo '#include "$<"' >> $@
|
||||
|
13
apps/arduino/README.md
Normal file
13
apps/arduino/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
Arduino Compatibility
|
||||
=====================
|
||||
|
||||
This application contains hardware-independent implementations of
|
||||
arduino compatibilty libraries and include files to be used with
|
||||
contiki.
|
||||
|
||||
The whole arduino compatibility library is work in progress. Note that
|
||||
features having to do with timers like `millis` and `delay` are
|
||||
currently untested. In Arduino they use timer 0 of the AVR
|
||||
microcontroller. It should be investigated to use the hardware timer
|
||||
already in use by contiki (on the OSD-merkur platform this is currently
|
||||
timer 5).
|
183
apps/arduino/arduino-process.c
Normal file
183
apps/arduino/arduino-process.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addgroup Arduino Process
|
||||
*
|
||||
* This wraps the Arduino-API entry points `loop` and `setup` in a
|
||||
* contiki process.
|
||||
*
|
||||
* If the normal contiki includes are used and resources initialized in
|
||||
* `setup`, Contiki resources can be used in an arduino sketch.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Wrapper for Arduino sketches
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "arduino-process.h"
|
||||
#include "hw_timer.h"
|
||||
#include "adc.h"
|
||||
#include "hw-arduino.h"
|
||||
#include "contiki.h"
|
||||
#include "project-conf.h"
|
||||
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
|
||||
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#define PRINT6ADDR(addr)
|
||||
#define PRINTLLADDR(addr)
|
||||
#endif
|
||||
|
||||
|
||||
extern volatile uint8_t mcusleepcycle;
|
||||
#if PLATFORM_HAS_BUTTON
|
||||
#include "rest-engine.h"
|
||||
#include "dev/button-sensor.h"
|
||||
extern resource_t res_event, res_separate;
|
||||
#endif /* PLATFORM_HAS_BUTTON */
|
||||
|
||||
volatile uint8_t mcusleepcycleval;
|
||||
/* 0 dont sleep; 1 sleep */
|
||||
uint8_t mcusleep;
|
||||
|
||||
/*-------------- enabled sleep mode ----------------------------------------*/
|
||||
void
|
||||
mcu_sleep_init(void)
|
||||
{
|
||||
mcusleepcycleval=mcusleepcycle;
|
||||
mcu_sleep_disable(); // if a shell is active we can type
|
||||
}
|
||||
void
|
||||
mcu_sleep_disable(void)
|
||||
{
|
||||
mcusleep=2;
|
||||
mcu_sleep_off();
|
||||
}
|
||||
void
|
||||
mcu_sleep_enable(void)
|
||||
{
|
||||
mcusleep=0;
|
||||
}
|
||||
void
|
||||
mcu_sleep_on(void)
|
||||
{
|
||||
if(mcusleep == 0){
|
||||
mcusleepcycle= mcusleepcycleval;
|
||||
}
|
||||
}
|
||||
/*--------------- disable sleep mode ---------------------------------------*/
|
||||
void
|
||||
mcu_sleep_off(void)
|
||||
{
|
||||
mcusleepcycle=0;
|
||||
}
|
||||
/*---------------- set duty cycle value ------------------------------------*/
|
||||
void
|
||||
mcu_sleep_set(uint8_t value)
|
||||
{
|
||||
mcusleepcycleval= value;
|
||||
// mcusleepcycle = mcusleepcycleval;
|
||||
}
|
||||
|
||||
PROCESS(arduino_sketch, "Arduino Sketch Wrapper");
|
||||
|
||||
#ifndef LOOP_INTERVAL
|
||||
#define LOOP_INTERVAL (1 * CLOCK_SECOND)
|
||||
#endif
|
||||
#define START_MCUSLEEP (10 * CLOCK_SECOND)
|
||||
|
||||
PROCESS_THREAD(arduino_sketch, ev, data)
|
||||
{
|
||||
static struct etimer loop_periodic_timer;
|
||||
static struct etimer start_mcusleep_timer;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
adc_init ();
|
||||
mcu_sleep_init ();
|
||||
setup ();
|
||||
/* Define application-specific events here. */
|
||||
etimer_set(&loop_periodic_timer, LOOP_INTERVAL);
|
||||
etimer_set(&start_mcusleep_timer, START_MCUSLEEP);
|
||||
|
||||
while (1) {
|
||||
PROCESS_WAIT_EVENT();
|
||||
#if PLATFORM_HAS_BUTTON
|
||||
if(ev == sensors_event && data == &button_sensor) {
|
||||
mcu_sleep_off();
|
||||
PRINTF("*******BUTTON*******\n");
|
||||
button ();
|
||||
mcu_sleep_on();
|
||||
}
|
||||
#endif /* PLATFORM_HAS_BUTTON */
|
||||
if(etimer_expired(&start_mcusleep_timer)) {
|
||||
PRINTF("mcusleep_timer %d\n",mcusleep);
|
||||
if(mcusleep == 1){
|
||||
PRINTF("mcu sleep on\n");
|
||||
mcu_sleep_enable();
|
||||
mcu_sleep_on();
|
||||
}
|
||||
if (mcusleep > 0) {
|
||||
mcusleep--;
|
||||
}
|
||||
etimer_reset(&start_mcusleep_timer);
|
||||
}
|
||||
|
||||
if(etimer_expired(&loop_periodic_timer)) {
|
||||
mcu_sleep_off();
|
||||
loop ();
|
||||
mcu_sleep_on();
|
||||
etimer_reset(&loop_periodic_timer);
|
||||
}
|
||||
}
|
||||
PROCESS_END();
|
||||
}
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
||||
/** @} */
|
77
apps/arduino/arduino-process.h
Normal file
77
apps/arduino/arduino-process.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \devgroup Arduino Process
|
||||
*
|
||||
* This wraps the Arduino-API entry points `loop` and `setup` in a
|
||||
* contiki process.
|
||||
*
|
||||
* If the normal contiki includes are used and resources initialized in
|
||||
* `setup`, Contiki resources can be used in an arduino sketch.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Wrapper for Arduino sketches
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
|
||||
/*--------------- enable sleep mode ---------------------------------------*/
|
||||
void mcu_sleep_enable(void);
|
||||
/*--------------- disable sleep mode ---------------------------------------*/
|
||||
void mcu_sleep_disable(void);
|
||||
/*--------------- sleep mode on---------------------------------------*/
|
||||
void mcu_sleep_on(void);
|
||||
/*--------------- sleep mode off---------------------------------------*/
|
||||
void mcu_sleep_off(void);
|
||||
/*---------------- set sleep value ------------------------------------*/
|
||||
void mcu_sleep_set(uint8_t value);
|
||||
|
||||
extern void loop (void);
|
||||
extern void setup (void);
|
||||
extern void arduino_init (void);
|
||||
extern void button (void);
|
||||
|
||||
extern struct process arduino_sketch;
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
||||
/** @} */
|
|
@ -4,3 +4,18 @@ er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c \
|
|||
|
||||
# Erbium will implement the REST Engine
|
||||
CFLAGS += -DREST=coap_rest_implementation
|
||||
|
||||
ifeq ($(WITH_DTLS_COAP),1)
|
||||
er-coap_src += er-coap-dtls.c
|
||||
|
||||
# Load tinydtls
|
||||
APPS += tinydtls
|
||||
$(CONTIKI)/apps/tinydtls/Makefile.tinydtls:
|
||||
@echo " You should run 'git submodule update --init' to clone 'app/tinydtls'"
|
||||
@exit 1
|
||||
include $(CONTIKI)/apps/tinydtls/Makefile.tinydtls
|
||||
PROJECTDIRS+=$(CONTIKI)/apps/tinydtls/aes $(CONTIKI)/apps/tinydtls/sha2 $(CONTIKI)/apps/tinydtls/ecc
|
||||
|
||||
else
|
||||
er-coap_src += er-coap-udp.c
|
||||
endif
|
||||
|
|
15
apps/er-coap/er-coap-communication.h
Normal file
15
apps/er-coap/er-coap-communication.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef _ER_COAP_COMMUNICATION_H_
|
||||
#define _ER_COAP_COMMUNICATION_H_
|
||||
|
||||
#include "contiki.h"
|
||||
|
||||
void
|
||||
coap_init_communication_layer(uint16_t port);
|
||||
|
||||
void
|
||||
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length);
|
||||
|
||||
void
|
||||
coap_handle_receive(void);
|
||||
|
||||
#endif
|
|
@ -94,6 +94,7 @@ typedef enum {
|
|||
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
||||
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
||||
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
||||
REQUEST_ENTITY_INCOMPLETE_4_08 = 136, /* REQUEST_ENTITY_INCOMPLETE */
|
||||
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
||||
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
||||
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
||||
|
|
161
apps/er-coap/er-coap-dtls.c
Normal file
161
apps/er-coap/er-coap-dtls.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "er-coap.h"
|
||||
#include "er-coap-engine.h"
|
||||
|
||||
#include "dtls.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "dtls_debug.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static struct dtls_context_t *dtls_ctx = NULL;
|
||||
|
||||
static dtls_handler_t coap_dtls_callback = {
|
||||
.write = coap_dtls_send_to_peer,
|
||||
.read = coap_dtls_read_from_peer,
|
||||
.event = NULL,
|
||||
#ifdef DTLS_PSK
|
||||
.get_psk_info = coap_dtls_get_psk_info,
|
||||
#endif
|
||||
#ifdef DTLS_ECC
|
||||
.get_ecdsa_key = NULL,
|
||||
.verify_ecdsa_key = NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_init_communication_layer(uint16_t port)
|
||||
{
|
||||
struct uip_udp_conn *udp_conn = NULL;
|
||||
|
||||
dtls_init();
|
||||
dtls_set_log_level(DTLS_LOG_DEBUG);
|
||||
|
||||
udp_conn = udp_new(NULL, 0, NULL);
|
||||
udp_bind(udp_conn, port);
|
||||
|
||||
dtls_ctx = dtls_new_context(udp_conn);
|
||||
if(dtls_ctx) {
|
||||
dtls_set_handler(dtls_ctx, &COAP_DTLS_CALLBACK);
|
||||
}
|
||||
/* new connection with remote host */
|
||||
printf("COAP-DTLS listening on port %u\n", uip_ntohs(udp_conn->lport));
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_send_message(uip_ipaddr_t *addr, uint16_t port,
|
||||
uint8_t *data, uint16_t length)
|
||||
{
|
||||
session_t session;
|
||||
|
||||
dtls_session_init(&session);
|
||||
uip_ipaddr_copy(&session.addr, addr);
|
||||
session.port = port;
|
||||
|
||||
dtls_write(dtls_ctx, &session, data, length);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_handle_receive()
|
||||
{
|
||||
session_t session;
|
||||
|
||||
if(uip_newdata()) {
|
||||
dtls_session_init(&session);
|
||||
uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
|
||||
session.port = UIP_UDP_BUF->srcport;
|
||||
|
||||
dtls_handle_message(dtls_ctx, &session, uip_appdata, uip_datalen());
|
||||
}
|
||||
}
|
||||
/* DTLS Specific functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#ifdef DTLS_PSK
|
||||
/* This function is the "key store" for tinyDTLS. It is called to
|
||||
* retrieve a key for the given identiy within this particular
|
||||
* session. */
|
||||
int
|
||||
coap_dtls_get_psk_info(struct dtls_context_t *ctx, const session_t *session,
|
||||
dtls_credentials_type_t type,
|
||||
const unsigned char *id, size_t id_len,
|
||||
unsigned char *result, size_t result_length)
|
||||
{
|
||||
|
||||
struct keymap_t {
|
||||
unsigned char *id;
|
||||
size_t id_length;
|
||||
unsigned char *key;
|
||||
size_t key_length;
|
||||
} psk[1] = {
|
||||
{ (unsigned char *)DTLS_IDENTITY, DTLS_IDENTITY_LENGTH, (unsigned char *)DTLS_PSK_KEY_VALUE, DTLS_PSK_KEY_VALUE_LENGTH },
|
||||
};
|
||||
if(type == DTLS_PSK_IDENTITY) {
|
||||
if(id_len) {
|
||||
dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id);
|
||||
}
|
||||
|
||||
if(result_length < psk[0].id_length) {
|
||||
dtls_warn("cannot set psk_identity -- buffer too small\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
memcpy(result, psk[0].id, psk[0].id_length);
|
||||
return psk[0].id_length;
|
||||
} else if(type == DTLS_PSK_KEY) {
|
||||
if(id) {
|
||||
int i;
|
||||
for(i = 0; i < sizeof(psk) / sizeof(struct keymap_t); i++) {
|
||||
if(id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
|
||||
if(result_length < psk[i].key_length) {
|
||||
dtls_warn("buffer too small for PSK");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
memcpy(result, psk[i].key, psk[i].key_length);
|
||||
return psk[i].key_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
int
|
||||
coap_dtls_send_to_peer(struct dtls_context_t *ctx,
|
||||
session_t *session, uint8 *data, size_t len)
|
||||
{
|
||||
|
||||
struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
|
||||
|
||||
uip_ipaddr_copy(&conn->ripaddr, &session->addr);
|
||||
conn->rport = session->port;
|
||||
|
||||
uip_udp_packet_send(conn, data, len);
|
||||
|
||||
/* Restore server connection to allow data from any node */
|
||||
memset(&conn->ripaddr, 0, sizeof(conn->ripaddr));
|
||||
memset(&conn->rport, 0, sizeof(conn->rport));
|
||||
|
||||
return len;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
int
|
||||
coap_dtls_read_from_peer(struct dtls_context_t *ctx,
|
||||
session_t *session, uint8 *data, size_t len)
|
||||
{
|
||||
uip_len = len;
|
||||
memmove(uip_appdata, data, len);
|
||||
coap_receive(ctx);
|
||||
return 0;
|
||||
}
|
47
apps/er-coap/er-coap-dtls.h
Normal file
47
apps/er-coap/er-coap-dtls.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef COAP_DTLS_H_
|
||||
#define COAP_DTLS_H_
|
||||
|
||||
/* Internal configuration of tinydtls for er-coap-dtls */
|
||||
|
||||
#if defined DTLS_CONF_IDENTITY && defined DTLS_CONF_IDENTITY_LENGTH
|
||||
#define DTLS_IDENTITY DTLS_CONF_IDENTITY
|
||||
#define DTLS_IDENTITY_LENGTH DTLS_CONF_IDENTITY_LENGTH
|
||||
#else
|
||||
#define DTLS_IDENTITY "Client_identity"
|
||||
#define DTLS_IDENTITY_LENGTH 15
|
||||
#endif
|
||||
|
||||
#if defined DTLS_CONF_PSK_KEY && defined DTLS_CONF_PSK_KEY_LENGTH
|
||||
#define DTLS_PSK_KEY_VALUE DTLS_CONF_PSK_KEY
|
||||
#define DTLS_PSK_KEY_VALUE_LENGTH DTLS_CONF_PSK_KEY_LENGTH
|
||||
#else
|
||||
#warning "DTLS: Using default secret key !"
|
||||
#define DTLS_PSK_KEY_VALUE "secretPSK"
|
||||
#define DTLS_PSK_KEY_VALUE_LENGTH 9
|
||||
#endif
|
||||
|
||||
/* Structure that hold tinydtls callbacks, has type 'dtls_handler_t'. */
|
||||
#ifndef COAP_DTLS_CALLBACK
|
||||
#ifdef COAP_DTLS_CONF_CALLBACK
|
||||
#define COAP_DTLS_CALLBACK COAP_DTLS_CONF_CALLBACK
|
||||
#else /* COAP_DTLS_CONF_CALLBACK */
|
||||
#define COAP_DTLS_CALLBACK coap_dtls_callback
|
||||
#endif /* COAP_DTLS_CALLBACK */
|
||||
|
||||
/* Send 'data' to peer defined by session */
|
||||
int coap_dtls_send_to_peer(struct dtls_context_t *ctx,
|
||||
session_t *session, uint8 *data, size_t len);
|
||||
|
||||
/* Read 'data' from peer */
|
||||
int coap_dtls_read_from_peer(struct dtls_context_t *ctx,
|
||||
session_t *session, uint8 *data, size_t len);
|
||||
#ifdef DTLS_PSK
|
||||
/* Retrieve the key for given identity withing this session */
|
||||
int coap_dtls_get_psk_info(struct dtls_context_t *ctx,
|
||||
const session_t *session,
|
||||
dtls_credentials_type_t type,
|
||||
const unsigned char *id, size_t id_len,
|
||||
unsigned char *result, size_t result_length);
|
||||
#endif
|
||||
|
||||
#endif /* COAP_DTLS_H_ */
|
|
@ -41,6 +41,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "er-coap-engine.h"
|
||||
#include "er-coap-communication.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
|
@ -64,8 +65,8 @@ static service_callback_t service_cbk = NULL;
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/*- Internal API ------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
coap_receive(void)
|
||||
int
|
||||
coap_receive()
|
||||
{
|
||||
erbium_status_code = NO_ERROR;
|
||||
|
||||
|
@ -346,7 +347,7 @@ PROCESS_THREAD(coap_engine, ev, data)
|
|||
PROCESS_YIELD();
|
||||
|
||||
if(ev == tcpip_event) {
|
||||
coap_receive();
|
||||
coap_handle_receive();
|
||||
} else if(ev == PROCESS_EVENT_TIMER) {
|
||||
/* retransmissions are handled here */
|
||||
coap_check_transactions();
|
||||
|
@ -482,6 +483,7 @@ const struct rest_implementation coap_rest_implementation = {
|
|||
NOT_FOUND_4_04,
|
||||
METHOD_NOT_ALLOWED_4_05,
|
||||
NOT_ACCEPTABLE_4_06,
|
||||
REQUEST_ENTITY_INCOMPLETE_4_08,
|
||||
REQUEST_ENTITY_TOO_LARGE_4_13,
|
||||
UNSUPPORTED_MEDIA_TYPE_4_15,
|
||||
INTERNAL_SERVER_ERROR_5_00,
|
||||
|
|
|
@ -52,6 +52,7 @@ typedef coap_packet_t rest_request_t;
|
|||
typedef coap_packet_t rest_response_t;
|
||||
|
||||
void coap_init_engine(void);
|
||||
int coap_receive();
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*- Client Part -------------------------------------------------------------*/
|
||||
|
|
42
apps/er-coap/er-coap-udp.c
Normal file
42
apps/er-coap/er-coap-udp.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "er-coap-engine.h"
|
||||
#include "er-coap-communication.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "uip-debug.h"
|
||||
|
||||
static struct uip_udp_conn *udp_conn = NULL;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_init_communication_layer(uint16_t port)
|
||||
{
|
||||
/* new connection with remote host */
|
||||
udp_conn = udp_new(NULL, 0, NULL);
|
||||
udp_bind(udp_conn, port);
|
||||
PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport));
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length)
|
||||
{
|
||||
/* Configure connection to reply to client */
|
||||
uip_ipaddr_copy(&udp_conn->ripaddr, addr);
|
||||
udp_conn->rport = port;
|
||||
|
||||
uip_udp_packet_send(udp_conn, data, length);
|
||||
PRINTF("-sent UDP datagram (%u)-\n", length);
|
||||
|
||||
/* Restore server connection to allow data from any node */
|
||||
memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr));
|
||||
udp_conn->rport = 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_handle_receive()
|
||||
{
|
||||
coap_receive();
|
||||
}
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include "er-coap.h"
|
||||
#include "er-coap-transactions.h"
|
||||
#include "er-coap-communication.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
|
@ -60,7 +61,6 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct uip_udp_conn *udp_conn = NULL;
|
||||
static uint16_t current_mid = 0;
|
||||
|
||||
coap_status_t erbium_status_code = NO_ERROR;
|
||||
|
@ -279,9 +279,7 @@ void
|
|||
coap_init_connection(uint16_t port)
|
||||
{
|
||||
/* new connection with remote host */
|
||||
udp_conn = udp_new(NULL, 0, NULL);
|
||||
udp_bind(udp_conn, port);
|
||||
PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport));
|
||||
coap_init_communication_layer(port);
|
||||
|
||||
/* initialize transaction ID */
|
||||
current_mid = random_rand();
|
||||
|
@ -422,23 +420,6 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||
return (option - buffer) + coap_pkt->payload_len; /* packet length */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
/* configure connection to reply to client */
|
||||
uip_ipaddr_copy(&udp_conn->ripaddr, addr);
|
||||
udp_conn->rport = port;
|
||||
|
||||
uip_udp_packet_send(udp_conn, data, length);
|
||||
|
||||
PRINTF("-sent UDP datagram (%u)-\n", length);
|
||||
|
||||
/* restore server socket to allow data from any node */
|
||||
memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr));
|
||||
udp_conn->rport = 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
coap_status_t
|
||||
coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
||||
{
|
||||
|
|
1
apps/json-resource/Makefile.json-resource
Normal file
1
apps/json-resource/Makefile.json-resource
Normal file
|
@ -0,0 +1 @@
|
|||
json-resource_src = generic_resource.c
|
271
apps/json-resource/generic_resource.c
Normal file
271
apps/json-resource/generic_resource.c
Normal file
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2014-15, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup Generic CoAP Resource Handler
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Generic CoAP Resource Handler
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "jsonparse.h"
|
||||
#include "er-coap.h"
|
||||
#include "generic_resource.h"
|
||||
|
||||
/* Error-handling macro */
|
||||
# define BYE(_exp, _tag) \
|
||||
do { \
|
||||
PRINTF("Expect "_exp": %d\n",_tag); \
|
||||
return -1; \
|
||||
} while(0)
|
||||
|
||||
#define DEBUG 1
|
||||
#if DEBUG
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
int8_t
|
||||
json_parse_variable
|
||||
(const uint8_t *bytes, size_t len, char *name, char *buf, size_t buflen)
|
||||
{
|
||||
int tag = 0;
|
||||
struct jsonparse_state state;
|
||||
struct jsonparse_state *parser = &state;
|
||||
PRINTF ("PUT: len: %d, %s\n", len, (const char *)bytes);
|
||||
jsonparse_setup (parser, (const char *)bytes, len);
|
||||
if ((tag = jsonparse_next (parser)) != JSON_TYPE_OBJECT) {
|
||||
BYE ("OBJECT", tag);
|
||||
}
|
||||
if ((tag = jsonparse_next (parser)) != JSON_TYPE_PAIR_NAME) {
|
||||
BYE ("PAIR_NAME", tag);
|
||||
}
|
||||
while (jsonparse_strcmp_value (parser, name) != 0) {
|
||||
tag = jsonparse_next (parser);
|
||||
if (tag != JSON_TYPE_PAIR) {
|
||||
BYE ("PAIR", tag);
|
||||
}
|
||||
tag = jsonparse_next (parser);
|
||||
tag = jsonparse_next (parser);
|
||||
if (tag != ',') {
|
||||
BYE (",", tag);
|
||||
}
|
||||
tag = jsonparse_next (parser);
|
||||
if (tag != JSON_TYPE_PAIR_NAME) {
|
||||
BYE ("PAIR_NAME", tag);
|
||||
}
|
||||
}
|
||||
tag = jsonparse_next (parser);
|
||||
if (tag != JSON_TYPE_PAIR) {
|
||||
BYE ("PAIR", tag);
|
||||
}
|
||||
tag = jsonparse_next (parser);
|
||||
if (tag != JSON_TYPE_STRING) {
|
||||
BYE ("STRING", tag);
|
||||
}
|
||||
jsonparse_copy_value (parser, buf, buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_uri (void *request)
|
||||
{
|
||||
static char buf [MAX_URI_STRING_LENGTH];
|
||||
const char *uri;
|
||||
size_t len = coap_get_header_uri_path (request, &uri);
|
||||
if (len > sizeof (buf) - 1) {
|
||||
*buf = '\0';
|
||||
} else {
|
||||
strncpy (buf, uri, len);
|
||||
buf [len] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *get_query (void *request)
|
||||
{
|
||||
static char buf [MAX_QUERY_STRING_LENGTH];
|
||||
const char *query;
|
||||
size_t len = coap_get_header_uri_query (request, &query);
|
||||
if (len > sizeof (buf) - 1) {
|
||||
*buf = '\0';
|
||||
} else {
|
||||
strncpy (buf, query, len);
|
||||
buf [len] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void generic_get_handler
|
||||
( void *request
|
||||
, void *response
|
||||
, uint8_t *buffer
|
||||
, uint16_t preferred_size
|
||||
, int32_t *offset
|
||||
, char *name
|
||||
, int is_str
|
||||
, size_t (*to_str)
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf, size_t bsize
|
||||
)
|
||||
)
|
||||
{
|
||||
int success = 1;
|
||||
char temp [MAX_GET_STRING_LENGTH];
|
||||
size_t len = 0;
|
||||
unsigned int accept = -1;
|
||||
const char *uri = get_uri (request);
|
||||
const char *query = get_query (request);
|
||||
|
||||
REST.get_header_accept (request, &accept);
|
||||
if ( accept != -1
|
||||
&& accept != REST.type.TEXT_PLAIN
|
||||
&& accept != REST.type.APPLICATION_JSON
|
||||
)
|
||||
{
|
||||
success = 0;
|
||||
REST.set_response_status (response, REST.status.NOT_ACCEPTABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// TEXT format
|
||||
if (accept == REST.type.APPLICATION_JSON) {
|
||||
len += snprintf
|
||||
( temp + len
|
||||
, sizeof (temp) - len
|
||||
, "{\n \"%s\" : %s"
|
||||
, name
|
||||
, is_str ? "\"" : ""
|
||||
);
|
||||
if (len > sizeof (temp)) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
len += to_str (name, uri, query, temp + len, sizeof (temp) - len);
|
||||
if (len > sizeof (temp)) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
len += snprintf
|
||||
( temp + len
|
||||
, sizeof (temp) - len
|
||||
, "%s\n}\n"
|
||||
, is_str ? "\"" : ""
|
||||
);
|
||||
if (len > sizeof (temp)) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
} else { // TEXT Format
|
||||
len += to_str (name, uri, query, temp + len, sizeof (temp) - len);
|
||||
if (len > sizeof (temp)) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
len += snprintf (temp + len, sizeof (temp) - len, "\n");
|
||||
if (len > sizeof (temp)) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
memcpy (buffer, temp, len);
|
||||
REST.set_header_content_type (response, accept);
|
||||
REST.set_response_payload (response, buffer, len);
|
||||
out :
|
||||
if (!success) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_put_handler
|
||||
( void *request
|
||||
, void *response
|
||||
, uint8_t *buffer
|
||||
, uint16_t preferred_size
|
||||
, int32_t *offset
|
||||
, char *name
|
||||
, int (*from_str)
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
)
|
||||
{
|
||||
int success = 1;
|
||||
char temp [100];
|
||||
size_t len = 0;
|
||||
const uint8_t *bytes = NULL;
|
||||
unsigned int c_ctype;
|
||||
const char *uri = get_uri (request);
|
||||
const char *query = get_query (request);
|
||||
REST.get_header_content_type (request, &c_ctype);
|
||||
|
||||
if (from_str && (len = coap_get_payload (request, &bytes))) {
|
||||
if (c_ctype == REST.type.TEXT_PLAIN) {
|
||||
int l = MIN (len, sizeof (temp) - 1);
|
||||
temp [sizeof (temp) - 1] = 0;
|
||||
strncpy (temp, (const char *)bytes, l);
|
||||
temp [l] = 0;
|
||||
} else { // jSON Format
|
||||
if (json_parse_variable (bytes, len, name, temp, sizeof (temp)) < 0) {
|
||||
success = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (from_str (name, uri, query, temp) < 0) {
|
||||
success = 0;
|
||||
} else {
|
||||
REST.set_response_status (response, REST.status.CHANGED);
|
||||
}
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
out:
|
||||
if (!success) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
178
apps/json-resource/generic_resource.h
Normal file
178
apps/json-resource/generic_resource.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright (c) 2014-15, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup Generic CoAP Resource Handler
|
||||
*
|
||||
* This factors the boilerplate code necessary for defining a resource
|
||||
* together with the necessary handler. Currently this supports
|
||||
* text/plain and application/json and outputs the resource with its
|
||||
* name in json format. This may change in the future as more CoRE
|
||||
* standards (e.g. see RFC 6690) get defined.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Generic CoAP Resource Handler
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*/
|
||||
|
||||
#define STR__(s) #s
|
||||
#define STR_(s) STR__(s)
|
||||
|
||||
#define MAX_GET_STRING_LENGTH 100
|
||||
#define MAX_URI_STRING_LENGTH 30
|
||||
#define MAX_QUERY_STRING_LENGTH 30
|
||||
|
||||
/*
|
||||
* A macro that extends the resource definition and also sets up the
|
||||
* necessary handler function that calls format/parse routines that
|
||||
* convert from/to string (fs and ts). The ts function needs to return
|
||||
* the length written, similar to sprintf.
|
||||
* The content type definitions ct="0 5" are text/plain and
|
||||
* application/json, respectively, see rfc7252 Table 9 p. 91.
|
||||
* Yes, this *is* a hack. But I hate boilerplate code.
|
||||
*/
|
||||
|
||||
#define GENERIC_RESOURCE(name, title, unit, is_str, fs, ts) \
|
||||
static void name##_get_handler \
|
||||
( void *request \
|
||||
, void *response \
|
||||
, uint8_t *buffer \
|
||||
, uint16_t ps \
|
||||
, int32_t *offset \
|
||||
) \
|
||||
{ \
|
||||
generic_get_handler \
|
||||
(request, response, buffer, ps, offset, STR_(name), is_str, ts); \
|
||||
} \
|
||||
static void name##_put_handler \
|
||||
( void *request \
|
||||
, void *response \
|
||||
, uint8_t *buffer \
|
||||
, uint16_t ps \
|
||||
, int32_t *offset \
|
||||
) \
|
||||
{ \
|
||||
generic_put_handler \
|
||||
(request, response, buffer, ps, offset, STR_(name), fs); \
|
||||
} \
|
||||
\
|
||||
RESOURCE ( res_##name \
|
||||
, "title=\"" STR_(title) "\"" \
|
||||
";rt=UCUM:\"" STR_(unit) "\"" \
|
||||
";ct=\"0 5\"" \
|
||||
, (ts) ? name##_get_handler : NULL \
|
||||
, NULL /* POST */ \
|
||||
, (fs) ? name##_put_handler : NULL \
|
||||
, NULL /* DELETE */ \
|
||||
)
|
||||
|
||||
/* Ignore constant pointer tests above */
|
||||
#pragma GCC diagnostic ignored "-Waddress"
|
||||
|
||||
/**
|
||||
* \brief Parse a resource in json format
|
||||
* \param bytes: Input string received via coap
|
||||
* \param len: Length of input string
|
||||
* \param name: Name to search in json input
|
||||
* \param buf: Output buffer
|
||||
* \param buflen: Output buffer length
|
||||
* \return 0 for success, -1 for error
|
||||
*
|
||||
* If compiled with DEBUG also prints the error encountered
|
||||
*/
|
||||
extern int8_t json_parse_variable
|
||||
(const uint8_t *bytes, size_t len, char *name, char *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* \brief Generic coap GET resource handler
|
||||
* \param name: The name of the variable in json
|
||||
* \param to_str: Application method to format value for output;
|
||||
* the function may chose to format differently for coap or text
|
||||
* The other parameters are the same as a normal resource handler
|
||||
* This helps avoid boilerplate code for request handlers
|
||||
*
|
||||
* The callback functions get the name of the parameter as a first
|
||||
* argument, this allows to re-use the same function for different
|
||||
* parameters. In addition it gets a buffer and the size of the buffer.
|
||||
* It needs to return the number of bytes output, similar to sprintf.
|
||||
*/
|
||||
extern void generic_get_handler
|
||||
( void *request
|
||||
, void *response
|
||||
, uint8_t *buffer
|
||||
, uint16_t preferred_size
|
||||
, int32_t *offset
|
||||
, char *name
|
||||
, int is_str
|
||||
, size_t (*to_str)
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Generic coap PUT resource handler
|
||||
* \param name: The name of the variable in json
|
||||
* \param from_str: Application method to parse value from string
|
||||
* and act on it, may be NULL in which case the resource only
|
||||
* supports GET not PUT
|
||||
* The other parameters are the same as a normal resource handler
|
||||
* This helps avoid boilerplate code for request handlers
|
||||
*
|
||||
* The callback functions get the name of the parameter as a first
|
||||
* argument, this allows to re-use the same function for different
|
||||
* parameters. The from_str in addition gets the string to parse.
|
||||
*/
|
||||
extern void generic_put_handler
|
||||
( void *request
|
||||
, void *response
|
||||
, uint8_t *buffer
|
||||
, uint16_t preferred_size
|
||||
, int32_t *offset
|
||||
, char *name
|
||||
, int (*from_str)
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
);
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
1
apps/ota-update/Makefile.ota-update
Normal file
1
apps/ota-update/Makefile.ota-update
Normal file
|
@ -0,0 +1 @@
|
|||
ota-update_src = res_bootloader.c res_reboot.c res_upload_image.c
|
22
apps/ota-update/ota-update.h
Normal file
22
apps/ota-update/ota-update.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
extern resource_t res_upload_image;
|
||||
extern resource_t res_part_count;
|
||||
extern resource_t res_part_size;
|
||||
extern resource_t res_boot_default;
|
||||
extern resource_t res_boot_next;
|
||||
extern resource_t res_active_part;
|
||||
extern resource_t res_part_start;
|
||||
extern resource_t res_part_ok;
|
||||
extern resource_t res_reboot;
|
||||
|
||||
#define OTA_ACTIVATE_RESOURCES() \
|
||||
static char resname[] = "ota/update";\
|
||||
rest_activate_resource (&res_upload_image, resname);\
|
||||
rest_activate_resource (&res_part_count, (char *)"ota/part_count");\
|
||||
rest_activate_resource (&res_part_size, (char *)"ota/part_size");\
|
||||
rest_activate_resource (&res_boot_default, (char *)"ota/boot_default");\
|
||||
rest_activate_resource (&res_boot_next, (char *)"ota/boot_next");\
|
||||
rest_activate_resource (&res_active_part, (char *)"ota/active_part");\
|
||||
rest_activate_resource (&res_part_start, (char *)"ota/part_start");\
|
||||
rest_activate_resource (&res_part_ok, (char *)"ota/part_ok");\
|
||||
rest_activate_resource (&res_reboot, (char *)"ota/reboot");
|
||||
|
260
apps/ota-update/res_bootloader.c
Normal file
260
apps/ota-update/res_bootloader.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Bootloader ressources
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "rest-engine.h"
|
||||
#include "er-coap-engine.h"
|
||||
#include "uiplib.h"
|
||||
#include "generic_resource.h"
|
||||
#include "bootloader_if.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
/*
|
||||
* Resources to be activated need to be imported through the extern keyword.
|
||||
* The build system automatically compiles the resources in the
|
||||
* corresponding sub-directory.
|
||||
*/
|
||||
|
||||
static size_t
|
||||
part_count
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_part_count ());
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( part_count
|
||||
, Partition Count
|
||||
, count
|
||||
, 0
|
||||
, NULL
|
||||
, part_count
|
||||
);
|
||||
|
||||
static size_t
|
||||
part_size
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_part_size ());
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( part_size
|
||||
, Partition Size
|
||||
, count
|
||||
, 0
|
||||
, NULL
|
||||
, part_size
|
||||
);
|
||||
|
||||
static size_t
|
||||
get_boot_default
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_boot_default ());
|
||||
}
|
||||
|
||||
static int
|
||||
set_boot_default
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
uint32_t tmp = strtoul (s, NULL, 10);
|
||||
bootloader_set_boot_default (tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( boot_default
|
||||
, Default boot partition
|
||||
, count
|
||||
, 0
|
||||
, set_boot_default
|
||||
, get_boot_default
|
||||
);
|
||||
|
||||
static size_t
|
||||
get_boot_next
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_boot_next ());
|
||||
}
|
||||
|
||||
static int
|
||||
set_boot_next
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
uint32_t tmp = strtoul (s, NULL, 10);
|
||||
bootloader_set_boot_next (tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( boot_next
|
||||
, Next boot partition
|
||||
, count
|
||||
, 0
|
||||
, set_boot_next
|
||||
, get_boot_next
|
||||
);
|
||||
|
||||
static size_t
|
||||
get_active_part
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_active_part ());
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( active_part
|
||||
, Currently active partition
|
||||
, count
|
||||
, 0
|
||||
, NULL
|
||||
, get_active_part
|
||||
);
|
||||
|
||||
/*
|
||||
* Parse query info. We insist that the query starts with 'part='
|
||||
* Then we parse the integer following the part= string and return the
|
||||
* number. The number is always positive, if something goes wrong we
|
||||
* return a negative number.
|
||||
*/
|
||||
static int get_query_partition (const char *query)
|
||||
{
|
||||
if (strncmp (query, "part=", 5)) {
|
||||
return -1;
|
||||
}
|
||||
return strtoul (query + 5, NULL, 10);
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_part_start
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
int idx = get_query_partition (query);
|
||||
if (idx < 0) {
|
||||
return snprintf (buf, bsize, "Invalid: \"%s\" use part=N query", query);
|
||||
}
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_part_start (idx));
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( part_start
|
||||
, Start of partition
|
||||
, count
|
||||
, 0
|
||||
, NULL
|
||||
, get_part_start
|
||||
);
|
||||
|
||||
static int
|
||||
set_part_ok
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
uint32_t tmp = strtoul (s, NULL, 10);
|
||||
int idx = get_query_partition (query);
|
||||
if (idx < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (tmp) {
|
||||
bootloader_set_part_ok (idx);
|
||||
} else {
|
||||
bootloader_clr_part_ok (idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_part_ok
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
int idx = get_query_partition (query);
|
||||
if (idx < 0) {
|
||||
return snprintf (buf, bsize, "Invalid: \"%s\" use part=N query", query);
|
||||
}
|
||||
return snprintf (buf, bsize, "%ld", bootloader_get_part_ok (idx));
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( part_ok
|
||||
, Set/Clear Partition OK flag
|
||||
, count
|
||||
, 0
|
||||
, set_part_ok
|
||||
, get_part_ok
|
||||
);
|
108
apps/ota-update/res_reboot.c
Normal file
108
apps/ota-update/res_reboot.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Marcus Priesch Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Reboot ressource
|
||||
* \author
|
||||
* Marcus Priesch <marcus@priesch.co.at>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "er-coap-engine.h"
|
||||
#include "generic_resource.h"
|
||||
#include "dev/watchdog.h"
|
||||
|
||||
PROCESS(reboot_process, "reboot");
|
||||
PROCESS_THREAD(reboot_process, ev, data)
|
||||
{
|
||||
static struct etimer etimer;
|
||||
|
||||
//PROCESS_EXITHANDLER(leds_off(LEDS_ALL);)
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
//shell_output_str(&reboot_command,
|
||||
// "Rebooting the node in four seconds...", "");
|
||||
|
||||
etimer_set(&etimer, CLOCK_SECOND * 4);
|
||||
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
||||
//leds_on(LEDS_RED);
|
||||
//etimer_reset(&etimer);
|
||||
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
||||
//leds_on(LEDS_GREEN);
|
||||
//etimer_reset(&etimer);
|
||||
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
||||
//leds_on(LEDS_BLUE);
|
||||
//etimer_reset(&etimer);
|
||||
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
||||
|
||||
watchdog_reboot();
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static size_t
|
||||
get_reboot
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
return snprintf (buf, bsize, "put 'OK' to reboot.");
|
||||
}
|
||||
|
||||
static int
|
||||
do_reboot
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
if (strncmp (s, "OK", 2) == 0) {
|
||||
process_start (&reboot_process, NULL);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( reboot
|
||||
, Reboot node
|
||||
, count
|
||||
, 0
|
||||
, do_reboot
|
||||
, get_reboot
|
||||
);
|
||||
|
243
apps/ota-update/res_upload_image.c
Normal file
243
apps/ota-update/res_upload_image.c
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (C) 2017, Marcus Priesch, Ralf Schlatterbeck
|
||||
* with code from the res-plugtest-large-update.c by
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Over-the-air update using blockwise transfer
|
||||
* \author
|
||||
* Marcus Priesch <marcus@priesch.co.at>
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "sys/cc.h"
|
||||
#include "rest-engine.h"
|
||||
#include "er-coap.h"
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "er-coap.h"
|
||||
#include "Arduino.h"
|
||||
#include <avr/interrupt.h>
|
||||
#include "bootloader_if.h"
|
||||
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#define PRINTF(x) printf x
|
||||
#else
|
||||
#define PRINTF(x)
|
||||
#endif
|
||||
|
||||
|
||||
// We allocate this statically, otherwise we cannot flash a new image
|
||||
// when ram is exhausted!
|
||||
static uint8_t current_page [256];
|
||||
static uint32_t current_offset = 0;
|
||||
#define PAGESIZE (sizeof (current_page))
|
||||
|
||||
/*
|
||||
* Note that the current code relies on the fact that the bootloader
|
||||
* used only supports two images. This may change in the future. We
|
||||
* mainly need to relax some of the checks and use a different algorithm
|
||||
* for computing imgidx, the index of the partition to be overwritten.
|
||||
* If the bootloader supports more than two partitions at some point we
|
||||
* may want the uploader to explicitly define the partition to be used.
|
||||
*/
|
||||
|
||||
static void
|
||||
res_put_handler
|
||||
( void *request
|
||||
, void *response
|
||||
, uint8_t *buffer
|
||||
, uint16_t preferred_size
|
||||
, int32_t *offset
|
||||
)
|
||||
{
|
||||
coap_packet_t *const packet = (coap_packet_t *)request;
|
||||
uint8_t *in_data = NULL;
|
||||
size_t len = 0;
|
||||
uint32_t partition_start = 0;
|
||||
const uint32_t partition_size = bootloader_get_part_size ();
|
||||
uint32_t imgidx = 0;
|
||||
unsigned int ct = -1;
|
||||
|
||||
/* If the currently-booted partition is not the default partition we
|
||||
* do not allow overwriting a partition: Neither the currently-booted
|
||||
* one (this would crash) nor the only partition that is marked
|
||||
* bootable. We also insist that boot_next == boot_default.
|
||||
*/
|
||||
if (bootloader_get_boot_default () != bootloader_get_boot_next ()) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
const char *error_msg = "Won't overwrite boot_next";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
if (bootloader_get_boot_default () != bootloader_get_active_part ()) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
const char *error_msg = "Won't overwrite current";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
imgidx = !bootloader_get_active_part ();
|
||||
partition_start = bootloader_get_part_start (imgidx);
|
||||
|
||||
REST.get_header_content_type (request, &ct);
|
||||
|
||||
/* Require content_type APPLICATION_OCTET_STREAM */
|
||||
if (ct != REST.type.APPLICATION_OCTET_STREAM) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
const char *error_msg = "ContentType";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
len = REST.get_request_payload (request, (const uint8_t **)&in_data);
|
||||
PRINTF (("cur: %lu len: %lu, offset: %lu\n",
|
||||
(uint32_t)current_offset, (uint32_t)len, (uint32_t)*offset));
|
||||
PRINTF (("b1-offs: %lu, b1-size: %u, b1-num: %lu b1-more: %d b1-size1: %lu\n",
|
||||
packet->block1_offset, packet->block1_size, packet->block1_num,
|
||||
packet->block1_more, packet->size1));
|
||||
if (len == 0 || NULL == in_data) {
|
||||
REST.set_response_status (response, REST.status.BAD_REQUEST);
|
||||
const char *error_msg = "NoPayload";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the block1_offset is 0 a new transmission has started */
|
||||
if (!packet->block1_offset) {
|
||||
current_offset = 0;
|
||||
}
|
||||
|
||||
if (packet->block1_offset > current_offset) {
|
||||
REST.set_response_status (response, REST.status.REQUEST_ENTITY_INCOMPLETE);
|
||||
const char *error_msg = "OutOfSequence";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Old packet or retransmission, immediately confirm */
|
||||
if (packet->block1_offset && packet->block1_offset + len <= current_offset) {
|
||||
REST.set_response_status (response, REST.status.CHANGED);
|
||||
coap_set_header_block1
|
||||
(response, packet->block1_num, 0, packet->block1_size);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: blocksize may be larger than our flash page size
|
||||
if (len > PAGESIZE) {
|
||||
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
|
||||
const char *error_msg = "GRMPF: PageSize";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
// FIXME: blocksize may be larger than our flash page size
|
||||
// So we should handle this case and repeatedly flash a block until the
|
||||
// received data is written.
|
||||
if (current_offset % PAGESIZE + len > PAGESIZE) {
|
||||
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
|
||||
const char *error_msg = "GRMPF: blocksize";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
// Should never happen, we test for < and > earlier.
|
||||
if (packet->block1_offset != current_offset) {
|
||||
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
|
||||
const char *error_msg = "GRMPF: Offset";
|
||||
REST.set_response_payload (response, error_msg, strlen (error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet->block1_offset + len > partition_size) {
|
||||
REST.set_response_status
|
||||
(response, REST.status.REQUEST_ENTITY_TOO_LARGE);
|
||||
REST.set_response_payload
|
||||
(response, buffer, sprintf ((char *)buffer, "%luB max.", partition_size));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (current_page + current_offset % PAGESIZE, in_data, len);
|
||||
/* Whenever an upload is started for a partition mark it as not ok */
|
||||
if (current_offset == 0) {
|
||||
PRINTF (("Clear partition_ok: %ld\n", imgidx));
|
||||
bootloader_clr_part_ok (imgidx);
|
||||
}
|
||||
current_offset += len;
|
||||
|
||||
if (current_offset % PAGESIZE == 0) {
|
||||
uint32_t dst_address = partition_start + current_offset - PAGESIZE;
|
||||
/* Special case: Flash irq vectors to backup position */
|
||||
if (current_offset - PAGESIZE < PART_IRQVEC_SIZE) {
|
||||
/* Only for images not at position 0 write first PART_IRQVEC_SIZE
|
||||
* bytes also to original position. For partition 0 it will be
|
||||
* copied there anyway *and* we would crash if we wrote to the
|
||||
* active memory!
|
||||
*/
|
||||
if (partition_start != 0) {
|
||||
PRINTF (("Flashing: %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
|
||||
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
|
||||
}
|
||||
/* Note: The partition_size returned by the bootloader does *NOT*
|
||||
* include the PART_IRQVEC_SIZE
|
||||
*/
|
||||
dst_address = partition_start + partition_size
|
||||
+ current_offset - PAGESIZE;
|
||||
}
|
||||
PRINTF (("Flashing: %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
|
||||
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
|
||||
} else if (!packet->block1_more) {
|
||||
uint32_t dst_address =
|
||||
partition_start + (current_offset / PAGESIZE) * PAGESIZE;
|
||||
PRINTF (("Flashing: last %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
|
||||
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
|
||||
}
|
||||
|
||||
|
||||
if (!packet->block1_more) {
|
||||
// we are finished
|
||||
bootloader_set_boot_next (imgidx);
|
||||
current_offset = 0;
|
||||
}
|
||||
|
||||
REST.set_response_status (response, REST.status.CHANGED);
|
||||
coap_set_header_block1 (response, packet->block1_num, 0, packet->block1_size);
|
||||
}
|
||||
|
||||
RESOURCE(
|
||||
res_upload_image
|
||||
, "title=\"Flash memory upgrade\";rt=\"block\""
|
||||
, NULL
|
||||
, NULL
|
||||
, res_put_handler
|
||||
, NULL
|
||||
);
|
||||
|
|
@ -56,6 +56,7 @@ struct rest_implementation_status {
|
|||
const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */
|
||||
const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */
|
||||
const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */
|
||||
const unsigned int REQUEST_ENTITY_INCOMPLETE; /* REQUEST_ENTITY_INCOMPLETE_4_08, REQUEST_ENTITY_INCOMPLETE_408 */
|
||||
const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */
|
||||
const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "arduino-process.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(serial_shell_process, "Contiki serial shell");
|
||||
|
@ -58,6 +58,8 @@ void
|
|||
shell_default_output(const char *text1, int len1, const char *text2, int len2)
|
||||
{
|
||||
int i;
|
||||
|
||||
mcu_sleep_disable();
|
||||
if(text1 == NULL) {
|
||||
text1 = "";
|
||||
len1 = 0;
|
||||
|
@ -89,6 +91,7 @@ void
|
|||
shell_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(serial_shell_process, ev, data)
|
||||
{
|
||||
|
@ -98,6 +101,7 @@ PROCESS_THREAD(serial_shell_process, ev, data)
|
|||
|
||||
while(1) {
|
||||
PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL);
|
||||
mcu_sleep_disable();
|
||||
shell_input(data, strlen(data));
|
||||
}
|
||||
|
||||
|
|
|
@ -66,3 +66,11 @@ endif
|
|||
ifeq ($(TARGET),z1)
|
||||
shell_src += shell-sky.c shell-exec.c
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),osd-merkur-256)
|
||||
shell_src += shell-merkur.c
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),osd-merkur-128)
|
||||
shell_src += shell-merkur.c
|
||||
endif
|
||||
|
|
237
apps/shell/shell-merkur.c
Normal file
237
apps/shell/shell-merkur.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Merkurboard-specific Contiki shell commands
|
||||
* \author
|
||||
* Harald Pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtol */
|
||||
#include "sys/cc.h"
|
||||
#include "dev/radio.h"
|
||||
#include "shell-merkur.h"
|
||||
#include "params.h"
|
||||
#include "arduino-process.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(shell_txpower_process, "txpower");
|
||||
SHELL_COMMAND(txpower_command,
|
||||
"txpower",
|
||||
"txpower <power>: change transmission power 0 (3dbm, default) to 15 (-17.2dbm)",
|
||||
&shell_txpower_process);
|
||||
PROCESS(shell_panid_process, "panid");
|
||||
SHELL_COMMAND(panid_command,
|
||||
"panid",
|
||||
"panid <0xabcd>: change panid (default 0xabcd)",
|
||||
&shell_panid_process);
|
||||
PROCESS(shell_rfchannel_process, "rfchannel");
|
||||
SHELL_COMMAND(rfchannel_command,
|
||||
"rfchannel",
|
||||
"rfchannel <channel>: change radio channel (11 - 26)",
|
||||
&shell_rfchannel_process);
|
||||
PROCESS(shell_ccathresholds_process, "ccathresholds");
|
||||
SHELL_COMMAND(ccathresholds_command,
|
||||
"ccathresholds",
|
||||
"ccathresholds <threshold: change cca thresholds -91 to -61 dBm (default -77)",
|
||||
&shell_ccathresholds_process);
|
||||
PROCESS(shell_macconf_process, "macconf");
|
||||
SHELL_COMMAND(macconf_command,
|
||||
"macconf",
|
||||
"macconf <conf>: change mac layer 0 -> do nothing; 1 -> Radio allways on",
|
||||
&shell_macconf_process);
|
||||
PROCESS(shell_saverfparam_process, "saverfparam");
|
||||
SHELL_COMMAND(saverfparam_command,
|
||||
"saverfparam",
|
||||
"saverfparam <> save radio parameters txpower, channel, panid to eeprom settingsmanager",
|
||||
&shell_saverfparam_process);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_txpower_process, ev, data)
|
||||
{
|
||||
radio_value_t value;
|
||||
char buf[10];
|
||||
const char *newptr;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
value = shell_strtolong(data, &newptr);
|
||||
|
||||
/* If no transmission power was given on the command line, we print
|
||||
out the current txpower. */
|
||||
if(newptr == data) {
|
||||
if(get_param(RADIO_PARAM_TXPOWER, &value) == RADIO_RESULT_OK) {
|
||||
}
|
||||
} else {
|
||||
set_param(RADIO_PARAM_TXPOWER, value);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%3d", value);
|
||||
shell_output_str(&txpower_command, "TX Power: ", buf);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_rfchannel_process, ev, data)
|
||||
{
|
||||
radio_value_t value;
|
||||
char buf[10];
|
||||
const char *newptr;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
value = shell_strtolong(data, &newptr);
|
||||
|
||||
/* If no channel was given on the command line, we print out the
|
||||
current channel. */
|
||||
if(newptr == data) {
|
||||
if(get_param(RADIO_PARAM_CHANNEL, &value) == RADIO_RESULT_OK) {
|
||||
|
||||
}
|
||||
} else {
|
||||
set_param(RADIO_PARAM_CHANNEL, value);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", value);
|
||||
shell_output_str(&rfchannel_command, "Channel: ", buf);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_ccathresholds_process, ev, data)
|
||||
{
|
||||
radio_value_t value;
|
||||
char buf[10];
|
||||
const char *newptr;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
value = shell_strtolong(data, &newptr);
|
||||
|
||||
/* If no channel was given on the command line, we print out the
|
||||
current channel. */
|
||||
if(newptr == data) {
|
||||
if(get_param(RADIO_PARAM_CCA_THRESHOLD, &value) == RADIO_RESULT_OK) {
|
||||
|
||||
}
|
||||
} else {
|
||||
set_param(RADIO_PARAM_CCA_THRESHOLD, value);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d dBm", value);
|
||||
shell_output_str(&rfchannel_command, "CCA Threshold: ", buf);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_macconf_process, ev, data)
|
||||
{
|
||||
radio_value_t value;
|
||||
char buf[10];
|
||||
const char *newptr;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
value = shell_strtolong(data, &newptr);
|
||||
|
||||
/* If no transmission power was given on the command line, we print
|
||||
out the current macconf. */
|
||||
if(newptr == data) {
|
||||
value = params_get_macconf();
|
||||
} else {
|
||||
params_set_macconf(value);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%3d", value);
|
||||
shell_output_str(&txpower_command, "macconf: ", buf);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_panid_process, ev, data)
|
||||
{
|
||||
radio_value_t value;
|
||||
char buf[10];
|
||||
char *newptr;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
value = strtol(data, &newptr, 0);
|
||||
|
||||
/* If no channel was given on the command line, we print out the
|
||||
current channel. */
|
||||
if(newptr == data) {
|
||||
if(get_param(RADIO_PARAM_PAN_ID, &value) != RADIO_RESULT_OK) {
|
||||
// printf("error: get_param RADIO_PARAM_PAN_ID\n");
|
||||
}
|
||||
} else {
|
||||
set_param(RADIO_PARAM_PAN_ID, value);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf),"0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF);
|
||||
shell_output_str(&panid_command, "panid: ", buf);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_saverfparam_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
/* Save txpower */
|
||||
params_save_txpower();
|
||||
/* Save rfchannel */
|
||||
params_save_channel();
|
||||
/* Save ccathresholds */
|
||||
// todo
|
||||
|
||||
/* Save panid */
|
||||
params_save_panid();
|
||||
/* Save macconf */
|
||||
params_save_macconf();
|
||||
|
||||
shell_output_str(&rfchannel_command, "saverfparam done ", 0);
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
shell_merkur_init(void)
|
||||
{
|
||||
// shell_ps_init();
|
||||
shell_reboot_init();
|
||||
shell_register_command(&txpower_command);
|
||||
shell_register_command(&rfchannel_command);
|
||||
shell_register_command(&ccathresholds_command);
|
||||
shell_register_command(&panid_command);
|
||||
shell_register_command(&macconf_command);
|
||||
shell_register_command(&saverfparam_command);
|
||||
// shell_register_command(&s_command);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
47
apps/shell/shell-merkur.h
Normal file
47
apps/shell/shell-merkur.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for Tmote Sky-specific Contiki shell commands
|
||||
* \author
|
||||
* harald pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
#ifndef SHELL_MERKUR_H_
|
||||
#define SHELL_MERKUR_H_
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
void shell_merkur_init(void);
|
||||
|
||||
#endif /* SHELL_MERKUR_H_ */
|
2
apps/time/Makefile.time
Normal file
2
apps/time/Makefile.time
Normal file
|
@ -0,0 +1,2 @@
|
|||
time_src = time.c resource_gmtime.c resource_timestamp.c \
|
||||
resource_timezone.c resource_crontab.c cron.c
|
20
apps/time/README
Normal file
20
apps/time/README
Normal file
|
@ -0,0 +1,20 @@
|
|||
Timezones
|
||||
=========
|
||||
|
||||
The new version supports time zones and daylight saving time (DST).
|
||||
Currently we support only a single timezone. We use the UNIX timezone
|
||||
format which is usually specified in an environment variable TZ.
|
||||
|
||||
Note that for timezone information you can have different
|
||||
representation, either relative to Universal Time Coordinated (UTC) or
|
||||
to International Atomic Time (TAI), the latter contains leap seconds.
|
||||
Since most systems today use UTC *and* the clock of a microcontroller
|
||||
is typically not accurate enough to care about leap seconds, we're using
|
||||
timezone files relative to UTC.
|
||||
|
||||
Wikipedia has a very good treatment of the public timezone database in
|
||||
https://en.wikipedia.org/wiki/Tz_database
|
||||
|
||||
The format of timezone strings is described in the Linux manual page
|
||||
tzset(3). The timezone specification for Europe/Vienna is
|
||||
CET-1CEST,M3.5.0,M10.5.0/3
|
118
apps/time/bitstring.h
Normal file
118
apps/time/bitstring.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 1989 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Paul Vixie.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* @(#)bitstring.h 5.2 (Berkeley) 4/4/90
|
||||
*/
|
||||
|
||||
typedef unsigned char bitstr_t;
|
||||
|
||||
/* internal macros */
|
||||
/* byte of the bitstring bit is in */
|
||||
#define _bit_byte(bit) \
|
||||
((bit) >> 3)
|
||||
|
||||
/* mask for the bit within its byte */
|
||||
#define _bit_mask(bit) \
|
||||
(1 << ((bit)&0x7))
|
||||
|
||||
/* external macros */
|
||||
/* bytes in a bitstring of nbits bits */
|
||||
#define bitstr_size(nbits) \
|
||||
((((nbits) - 1) >> 3) + 1)
|
||||
|
||||
|
||||
/* allocate a bitstring on the stack */
|
||||
#define bit_decl(name, nbits) \
|
||||
(name)[bitstr_size(nbits)]
|
||||
|
||||
/* is bit N of bitstring name set? */
|
||||
#define bit_test(name, bit) \
|
||||
((name)[_bit_byte(bit)] & _bit_mask(bit))
|
||||
|
||||
/* set bit N of bitstring name */
|
||||
#define bit_set(name, bit) \
|
||||
(name)[_bit_byte(bit)] |= _bit_mask(bit)
|
||||
|
||||
/* clear bit N of bitstring name */
|
||||
#define bit_clear(name, bit) \
|
||||
(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
|
||||
|
||||
/* clear bits start ... stop in bitstring */
|
||||
#define bit_nclear(name, start, stop) { \
|
||||
register bitstr_t *_name = name; \
|
||||
register int _start = start, _stop = stop; \
|
||||
register int _startbyte = _bit_byte(_start); \
|
||||
register int _stopbyte = _bit_byte(_stop); \
|
||||
if (_startbyte == _stopbyte) { \
|
||||
_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
|
||||
(0xff << ((_stop&0x7) + 1))); \
|
||||
} else { \
|
||||
_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
|
||||
while (++_startbyte < _stopbyte) \
|
||||
_name[_startbyte] = 0; \
|
||||
_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* set bits start ... stop in bitstring */
|
||||
#define bit_nset(name, start, stop) { \
|
||||
register bitstr_t *_name = name; \
|
||||
register int _start = start, _stop = stop; \
|
||||
register int _startbyte = _bit_byte(_start); \
|
||||
register int _stopbyte = _bit_byte(_stop); \
|
||||
if (_startbyte == _stopbyte) { \
|
||||
_name[_startbyte] |= ((0xff << (_start&0x7)) & \
|
||||
(0xff >> (7 - (_stop&0x7)))); \
|
||||
} else { \
|
||||
_name[_startbyte] |= 0xff << ((_start)&0x7); \
|
||||
while (++_startbyte < _stopbyte) \
|
||||
_name[_startbyte] = 0xff; \
|
||||
_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* find first bit clear in name */
|
||||
#define bit_ffc(name, nbits, value) { \
|
||||
register bitstr_t *_name = name; \
|
||||
register int _byte, _nbits = nbits; \
|
||||
register int _stopbyte = _bit_byte(_nbits), _value = -1; \
|
||||
for (_byte = 0; _byte <= _stopbyte; ++_byte) \
|
||||
if (_name[_byte] != 0xff) { \
|
||||
_value = _byte << 3; \
|
||||
for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
|
||||
++_value, _stopbyte >>= 1); \
|
||||
break; \
|
||||
} \
|
||||
*(value) = _value; \
|
||||
}
|
||||
|
||||
/* find first bit set in name */
|
||||
#define bit_ffs(name, nbits, value) { \
|
||||
register bitstr_t *_name = name; \
|
||||
register int _byte, _nbits = nbits; \
|
||||
register int _stopbyte = _bit_byte(_nbits), _value = -1; \
|
||||
for (_byte = 0; _byte <= _stopbyte; ++_byte) \
|
||||
if (_name[_byte]) { \
|
||||
_value = _byte << 3; \
|
||||
for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
|
||||
++_value, _stopbyte >>= 1); \
|
||||
break; \
|
||||
} \
|
||||
*(value) = _value; \
|
||||
}
|
488
apps/time/cron.c
Normal file
488
apps/time/cron.c
Normal file
|
@ -0,0 +1,488 @@
|
|||
/**
|
||||
* \file
|
||||
* cron: Cron-like functionality
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
* \brief cron-like command scheduler
|
||||
*
|
||||
* Inspired by vixie's cron by Paul Vixie which is
|
||||
* Copyright 1988,1990,1993,1994 by Paul Vixie
|
||||
*
|
||||
* Distribute freely, except: don't remove my name from the source or
|
||||
* documentation (don't take credit for my work), mark your changes (don't
|
||||
* get me blamed for your possible bugs), don't alter or remove this
|
||||
* notice. May be sold if buildable source is provided to buyer. No
|
||||
* warrantee of any kind, express or implied, is included with this
|
||||
* software; use at your own risk, responsibility for damages (if any) to
|
||||
* anyone resulting from the use of this software rests entirely with the
|
||||
* user.
|
||||
*
|
||||
* Changes to make this work on a microcontroller by Ralf Schlatterbeck
|
||||
* In fact this is mostly a rewrite but keeps central algorithms and
|
||||
* some data structures of the original.
|
||||
* The syntax is simplified, we don't support the @ notation (e.g.
|
||||
* @hourly) and named entities (e.g. weekday names instead of numbers).
|
||||
* Furthermore we can't send email and don't support environment
|
||||
* variables. The called commands are functions registered via a
|
||||
* registration mechanism before runtime.
|
||||
* Copyright 2016 Ralf Schlatterbeck, distribute with the conditions
|
||||
* given above.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include "contiki.h"
|
||||
#include "cron.h"
|
||||
#include "xtime.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
static struct cron_entry cron_entries [MAX_CRON_ENTRIES];
|
||||
static struct cron_cmd cron_commands [MAX_CRON_COMMANDS];
|
||||
static size_t cron_registered_entries = 0;
|
||||
static size_t cron_registered_commands = 0;
|
||||
static struct cron_entry *entry_freelist = NULL;
|
||||
static struct cron_entry *entry_list = NULL;
|
||||
|
||||
typedef int64_t minute_t;
|
||||
static xtime_t start_time;
|
||||
static minute_t cron_clock_time;
|
||||
|
||||
/* Register a new cron command
|
||||
* A command consists of a name (which must be unique, uniqueness is not
|
||||
* enforced currently as registrations are done once at initialization
|
||||
* time), a function to be called and a parameter.
|
||||
*/
|
||||
int cron_register_command
|
||||
(const char *name, void (*function)(void *), void * parameter)
|
||||
{
|
||||
if (cron_registered_commands >= MAX_CRON_COMMANDS) {
|
||||
return -1;
|
||||
}
|
||||
cron_commands [cron_registered_commands].name = name;
|
||||
cron_commands [cron_registered_commands].function = function;
|
||||
cron_commands [cron_registered_commands].parameter = parameter;
|
||||
cron_registered_commands++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new crontab entry.
|
||||
* This allocates from the freelist and returns NULL if no more entries
|
||||
* are available.
|
||||
* Implementation note: If cron_registered_entries is 0 we first
|
||||
* initialize the entry_freelist and the entry_list.
|
||||
*/
|
||||
struct cron_entry *allocate_cron_entry (void)
|
||||
{
|
||||
size_t n;
|
||||
struct cron_entry *e;
|
||||
if (cron_registered_entries == 0) {
|
||||
entry_list = NULL;
|
||||
entry_freelist = &cron_entries [0];
|
||||
for (n=0; n < (MAX_CRON_ENTRIES - 1); n++) {
|
||||
cron_entries [n].next = &cron_entries [n+1];
|
||||
}
|
||||
cron_entries [MAX_CRON_ENTRIES - 1].next = NULL;
|
||||
}
|
||||
if (cron_registered_entries >= MAX_CRON_ENTRIES) {
|
||||
return NULL;
|
||||
}
|
||||
e = entry_freelist;
|
||||
entry_freelist = e->next;
|
||||
e->next = entry_list;
|
||||
entry_list = e;
|
||||
cron_registered_entries++;
|
||||
return e;
|
||||
}
|
||||
|
||||
void free_cron_entry (struct cron_entry *obsolete)
|
||||
{
|
||||
struct cron_entry *e;
|
||||
assert (cron_registered_entries);
|
||||
if (entry_list == obsolete) {
|
||||
entry_list = obsolete->next;
|
||||
obsolete->next = entry_freelist;
|
||||
entry_freelist = obsolete;
|
||||
cron_registered_entries--;
|
||||
return;
|
||||
}
|
||||
for (e=entry_list; e; e=e->next) {
|
||||
if (e->next == obsolete) {
|
||||
e->next = obsolete->next;
|
||||
obsolete->next = entry_freelist;
|
||||
entry_freelist = obsolete;
|
||||
cron_registered_entries--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert (e != NULL);
|
||||
}
|
||||
|
||||
struct cron_entry *get_cron_entry (size_t idx)
|
||||
{
|
||||
if (idx >= MAX_CRON_ENTRIES) {
|
||||
return NULL;
|
||||
}
|
||||
return &cron_entries [idx];
|
||||
}
|
||||
|
||||
/* Set the number in bits, return 0 on success -1 on error */
|
||||
static int set_element (bitstr_t *bits, int low, int high, int n)
|
||||
{
|
||||
if (n < low || n > high) {
|
||||
return -1;
|
||||
}
|
||||
bit_set (bits, (n - low));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_number (int *np, int high, const char *s)
|
||||
{
|
||||
char *endptr;
|
||||
long l = strtol (s, &endptr, 10);
|
||||
if (endptr == s || errno == ERANGE || l > high) {
|
||||
return NULL;
|
||||
}
|
||||
*np = l;
|
||||
return endptr;
|
||||
}
|
||||
|
||||
static const char *get_range (bitstr_t *bits, int low, int high, const char *s)
|
||||
{
|
||||
int i;
|
||||
int n1, n2, n3;
|
||||
|
||||
if (*s == '*') {
|
||||
/* '*' means "first-last" but can be modified by /step */
|
||||
n1 = low;
|
||||
n2 = high;
|
||||
if (*++s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
s = get_number (&n1, high, s);
|
||||
if (s == NULL || *s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
if (*s != '-') {
|
||||
if (set_element (bits, low, high, n1) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return s;
|
||||
} else {
|
||||
if (*++s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
s = get_number (&n2, high, s);
|
||||
if (*s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*s == '/') {
|
||||
if (*++s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
s = get_number (&n3, high, s);
|
||||
if (*s == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
n3 = 1;
|
||||
}
|
||||
/* Explicit check for sane values */
|
||||
if (n1 < low || n1 > high || n2 < low || n2 > high) {
|
||||
return NULL;
|
||||
}
|
||||
for (i=n1; i<=n2; i+=n3) {
|
||||
if (set_element (bits, low, high, i) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static const char *get_list (bitstr_t *bits, int low, int high, const char *s)
|
||||
{
|
||||
int done = 0;
|
||||
bit_nclear (bits, 0, (high - low + 1));
|
||||
while (!done) {
|
||||
s = get_range (bits, low, high, s);
|
||||
if (NULL == s) {
|
||||
return NULL;
|
||||
}
|
||||
if (*s == ',') {
|
||||
s++;
|
||||
} else {
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
/* Skip white space */
|
||||
while (s && isspace (*s)) {
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a single crontab entry on a single line.
|
||||
* We get the line via CoAP.
|
||||
* Returns 0 if parsed successfully, -1 on error.
|
||||
* On error the err pointer is set to the error message.
|
||||
*/
|
||||
int parse_crontab_line
|
||||
(const char *line, struct cron_entry *e, const char **err)
|
||||
{
|
||||
size_t n;
|
||||
const char *s = line;
|
||||
size_t cmd_len = 0;
|
||||
|
||||
e->flags &= ~VALID;
|
||||
if (*s == '*') {
|
||||
e->flags |= MIN_STAR;
|
||||
}
|
||||
s = get_list (e->minute, FIRST_MINUTE, LAST_MINUTE, s);
|
||||
if (NULL == s || *s == '\0') {
|
||||
*err = "minute";
|
||||
return -1;
|
||||
}
|
||||
if (*s == '*') {
|
||||
e->flags |= HR_STAR;
|
||||
}
|
||||
s = get_list (e->hour, FIRST_HOUR, LAST_HOUR, s);
|
||||
if (NULL == s || *s == '\0') {
|
||||
*err = "hour";
|
||||
return -1;
|
||||
}
|
||||
if (*s == '*') {
|
||||
e->flags |= DOM_STAR;
|
||||
}
|
||||
s = get_list (e->dom, FIRST_DOM, LAST_DOM, s);
|
||||
if (NULL == s || *s == '\0') {
|
||||
*err = "dom";
|
||||
return -1;
|
||||
}
|
||||
s = get_list (e->month, FIRST_MONTH, LAST_MONTH, s);
|
||||
if (NULL == s || *s == '\0') {
|
||||
*err = "month";
|
||||
return -1;
|
||||
}
|
||||
if (*s == '*') {
|
||||
e->flags |= DOW_STAR;
|
||||
}
|
||||
s = get_list (e->dow, FIRST_DOW, LAST_DOW, s);
|
||||
if (NULL == s || *s == '\0') {
|
||||
*err = "dow";
|
||||
return -1;
|
||||
}
|
||||
/* Make sundays equivalent */
|
||||
if (bit_test (e->dow, 0) || bit_test (e->dow, 7)) {
|
||||
bit_set (e->dow, 0);
|
||||
bit_set (e->dow, 7);
|
||||
}
|
||||
/* strip whitespace at *end* of command
|
||||
* by getting length without whitespace
|
||||
*/
|
||||
for (n=0; s [n]; n++) {
|
||||
if (!isspace (s [n])) {
|
||||
cmd_len = n + 1;
|
||||
}
|
||||
}
|
||||
for (n=0; n<cron_registered_commands; n++) {
|
||||
if ( cmd_len == strlen (cron_commands [n].name)
|
||||
&& !strncmp (cron_commands [n].name, s, cmd_len)
|
||||
)
|
||||
{
|
||||
e->cmd = &cron_commands [n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == cron_registered_commands) {
|
||||
*err = "command";
|
||||
return -1;
|
||||
}
|
||||
e->flags |= VALID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_time (void)
|
||||
{
|
||||
struct xtm *tm;
|
||||
struct xtimeval tv;
|
||||
xgettimeofday (&tv, NULL);
|
||||
start_time = tv.tv_sec;
|
||||
tm = xlocaltime (&start_time);
|
||||
/* We adjust the time to GMT so we can catch DST changes */
|
||||
cron_clock_time = (start_time + tm->tm_gmtoff) / (xtime_t)SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
static void find_jobs (minute_t vtime, int do_wild, int do_nonwild)
|
||||
{
|
||||
xtime_t virtual_second = vtime * SECONDS_PER_MINUTE;
|
||||
struct xtm *tm = xgmtime (&virtual_second);
|
||||
int minute, hour, dom, month, dow;
|
||||
struct cron_entry *e;
|
||||
|
||||
/* make 0-based values out of these so we can use them as indicies */
|
||||
minute = tm->tm_min -FIRST_MINUTE;
|
||||
hour = tm->tm_hour -FIRST_HOUR;
|
||||
dom = tm->tm_mday -FIRST_DOM;
|
||||
month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
|
||||
dow = tm->tm_wday -FIRST_DOW;
|
||||
#ifdef DEBUG
|
||||
printf ("%d %d %d %d %d\n", minute, hour, dom, month, dow);
|
||||
#endif
|
||||
|
||||
/* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the
|
||||
* first and fifteenth AND every Sunday; '* * * * Sun' will run *only*
|
||||
* on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this
|
||||
* is why we keep 'e->dow_star' and 'e->dom_star'. yes, it's bizarre.
|
||||
* like many bizarre things, it's the standard.
|
||||
*/
|
||||
for (e = entry_list; e; e = e->next) {
|
||||
#ifdef DEBUG
|
||||
if (e->flags & VALID) {
|
||||
printf ("Checking entry %s\n", e->cmd->name);
|
||||
}
|
||||
printf ("valid: %d\n", (e->flags & VALID));
|
||||
printf ("minute: %d\n", (bit_test (e->minute, minute)));
|
||||
printf ("hour: %d\n", (bit_test (e->hour, hour)));
|
||||
printf ("month %d\n", (bit_test (e->month, month)));
|
||||
printf ("dom* %d\n", (e->flags & DOM_STAR));
|
||||
printf ("dow* %d\n", (e->flags & DOW_STAR));
|
||||
printf ("dow %d\n", (bit_test (e->dow, dow)));
|
||||
printf ("dom %d\n", (bit_test (e->dom, dom)));
|
||||
printf ("min* %d\n", (e->flags & MIN_STAR));
|
||||
printf ("hr* %d\n", (e->flags & HR_STAR));
|
||||
printf ("nonwild %d\n", (do_nonwild));
|
||||
#endif
|
||||
if ( (e->flags & VALID)
|
||||
&& bit_test (e->minute, minute)
|
||||
&& bit_test (e->hour, hour)
|
||||
&& bit_test (e->month, month)
|
||||
&& ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
|
||||
? (bit_test (e->dow, dow) && bit_test (e->dom, dom))
|
||||
: (bit_test (e->dow, dow) || bit_test (e->dom, dom))
|
||||
)
|
||||
)
|
||||
{
|
||||
if ( (do_nonwild && !(e->flags & (MIN_STAR | HR_STAR)))
|
||||
|| (do_wild && (e->flags & (MIN_STAR | HR_STAR)))
|
||||
)
|
||||
{
|
||||
printf ("Cron: calling \"%s\"\n", e->cmd->name);
|
||||
e->cmd->function (e->cmd->parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The cron callback function must be run regularly, at least once per
|
||||
* minute.
|
||||
* Implementation:
|
||||
* Clocks are in minutes since the epoch (time() / 60).
|
||||
* virtual_time is the time it *would* be if we are called promptly and
|
||||
* nobody ever changed the clock. It is monotonically increasing...
|
||||
* unless a timejump happens.
|
||||
* time_running is the time we were last called. We determine
|
||||
* initialization by checking time_running for -1.
|
||||
* cron_clock_time is the current time for this run.
|
||||
*/
|
||||
void cron (void)
|
||||
{
|
||||
static minute_t time_running = -1;
|
||||
static minute_t virtual_time = -1;
|
||||
minute_t time_diff;
|
||||
|
||||
/*
|
||||
* ... calculate how the current time differs from
|
||||
* our virtual clock. Classify the change into one
|
||||
* of 4 cases
|
||||
*/
|
||||
set_time ();
|
||||
if (time_running == cron_clock_time) {
|
||||
#ifdef DEBUG
|
||||
printf ("time not reached\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
time_running = cron_clock_time;
|
||||
time_diff = time_running - virtual_time;
|
||||
#ifdef DEBUG
|
||||
printf ("time_diff: %ld\n", (long)time_diff);
|
||||
#endif
|
||||
/* shortcut for the most common case */
|
||||
if (time_diff == 1) {
|
||||
virtual_time = time_running;
|
||||
find_jobs (virtual_time, 1, 1);
|
||||
} else {
|
||||
int wakeup_kind = -1;
|
||||
if (time_diff > -(3*MINUTE_COUNT)) {
|
||||
wakeup_kind = 0;
|
||||
}
|
||||
if (time_diff > 0) {
|
||||
wakeup_kind = 1;
|
||||
}
|
||||
if (time_diff > 5) {
|
||||
wakeup_kind = 2;
|
||||
}
|
||||
if (time_diff > (3*MINUTE_COUNT)) {
|
||||
wakeup_kind = 3;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf ("wakeup_kind: %d\n", wakeup_kind);
|
||||
#endif
|
||||
switch (wakeup_kind) {
|
||||
/* time_diff is a small positive number (wokeup late)
|
||||
* run jobs for each virtual minute until caught up.
|
||||
*/
|
||||
case 1:
|
||||
do {
|
||||
virtual_time++;
|
||||
find_jobs (virtual_time, 1, 1);
|
||||
} while (virtual_time < time_running);
|
||||
break;
|
||||
/* time_diff is a medium-sized positive number, for example
|
||||
* because we went to DST. Run wildcard jobs once, then run any
|
||||
* fixed-time jobs that would otherwise be skipped. If we use up
|
||||
* our minute (possible, if there are a lot of jobs to run) go
|
||||
* around the loop again so that wildcard jobs have a chance to
|
||||
* run, and we do our housekeeping.
|
||||
*/
|
||||
case 2:
|
||||
/* run wildcard jobs for current minute */
|
||||
find_jobs (time_running, 1, 0);
|
||||
/* run fixed-time jobs for each minute missed */
|
||||
do {
|
||||
virtual_time++;
|
||||
find_jobs (virtual_time, 0, 1);
|
||||
set_time ();
|
||||
} while ( virtual_time < time_running
|
||||
&& cron_clock_time == time_running
|
||||
);
|
||||
break;
|
||||
/* time_diff is a small or medium-sized negative num, eg.
|
||||
* because of DST ending. Just run the wildcard jobs. The
|
||||
* fixed-time jobs probably have already run, and should not be
|
||||
* repeated. virtual_time does not change until we are caught up.
|
||||
*/
|
||||
case 0:
|
||||
find_jobs (time_running, 1, 0);
|
||||
break;
|
||||
/* Other: time has changed a *lot*, jump virtual time, and run
|
||||
* everything
|
||||
*/
|
||||
default:
|
||||
virtual_time = time_running;
|
||||
find_jobs (time_running, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
91
apps/time/cron.h
Normal file
91
apps/time/cron.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Definitions for cron
|
||||
* Inspired by vixie's cron by Paul Vixie which is
|
||||
* Copyright 1988,1990,1993,1994 by Paul Vixie
|
||||
*
|
||||
* Distribute freely, except: don't remove my name from the source or
|
||||
* documentation (don't take credit for my work), mark your changes (don't
|
||||
* get me blamed for your possible bugs), don't alter or remove this
|
||||
* notice. May be sold if buildable source is provided to buyer. No
|
||||
* warrantee of any kind, express or implied, is included with this
|
||||
* software; use at your own risk, responsibility for damages (if any) to
|
||||
* anyone resulting from the use of this software rests entirely with the
|
||||
* user.
|
||||
* Changes to make this work on a microcontroller by Ralf Schlatterbeck
|
||||
* In fact this is mostly a rewrite but keeps central algorithms of the
|
||||
* original.
|
||||
* Copyright 2016 Ralf Schlatterbeck, distribute with the conditions
|
||||
* given above.
|
||||
*/
|
||||
|
||||
#ifndef _cron_h_
|
||||
#define _cron_h_
|
||||
|
||||
#include "bitstring.h"
|
||||
|
||||
#define SECONDS_PER_MINUTE 60
|
||||
|
||||
#define FIRST_MINUTE 0
|
||||
#define LAST_MINUTE 59
|
||||
#define MINUTE_COUNT (LAST_MINUTE - FIRST_MINUTE + 1)
|
||||
|
||||
#define FIRST_HOUR 0
|
||||
#define LAST_HOUR 23
|
||||
#define HOUR_COUNT (LAST_HOUR - FIRST_HOUR + 1)
|
||||
|
||||
#define FIRST_DOM 1
|
||||
#define LAST_DOM 31
|
||||
#define DOM_COUNT (LAST_DOM - FIRST_DOM + 1)
|
||||
|
||||
#define FIRST_MONTH 1
|
||||
#define LAST_MONTH 12
|
||||
#define MONTH_COUNT (LAST_MONTH - FIRST_MONTH + 1)
|
||||
|
||||
/* note on DOW: 0 and 7 are both Sunday, for compatibility reasons. */
|
||||
#define FIRST_DOW 0
|
||||
#define LAST_DOW 7
|
||||
#define DOW_COUNT (LAST_DOW - FIRST_DOW + 1)
|
||||
|
||||
#ifndef MAX_CRON_ENTRIES
|
||||
#define MAX_CRON_ENTRIES 5
|
||||
#endif
|
||||
|
||||
#ifndef MAX_CRON_COMMANDS
|
||||
#define MAX_CRON_COMMANDS 5
|
||||
#endif
|
||||
|
||||
struct cron_cmd {
|
||||
const char *name;
|
||||
void (*function)(void *);
|
||||
void *parameter;
|
||||
};
|
||||
|
||||
struct cron_entry {
|
||||
struct cron_entry *next;
|
||||
struct cron_cmd *cmd;
|
||||
bitstr_t bit_decl(minute, MINUTE_COUNT);
|
||||
bitstr_t bit_decl(hour, HOUR_COUNT);
|
||||
bitstr_t bit_decl(dom, DOM_COUNT);
|
||||
bitstr_t bit_decl(month, MONTH_COUNT);
|
||||
bitstr_t bit_decl(dow, DOW_COUNT);
|
||||
int flags;
|
||||
|
||||
#define DOM_STAR 0x01
|
||||
#define DOW_STAR 0x02
|
||||
#define WHEN_REBOOT 0x04
|
||||
#define MIN_STAR 0x08
|
||||
#define HR_STAR 0x10
|
||||
#define VALID 0x20
|
||||
};
|
||||
|
||||
extern int parse_crontab_line
|
||||
(const char *line, struct cron_entry *e, const char **err);
|
||||
extern int cron_register_command
|
||||
(const char *name, void (*function)(void *), void * parameter);
|
||||
|
||||
extern struct cron_entry *allocate_cron_entry (void);
|
||||
extern struct cron_entry *get_cron_entry (size_t idx);
|
||||
extern void free_cron_entry (struct cron_entry *e);
|
||||
extern void cron (void);
|
||||
|
||||
#endif /* _cron_h_ */
|
125
apps/time/resource_crontab.c
Normal file
125
apps/time/resource_crontab.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* \file
|
||||
* Resource for crontab entry
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
* \brief get/put crontab entry
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "time_resource.h"
|
||||
#include "jsonparse.h"
|
||||
#include "er-coap.h"
|
||||
#include "generic_resource.h"
|
||||
#include "cron.h"
|
||||
|
||||
static size_t get_index_from_uri (const char *uri)
|
||||
{
|
||||
const char *s;
|
||||
char *endptr;
|
||||
size_t idx;
|
||||
if (uri == NULL) {
|
||||
return MAX_CRON_ENTRIES;
|
||||
}
|
||||
if (NULL == (s = strrchr (uri, '/'))) {
|
||||
return MAX_CRON_ENTRIES;
|
||||
}
|
||||
idx = strtoul (s+1, &endptr, 10);
|
||||
if (s == endptr || *endptr != '\0') {
|
||||
return MAX_CRON_ENTRIES;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
int crontab_from_string
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
const char *err;
|
||||
int res;
|
||||
size_t idx = get_index_from_uri (uri);
|
||||
if (idx >= MAX_CRON_ENTRIES) {
|
||||
return -1;
|
||||
}
|
||||
res = parse_crontab_line (s, get_cron_entry (idx), &err);
|
||||
if (res < 0) {
|
||||
printf ("Error parsing: %s\n", err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
crontab_to_string
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
/* FIXME: For now we only return "valid" or "invalid" until someone
|
||||
* comes up with a clever algorithm to reconstruct a crontab string
|
||||
* from the cron_entry struct.
|
||||
*/
|
||||
size_t idx = get_index_from_uri (uri);
|
||||
struct cron_entry *e;
|
||||
if (idx >= MAX_CRON_ENTRIES) {
|
||||
return MAX_GET_STRING_LENGTH;
|
||||
}
|
||||
e = get_cron_entry (idx);
|
||||
if (e->flags & VALID) {
|
||||
return snprintf (buf, bsize, "valid");
|
||||
}
|
||||
return snprintf (buf, bsize, "invalid");
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( crontab
|
||||
, crontab-entry
|
||||
, s
|
||||
, 1
|
||||
, crontab_from_string
|
||||
, crontab_to_string
|
||||
);
|
||||
|
||||
/* Allocate all cron entries and the necessary resources */
|
||||
void activate_cron_resources (void)
|
||||
{
|
||||
size_t n;
|
||||
for (n=0; n<MAX_CRON_ENTRIES; n++) {
|
||||
resource_t *res;
|
||||
char *buf;
|
||||
size_t len;
|
||||
struct cron_entry *e;
|
||||
char name [15];
|
||||
/* Need to copy the resource because resource->url holds the path
|
||||
* under which we activate it using rest_activate_resource
|
||||
*/
|
||||
if (NULL == (res = malloc (sizeof (*res)))) {
|
||||
printf ("Error malloc\n");
|
||||
break;
|
||||
}
|
||||
memcpy (res, &res_crontab, sizeof (*res));
|
||||
e = allocate_cron_entry ();
|
||||
assert (!(e->flags & VALID));
|
||||
len = snprintf (name, sizeof (name), "crontab/%u", n);
|
||||
name [sizeof (name) -1] = '\0';
|
||||
assert (len < 15);
|
||||
if (NULL == (buf = malloc (len + 1))) {
|
||||
printf ("Error malloc\n");
|
||||
break;
|
||||
}
|
||||
strcpy (buf, name);
|
||||
rest_activate_resource (res, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
63
apps/time/resource_gmtime.c
Normal file
63
apps/time/resource_gmtime.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* \file
|
||||
* Resource for gmtime (utc) / localtime handling
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
* \brief get time as a string in utc or localtime
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "xtime.h"
|
||||
#include "time_resource.h"
|
||||
#include "jsonparse.h"
|
||||
#include "er-coap.h"
|
||||
#include "generic_resource.h"
|
||||
|
||||
size_t time_to_string
|
||||
(const char *name, const char *uri, const char *query, char *buf, size_t bs)
|
||||
{
|
||||
struct xtimeval tv;
|
||||
struct xtm tm;
|
||||
struct xtm *(*method)(const xtime_t *, struct xtm *) = xgmtime_r;
|
||||
if (0 == strcmp (name, "localtime")) {
|
||||
method = xlocaltime_r;
|
||||
}
|
||||
xgettimeofday (&tv, NULL);
|
||||
method (&tv.tv_sec, &tm);
|
||||
return snprintf
|
||||
( buf
|
||||
, bs
|
||||
, "%lu-%02u-%02u %02u:%02u:%02u %s"
|
||||
, 1900 + tm.tm_year
|
||||
, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec
|
||||
, tm.tm_zone
|
||||
);
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE \
|
||||
( localtime
|
||||
, Local time
|
||||
, formatted time
|
||||
, 1
|
||||
, NULL
|
||||
, time_to_string
|
||||
);
|
||||
|
||||
GENERIC_RESOURCE \
|
||||
( utc
|
||||
, UTC
|
||||
, formatted time
|
||||
, 1
|
||||
, NULL
|
||||
, time_to_string
|
||||
);
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
63
apps/time/resource_timestamp.c
Normal file
63
apps/time/resource_timestamp.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* \file
|
||||
* Resource for timestamp handling
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
* \brief get/put time in seconds since 1970 (UNIX time)
|
||||
* Note: the internal format of the time in seconds is a 64bit number
|
||||
* unfortunately javascript (json) will only support double for which
|
||||
* the mantissa isn't long enough for representing that number. So we're
|
||||
* back to 32 bit and have a year 2038 problem.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "xtime.h"
|
||||
#include "time_resource.h"
|
||||
#include "jsonparse.h"
|
||||
#include "er-coap.h"
|
||||
#include "generic_resource.h"
|
||||
|
||||
int timestamp_from_string
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
struct xtimeval tv;
|
||||
// FIXME: Platform has no strtoll (long long)?
|
||||
tv.tv_sec = strtol (s, NULL, 10);
|
||||
xsettimeofday (&tv, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
timestamp_to_string
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
struct xtimeval tv;
|
||||
xgettimeofday (&tv, NULL);
|
||||
// FIXME: Platform doesn't seem to support long long printing
|
||||
// We get empty string
|
||||
return snprintf (buf, bsize, "%ld", (long)tv.tv_sec);
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( timestamp
|
||||
, Time
|
||||
, s
|
||||
, 1
|
||||
, timestamp_from_string
|
||||
, timestamp_to_string
|
||||
);
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
55
apps/time/resource_timezone.c
Normal file
55
apps/time/resource_timezone.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* \file
|
||||
* Resource for timezone handling
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
* \brief get/put timezone string
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "xtime.h"
|
||||
#include "time_resource.h"
|
||||
#include "jsonparse.h"
|
||||
#include "er-coap.h"
|
||||
#include "generic_resource.h"
|
||||
|
||||
int timezone_from_string
|
||||
(const char *name, const char *uri, const char *query, const char *s)
|
||||
{
|
||||
set_tz (s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
timezone_to_string
|
||||
( const char *name
|
||||
, const char *uri
|
||||
, const char *query
|
||||
, char *buf
|
||||
, size_t bsize
|
||||
)
|
||||
{
|
||||
if (get_tz (buf, bsize) == NULL) {
|
||||
*buf = '\0';
|
||||
}
|
||||
return strlen (buf);
|
||||
}
|
||||
|
||||
GENERIC_RESOURCE
|
||||
( timezone
|
||||
, TZ
|
||||
, s
|
||||
, 1
|
||||
, timezone_from_string
|
||||
, timezone_to_string
|
||||
);
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
847
apps/time/time.c
Normal file
847
apps/time/time.c
Normal file
|
@ -0,0 +1,847 @@
|
|||
/**
|
||||
* \addgroup Time related functions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#include "contiki.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "contiki-lib.h"
|
||||
#include "xtime.h"
|
||||
#include "tzparse.h"
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define DAYSPERWEEK 7
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
static const int mon_lengths[2][MONSPERYEAR] =
|
||||
{ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Static timezone information
|
||||
*/
|
||||
static struct tzoffset_info localtime_tzoffset;
|
||||
|
||||
/* Used for gmtime and localtime, according to manpage on linux the
|
||||
* internal value may be overwritten "by subsequent calls to any of the
|
||||
* date and time functions".
|
||||
*/
|
||||
static struct xtm tm;
|
||||
|
||||
/*
|
||||
* Internal variables to manage offset of utc from the contiki clock
|
||||
* and timezone offset from utc in minutes.
|
||||
* For now we don't manage the sub-second offset -- time of setting the
|
||||
* clock and the precisiont of the clock in use don't warrant this
|
||||
* effort.
|
||||
* The last_seconds is used to check if we had a seconds overflow,
|
||||
* although this happens only every 136 years :-)
|
||||
*/
|
||||
static xtime_t clock_offset;
|
||||
static uint32_t last_seconds;
|
||||
|
||||
static xtime_t
|
||||
transtime (xtime_t janfirst, int year, const struct tzrule *rp, long offset);
|
||||
|
||||
# define LEAP_YEAR(_year) \
|
||||
((_year % 4) == 0 && (_year % 100 != 0 || _year % 400 == 0))
|
||||
# define YDAYS(_year) (LEAP_YEAR(year) ? 366 : 365)
|
||||
|
||||
struct xtm *xgmtime_r (const xtime_t *timep, struct xtm *ptm)
|
||||
{
|
||||
unsigned int year;
|
||||
int days, month, month_len;
|
||||
xtime_t t = *timep;
|
||||
ptm->tm_sec = t % 60;
|
||||
t /= 60;
|
||||
ptm->tm_min = t % 60;
|
||||
t /= 60;
|
||||
ptm->tm_hour = t % 24;
|
||||
t /= 24;
|
||||
ptm->tm_wday = (t+4) % 7;
|
||||
year = 1970;
|
||||
days = 0;
|
||||
while ((days += YDAYS (year)) <= t)
|
||||
{
|
||||
year++;
|
||||
}
|
||||
ptm->tm_year = year - 1900;
|
||||
days -= YDAYS (year);
|
||||
t -= days;
|
||||
ptm->tm_yday = t;
|
||||
for (month=0; month<12; month++)
|
||||
{
|
||||
if (month == 1)
|
||||
{
|
||||
month_len = LEAP_YEAR (year) ? 29 : 28;
|
||||
}
|
||||
else
|
||||
{
|
||||
int m = month;
|
||||
if (m >= 7)
|
||||
{
|
||||
m -= 1;
|
||||
}
|
||||
m &= 1;
|
||||
month_len = m ? 30 : 31;
|
||||
}
|
||||
if (t >= month_len)
|
||||
{
|
||||
t -= month_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptm->tm_mon = month;
|
||||
ptm->tm_mday = t + 1;
|
||||
ptm->tm_isdst = 0;
|
||||
ptm->tm_gmtoff = 0;
|
||||
ptm->tm_zone = "UTC";
|
||||
return ptm;
|
||||
}
|
||||
|
||||
struct xtm *xgmtime (const xtime_t *timep)
|
||||
{
|
||||
return xgmtime_r (timep, &tm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute is_dst flag of given timestamp
|
||||
*/
|
||||
static int is_dst (const xtime_t *timep, const struct tzoffset_info *tzo)
|
||||
{
|
||||
xtime_t janfirst = 0;
|
||||
xtime_t starttime, endtime;
|
||||
int year = 1970;
|
||||
int lastdst = 0;
|
||||
if (tzo->dstname == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (year = 1970; janfirst < *timep; year++) {
|
||||
starttime = transtime (janfirst, year, &tzo->start, tzo->stdoffset);
|
||||
endtime = transtime (janfirst, year, &tzo->end, tzo->dstoffset);
|
||||
if (starttime <= *timep && endtime <= *timep) {
|
||||
lastdst = (starttime > endtime);
|
||||
} else if (starttime > *timep && endtime <= *timep) {
|
||||
return 0;
|
||||
} else if (starttime <= *timep && endtime > *timep) {
|
||||
return 1;
|
||||
} else if (starttime > *timep && endtime > *timep) {
|
||||
return lastdst;
|
||||
}
|
||||
janfirst += YDAYS (year) * SECSPERDAY;
|
||||
}
|
||||
return lastdst;
|
||||
}
|
||||
|
||||
struct xtm *xlocaltime_r (const xtime_t *timep, struct xtm *ptm)
|
||||
{
|
||||
const struct tzoffset_info *tzo = &localtime_tzoffset;
|
||||
int isdst = 0;
|
||||
long offset = 0;
|
||||
xtime_t t = *timep;
|
||||
|
||||
if (tzo->stdname == NULL) {
|
||||
set_tz (DEFAULT_TIMEZONE);
|
||||
}
|
||||
isdst = is_dst (timep, tzo);
|
||||
offset = isdst ? tzo->dstoffset : tzo->stdoffset;
|
||||
t -= offset;
|
||||
xgmtime_r (&t, ptm);
|
||||
ptm->tm_isdst = isdst;
|
||||
ptm->tm_gmtoff = -offset;
|
||||
ptm->tm_zone = isdst ? tzo->dstname : tzo->stdname;
|
||||
return ptm;
|
||||
}
|
||||
|
||||
struct xtm *xlocaltime (const xtime_t *timep)
|
||||
{
|
||||
return xlocaltime_r (timep, &tm);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get time in seconds and microseconds
|
||||
* xgettimeofday will return the clock time as the microseconds part
|
||||
* while xsettimeofday will *ignore* the microseconds part (for now).
|
||||
* Note that the contiki clock interface is broken anyway, we can't read
|
||||
* seconds and sub-seconds atomically. We try to work around this by
|
||||
* repeatedly reading seconds, sub-seconds, seconds until first and
|
||||
* second read of seconds match.
|
||||
*/
|
||||
int xgettimeofday (struct xtimeval *tv, struct timezone *tz)
|
||||
{
|
||||
uint32_t cs;
|
||||
if (tv) {
|
||||
int i;
|
||||
/* Limit tries to get the same second twice to two */
|
||||
for (i=0; i<2; i++) {
|
||||
cs = clock_seconds ();
|
||||
if (cs < last_seconds) {
|
||||
clock_offset += 0xFFFFFFFFL;
|
||||
clock_offset ++;
|
||||
}
|
||||
last_seconds = cs;
|
||||
tv->tv_sec = cs + clock_offset;
|
||||
tv->tv_usec = ((xtime_t)(clock_time () % CLOCK_SECOND))
|
||||
* 1000000L / CLOCK_SECOND;
|
||||
if (cs == clock_seconds ()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tz) {
|
||||
const struct tzoffset_info *tzo = &localtime_tzoffset;
|
||||
tz->tz_dsttime = is_dst (&tv->tv_sec, tzo);
|
||||
if (tz->tz_dsttime) {
|
||||
tz->tz_minuteswest = -tzo->dstoffset / 60;
|
||||
} else {
|
||||
tz->tz_minuteswest = -tzo->stdoffset / 60;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set time in seconds, microseconds ignored for now
|
||||
*/
|
||||
int xsettimeofday (const struct xtimeval *tv, const struct timezone *tz)
|
||||
{
|
||||
/* Don't allow setting timezone */
|
||||
if (tz) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (tv) {
|
||||
uint32_t cs;
|
||||
cs = clock_seconds ();
|
||||
clock_offset = tv->tv_sec - cs;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save timezone names into reserved string buffer and fill in the names
|
||||
* into the given tzoffset_info.
|
||||
* Return -1 on error, 0 for success.
|
||||
*/
|
||||
static int save_tznames
|
||||
( const char *stdname, const char *dstname
|
||||
, size_t stdlen, size_t dstlen
|
||||
, struct tzoffset_info *tzo
|
||||
)
|
||||
{
|
||||
size_t len = stdlen;
|
||||
if (stdname == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (dstname != NULL) {
|
||||
len += dstlen;
|
||||
}
|
||||
if (len + 2 > sizeof (tzo->namebuf)) {
|
||||
return -1;
|
||||
}
|
||||
tzo->stdname = tzo->namebuf;
|
||||
strncpy (tzo->namebuf, stdname, stdlen);
|
||||
tzo->namebuf [stdlen] = '\0';
|
||||
if (dstlen) {
|
||||
strncpy (tzo->namebuf + stdlen + 1, dstname, dstlen);
|
||||
tzo->namebuf [stdlen + 1 + dstlen] = '\0';
|
||||
tzo->dstname = tzo->namebuf + stdlen + 1;
|
||||
} else {
|
||||
tzo->dstname = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility functions for timezone string parsing (POSIX section 8)
|
||||
* Code adapted from OpenBSD localtime.c 1.57 2015/12/12 21:25:44
|
||||
* which is in the public domain.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The DST rules to use if TZ has no rules:
|
||||
* We default to US rules as of 1999-08-17.
|
||||
* POSIX 1003.1 section 8.1.1 says that the default DST rules are
|
||||
* implementation dependent; for historical reasons, US rules are a
|
||||
* common default.
|
||||
*/
|
||||
#ifndef TZDEFRULESTRING
|
||||
#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
|
||||
* year, a rule, and the offset from UTC at the time that rule takes effect,
|
||||
* calculate the Epoch-relative time that rule takes effect.
|
||||
*/
|
||||
|
||||
static xtime_t
|
||||
transtime(xtime_t janfirst, int year, const struct tzrule *rulep, long offset)
|
||||
{
|
||||
int leapyear;
|
||||
xtime_t value;
|
||||
int i;
|
||||
int d, m1, yy0, yy1, yy2, dow;
|
||||
|
||||
value = 0;
|
||||
leapyear = LEAP_YEAR (year);
|
||||
switch (rulep->r_type) {
|
||||
|
||||
case JULIAN_DAY:
|
||||
/*
|
||||
* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
|
||||
* years.
|
||||
* In non-leap years, or if the day number is 59 or less, just
|
||||
* add SECSPERDAY times the day number-1 to the time of
|
||||
* January 1, midnight, to get the day.
|
||||
*/
|
||||
value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
|
||||
if (leapyear && rulep->r_day >= 60) {
|
||||
value += SECSPERDAY;
|
||||
}
|
||||
break;
|
||||
|
||||
case DAY_OF_YEAR:
|
||||
/*
|
||||
* n - day of year.
|
||||
* Just add SECSPERDAY times the day number to the time of
|
||||
* January 1, midnight, to get the day.
|
||||
*/
|
||||
value = janfirst + rulep->r_day * SECSPERDAY;
|
||||
break;
|
||||
|
||||
case MONTH_NTH_DAY_OF_WEEK:
|
||||
/*
|
||||
* Mm.n.d - nth "dth day" of month m.
|
||||
*/
|
||||
value = janfirst;
|
||||
for (i = 0; i < rulep->r_mon - 1; ++i) {
|
||||
value += mon_lengths [leapyear][i] * SECSPERDAY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Use Zeller's Congruence to get day-of-week of first day of
|
||||
** month.
|
||||
*/
|
||||
m1 = (rulep->r_mon + 9) % 12 + 1;
|
||||
yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
|
||||
yy1 = yy0 / 100;
|
||||
yy2 = yy0 % 100;
|
||||
dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
|
||||
if (dow < 0) {
|
||||
dow += DAYSPERWEEK;
|
||||
}
|
||||
|
||||
/*
|
||||
** "dow" is the day-of-week of the first day of the month. Get
|
||||
** the day-of-month (zero-origin) of the first "dow" day of the
|
||||
** month.
|
||||
*/
|
||||
d = rulep->r_day - dow;
|
||||
if (d < 0) {
|
||||
d += DAYSPERWEEK;
|
||||
}
|
||||
for (i = 1; i < rulep->r_week; ++i) {
|
||||
if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1]) {
|
||||
break;
|
||||
}
|
||||
d += DAYSPERWEEK;
|
||||
}
|
||||
|
||||
/*
|
||||
** "d" is the day-of-month (zero-origin) of the day we want.
|
||||
*/
|
||||
value += d * SECSPERDAY;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
|
||||
** question. To get the Epoch-relative time of the specified local
|
||||
** time on that day, add the transition time and the current offset
|
||||
** from UTC.
|
||||
*/
|
||||
return value + rulep->r_time + offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer into a time zone string, scan until a character that is not
|
||||
* a valid character in a zone name is found. Return a pointer to that
|
||||
* character.
|
||||
*/
|
||||
|
||||
static const char *getzname (const char *s)
|
||||
{
|
||||
char c;
|
||||
while ((c = *s) != '\0' && !isdigit(c) && c != ',' && c != '-' && c != '+'){
|
||||
++s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer into an extended time zone string, scan until the ending
|
||||
* delimiter of the zone name is located. Return a pointer to the delimiter.
|
||||
*
|
||||
* As with getzname above, the legal character set is actually quite
|
||||
* restricted, with other characters producing undefined results.
|
||||
* We don't do any checking here; checking is done later in common-case code.
|
||||
*/
|
||||
|
||||
static const char *getqzname (const char *strp, const int delim)
|
||||
{
|
||||
int c;
|
||||
while ((c = *strp) != '\0' && c != delim) {
|
||||
++strp;
|
||||
}
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer into a time zone string, extract a number from that string.
|
||||
* Check that the number is within a specified range; if it is not, return
|
||||
* NULL.
|
||||
* Otherwise, return a pointer to the first character not part of the number.
|
||||
*/
|
||||
|
||||
static const char *getnum (const char *strp, int *nump, int min, int max)
|
||||
{
|
||||
char c;
|
||||
int num;
|
||||
|
||||
if (strp == NULL || !isdigit ((c = *strp))) {
|
||||
return NULL;
|
||||
}
|
||||
num = 0;
|
||||
do {
|
||||
num = num * 10 + (c - '0');
|
||||
if (num > max) {
|
||||
return NULL; /* illegal value */
|
||||
}
|
||||
c = *++strp;
|
||||
} while (isdigit (c));
|
||||
if (num < min) {
|
||||
return NULL; /* illegal value */
|
||||
}
|
||||
*nump = num;
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer into a time zone string, extract a number of seconds,
|
||||
* in hh[:mm[:ss]] form, from the string.
|
||||
* If any error occurs, return NULL.
|
||||
* Otherwise, return a pointer to the first character not part of the number
|
||||
* of seconds.
|
||||
*/
|
||||
|
||||
static const char *getsecs (const char *strp, long *secsp)
|
||||
{
|
||||
int num;
|
||||
|
||||
/*
|
||||
* `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
|
||||
* "M10.4.6/26", which does not conform to Posix,
|
||||
* but which specifies the equivalent of
|
||||
* ``02:00 on the first Sunday on or after 23 Oct''.
|
||||
*/
|
||||
strp = getnum (strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*secsp = num * (long) SECSPERHOUR;
|
||||
if (*strp == ':') {
|
||||
++strp;
|
||||
strp = getnum (strp, &num, 0, MINSPERHOUR - 1);
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*secsp += num * SECSPERMIN;
|
||||
if (*strp == ':') {
|
||||
++strp;
|
||||
/* `SECSPERMIN' allows for leap seconds. */
|
||||
strp = getnum (strp, &num, 0, SECSPERMIN);
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*secsp += num;
|
||||
}
|
||||
}
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer into a time zone string, extract an offset, in
|
||||
* [+-]hh[:mm[:ss]] form, from the string.
|
||||
* If any error occurs, return NULL.
|
||||
* Otherwise, return a pointer to the first character not part of the time.
|
||||
*/
|
||||
|
||||
static const char *getoffset (const char *strp, long *offsetp)
|
||||
{
|
||||
int neg = 0;
|
||||
|
||||
if (*strp == '-') {
|
||||
neg = 1;
|
||||
++strp;
|
||||
} else if (*strp == '+') {
|
||||
++strp;
|
||||
}
|
||||
strp = getsecs (strp, offsetp);
|
||||
if (strp == NULL) {
|
||||
return NULL; /* illegal time */
|
||||
}
|
||||
if (neg) {
|
||||
*offsetp = -*offsetp;
|
||||
}
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse (optionally extended) timezone name. Return pointer to
|
||||
* (undelimited) timezone name in tzn and length of same in len.
|
||||
* Return pointer to first character *after* name, NULL on error.
|
||||
* Factored from original tzparse function.
|
||||
*/
|
||||
static const char *
|
||||
egettzname (const char *strp, size_t *len, const char **tzn)
|
||||
{
|
||||
*tzn = strp;
|
||||
if (*strp == '<') {
|
||||
strp++;
|
||||
*tzn = strp;
|
||||
strp = getqzname (strp, '>');
|
||||
if (*strp != '>') {
|
||||
return NULL;
|
||||
}
|
||||
*len = strp - *tzn;
|
||||
strp++;
|
||||
} else {
|
||||
strp = getzname (strp);
|
||||
*len = strp - *tzn;
|
||||
}
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given a pointer into a time zone string, extract a rule in the form
|
||||
** date[/time]. See POSIX section 8 for the format of "date" and "time".
|
||||
** If a valid rule is not found, return NULL.
|
||||
** Otherwise, return a pointer to the first character not part of the rule.
|
||||
*/
|
||||
|
||||
static const char *getrule (const char *strp, struct tzrule *rulep)
|
||||
{
|
||||
if (*strp == 'J') {
|
||||
/*
|
||||
* Julian day.
|
||||
*/
|
||||
rulep->r_type = JULIAN_DAY;
|
||||
++strp;
|
||||
strp = getnum (strp, &rulep->r_day, 1, DAYSPERNYEAR);
|
||||
} else if (*strp == 'M') {
|
||||
/*
|
||||
* Month, week, day.
|
||||
*/
|
||||
rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
|
||||
++strp;
|
||||
strp = getnum (strp, &rulep->r_mon, 1, MONSPERYEAR);
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (*strp++ != '.') {
|
||||
return NULL;
|
||||
}
|
||||
strp = getnum (strp, &rulep->r_week, 1, 5);
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (*strp++ != '.') {
|
||||
return NULL;
|
||||
}
|
||||
strp = getnum (strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
|
||||
} else if (isdigit (*strp)) {
|
||||
/*
|
||||
* Day of year.
|
||||
*/
|
||||
rulep->r_type = DAY_OF_YEAR;
|
||||
strp = getnum (strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
|
||||
} else {
|
||||
return NULL; /* invalid format */
|
||||
}
|
||||
if (strp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (*strp == '/') {
|
||||
/*
|
||||
* Time specified.
|
||||
*/
|
||||
++strp;
|
||||
strp = getsecs (strp, &rulep->r_time);
|
||||
} else {
|
||||
rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
|
||||
}
|
||||
return strp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse POSIX section 8 TZ string.
|
||||
* We keep the misnomer "name" for the timezone string.
|
||||
*/
|
||||
int tzparse (const char *name, struct tzoffset_info *tzo)
|
||||
{
|
||||
const char *stdname;
|
||||
const char *dstname;
|
||||
size_t stdlen;
|
||||
size_t dstlen;
|
||||
long stdoffset;
|
||||
long dstoffset;
|
||||
|
||||
dstname = NULL;
|
||||
stdname = name;
|
||||
name = egettzname (name, &stdlen, &stdname);
|
||||
if (name == NULL || *name == '\0') {
|
||||
return -1;
|
||||
}
|
||||
name = getoffset (name, &stdoffset);
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (*name != '\0') {
|
||||
name = egettzname (name, &dstlen, &dstname);
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (*name != '\0' && *name != ',' && *name != ';') {
|
||||
name = getoffset (name, &dstoffset);
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
dstoffset = stdoffset - SECSPERHOUR;
|
||||
}
|
||||
if (*name == '\0') {
|
||||
name = TZDEFRULESTRING;
|
||||
}
|
||||
if (*name == ',' || *name == ';') {
|
||||
struct tzrule start;
|
||||
struct tzrule end;
|
||||
++name;
|
||||
if ((name = getrule (name, &start)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (*name++ != ',') {
|
||||
return -1;
|
||||
}
|
||||
if ((name = getrule (name, &end)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (*name != '\0') {
|
||||
return -1;
|
||||
}
|
||||
if (save_tznames (stdname, dstname, stdlen, dstlen, tzo) != 0) {
|
||||
return -1;
|
||||
}
|
||||
tzo->start = start;
|
||||
tzo->end = end;
|
||||
tzo->stdoffset = stdoffset;
|
||||
tzo->dstoffset = dstoffset;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* only standard time, no DST */
|
||||
if (save_tznames (stdname, NULL, stdlen, 0, tzo) != 0) {
|
||||
return -1;
|
||||
}
|
||||
tzo->stdoffset = stdoffset;
|
||||
tzo->dstoffset = stdoffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide a single static timezone which is used by localtime et.al.
|
||||
*/
|
||||
int set_tz (const char *tzstring)
|
||||
{
|
||||
return tzparse (tzstring, &localtime_tzoffset);
|
||||
}
|
||||
|
||||
static size_t lensecs (long seconds)
|
||||
{
|
||||
size_t len = 1;
|
||||
long secs = abs (seconds);
|
||||
if (seconds < 0) {
|
||||
len++;
|
||||
}
|
||||
if (secs / 3600 > 9) {
|
||||
len++;
|
||||
}
|
||||
if (secs % 3600) {
|
||||
len += 3;
|
||||
if (secs % 60) {
|
||||
len += 3;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get length of string resulting from serializing rule.
|
||||
*/
|
||||
static size_t lenrule (const struct tzrule *rule)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (rule->r_type == JULIAN_DAY) {
|
||||
len++;
|
||||
}
|
||||
if (rule->r_type == JULIAN_DAY || rule->r_type == DAY_OF_YEAR) {
|
||||
len++;
|
||||
if (rule->r_day > 9) {
|
||||
len++;
|
||||
if (rule->r_day > 99) {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
} else if (rule->r_type == MONTH_NTH_DAY_OF_WEEK) {
|
||||
len++;
|
||||
len++;
|
||||
if (rule->r_mon > 9) {
|
||||
len++;
|
||||
}
|
||||
len += 4; /* dots and week/day */
|
||||
if (rule->r_time != 7200) {
|
||||
len++;
|
||||
len += lensecs (rule->r_time);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int is_extended_name (const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0; name [i]; i++) {
|
||||
if (isdigit (name [i]) || name [i] == '+' || name [i] == '-') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get length of timezone string resulting from serializing tzo.
|
||||
*/
|
||||
static size_t len_tz_r (const struct tzoffset_info *tzo)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (tzo->stdname == NULL) {
|
||||
return 0;
|
||||
}
|
||||
len = strlen (tzo->stdname);
|
||||
if (is_extended_name (tzo->stdname)) {
|
||||
len += 2;
|
||||
}
|
||||
len += lensecs (tzo->stdoffset);
|
||||
if (tzo->dstname) {
|
||||
len += strlen (tzo->dstname);
|
||||
if (is_extended_name (tzo->dstname)) {
|
||||
len += 2;
|
||||
}
|
||||
if (tzo->dstoffset - tzo->stdoffset != -3600) {
|
||||
len += lensecs (tzo->dstoffset);
|
||||
}
|
||||
len += 2; /* commas */
|
||||
len += lenrule (&tzo->start);
|
||||
len += lenrule (&tzo->end);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t len_tz (void)
|
||||
{
|
||||
return len_tz_r (&localtime_tzoffset);
|
||||
}
|
||||
|
||||
void appendsecs (char *buf, long minutes)
|
||||
{
|
||||
char *p = buf + strlen (buf);
|
||||
long min = abs (minutes);
|
||||
if (minutes < 0) {
|
||||
*p++ = '-';
|
||||
}
|
||||
if (min % 3600 == 0) {
|
||||
sprintf (p, "%ld", min / 3600);
|
||||
} else if (min % 60 == 0) {
|
||||
sprintf (p, "%ld:%ld", min / 3600, (min / 60) % 60);
|
||||
} else {
|
||||
sprintf (p, "%ld:%ld:%ld", min / 3600, (min / 60) % 60, min % 60);
|
||||
}
|
||||
}
|
||||
|
||||
void appendrule (char *buf, const struct tzrule *rule)
|
||||
{
|
||||
char *p = buf + strlen (buf);
|
||||
if (rule->r_type == JULIAN_DAY) {
|
||||
sprintf (p, "J%d", rule->r_day);
|
||||
} else if (rule->r_type == DAY_OF_YEAR) {
|
||||
sprintf (p, "%d", rule->r_day);
|
||||
} else if (rule->r_type == MONTH_NTH_DAY_OF_WEEK) {
|
||||
sprintf (p, "M%d.%d.%d", rule->r_mon, rule->r_week, rule->r_day);
|
||||
p = buf + strlen (buf);
|
||||
if (rule->r_time != 7200) {
|
||||
*p++ = '/';
|
||||
*p = '\0';
|
||||
appendsecs (p, rule->r_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_tz (char *buf, size_t buflen)
|
||||
{
|
||||
const struct tzoffset_info *tzo = &localtime_tzoffset;
|
||||
|
||||
if (tzo->stdname == NULL || len_tz_r (tzo) > buflen) {
|
||||
return NULL;
|
||||
}
|
||||
if (is_extended_name (tzo->stdname)) {
|
||||
sprintf (buf, "<%s>", tzo->stdname);
|
||||
} else {
|
||||
strcpy (buf, tzo->stdname);
|
||||
}
|
||||
appendsecs (buf, tzo->stdoffset);
|
||||
if (tzo->dstname != NULL) {
|
||||
if (is_extended_name (tzo->dstname)) {
|
||||
sprintf (buf + strlen (buf), "<%s>", tzo->dstname);
|
||||
} else {
|
||||
strcat (buf, tzo->dstname);
|
||||
}
|
||||
if (tzo->dstoffset - tzo->stdoffset != -3600) {
|
||||
appendsecs (buf, tzo->dstoffset);
|
||||
}
|
||||
strcat (buf, ",");
|
||||
appendrule (buf, &tzo->start);
|
||||
strcat (buf, ",");
|
||||
appendrule (buf, &tzo->end);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
32
apps/time/time_resource.h
Normal file
32
apps/time/time_resource.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* \addgroup Time related functions
|
||||
*
|
||||
* Resource definitions for time module
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Resource definitions for the time module
|
||||
*
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@tux.runtux.com>
|
||||
*/
|
||||
|
||||
#ifndef time_resource_h
|
||||
#define time_resource_h
|
||||
#include <assert.h>
|
||||
#include "contiki.h"
|
||||
#include "rest-engine.h"
|
||||
|
||||
extern resource_t res_timestamp;
|
||||
extern resource_t res_timezone;
|
||||
extern resource_t res_crontab;
|
||||
extern resource_t res_localtime;
|
||||
extern resource_t res_utc;
|
||||
|
||||
extern void activate_cron_resources (void);
|
||||
|
||||
#endif // time_resource_h
|
||||
/** @} */
|
56
apps/time/tzparse.h
Normal file
56
apps/time/tzparse.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Timezone parsing
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Definitions for timezone parsing
|
||||
*
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@tux.runtux.com>
|
||||
*/
|
||||
|
||||
#ifndef tzparse_h
|
||||
#define tzparse_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rule for DST switching
|
||||
*/
|
||||
struct tzrule {
|
||||
int r_type; /* type of rule--see below */
|
||||
int r_day; /* day number of rule */
|
||||
int r_week; /* week number of rule */
|
||||
int r_mon; /* month number of rule */
|
||||
long r_time; /* transition time of rule */
|
||||
};
|
||||
|
||||
#define JULIAN_DAY 0 /* Jn - Julian day */
|
||||
#define DAY_OF_YEAR 1 /* n - day of year */
|
||||
#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
|
||||
|
||||
/*
|
||||
* Info about timezone offset handling.
|
||||
* We get at least a dstname and stdoffset, if no daylight saving is in
|
||||
* effect, dstname is NULL and no rule is filled in.
|
||||
*/
|
||||
struct tzoffset_info {
|
||||
const char *stdname;
|
||||
const char *dstname;
|
||||
long stdoffset;
|
||||
long dstoffset;
|
||||
struct tzrule start;
|
||||
struct tzrule end;
|
||||
char namebuf [TZ_MAX_CHARS];
|
||||
};
|
||||
|
||||
int tzparse (const char *name, struct tzoffset_info *tzo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // tzparse_h
|
94
apps/time/xtime.h
Normal file
94
apps/time/xtime.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* \defgroup Time related functions
|
||||
*
|
||||
* This rolls the necessary definition for getting/setting time and
|
||||
* managing local time into one include file, on posix systems this
|
||||
* lives in at least two include files, time.h and sys/time.h
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Definitions for the time module
|
||||
*
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@tux.runtux.com>
|
||||
*/
|
||||
|
||||
#ifndef xtime_h
|
||||
#define xtime_h
|
||||
|
||||
/* This is a time.h implementation but to avoid name-clashes with libs
|
||||
* trying to be helpfull we add the prefix x
|
||||
*/
|
||||
|
||||
#ifdef LOCAL_COMPILE
|
||||
#define clock_seconds() 1
|
||||
#define clock_time() 1
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEZONE "CET-1CEST,M3.5.0,M10.5.0/3"
|
||||
|
||||
typedef signed long long xtime_t;
|
||||
typedef signed long suseconds_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* tm_gmtoff and tm_zone are BSD additions */
|
||||
struct xtm {
|
||||
uint32_t tm_year; /* year */
|
||||
uint16_t tm_yday; /* day in the year */
|
||||
uint8_t tm_sec; /* seconds */
|
||||
uint8_t tm_min; /* minutes */
|
||||
uint8_t tm_hour; /* hours */
|
||||
uint8_t tm_mday; /* day of the month */
|
||||
uint8_t tm_mon; /* month */
|
||||
uint8_t tm_wday; /* day of the week */
|
||||
uint8_t tm_isdst; /* daylight saving time */
|
||||
int32_t tm_gmtoff; /* Seconds east of UTC */
|
||||
const char *tm_zone; /* Timezone abbreviation */
|
||||
};
|
||||
|
||||
struct xtimeval {
|
||||
xtime_t tv_sec; /* seconds */
|
||||
suseconds_t tv_usec; /* microseconds */
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int16_t tz_minuteswest; /* minutes west of Greenwich */
|
||||
int tz_dsttime; /* type of DST correction, unused */
|
||||
};
|
||||
|
||||
struct xtm *xgmtime (const xtime_t *timep);
|
||||
struct xtm *xgmtime_r (const xtime_t *timep, struct xtm *result);
|
||||
struct xtm *xlocaltime (const xtime_t *timep);
|
||||
struct xtm *xlocaltime_r (const xtime_t *timep, struct xtm *result);
|
||||
|
||||
int xgettimeofday (struct xtimeval *tv, struct timezone *tz);
|
||||
int xsettimeofday (const struct xtimeval *tv, const struct timezone *tz);
|
||||
|
||||
/*
|
||||
* Maximum length of all timezone names, this is much longer in UNIX
|
||||
* implementations but we have limited space here. Note that the length
|
||||
* includes a trailing \0 byte for each timezone name.
|
||||
*/
|
||||
#ifndef TZ_MAX_CHARS
|
||||
#define TZ_MAX_CHARS 16
|
||||
#endif
|
||||
|
||||
/* Maximum length of buffer to reserve for timezone string */
|
||||
#define MAXTZLEN (TZ_MAX_CHARS+9+2*(2+6+1+8)+1)
|
||||
|
||||
int set_tz (const char *tzstring);
|
||||
const char *get_tz (char *buffer, size_t buflen);
|
||||
size_t len_tz (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // xtime_h
|
||||
/** @} */
|
1
apps/tinydtls
Submodule
1
apps/tinydtls
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit e95b02584a0041817da67c8c01f2a197d0c26915
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#define IGNORE_CHAR(c) (c == 0x0d)
|
||||
#define END 0x0a
|
||||
//#define IGNORE_CHAR(c) (c == 0x0a)
|
||||
//#define END 0x0d
|
||||
|
||||
static struct ringbuf rxbuf;
|
||||
static uint8_t rxbuf_data[BUFSIZE];
|
||||
|
|
|
@ -130,7 +130,7 @@ typedef uint16_t settings_length_t;
|
|||
|
||||
#define SETTINGS_KEY_RDC_INDEX TCC('R','D') /*!< RDC index, uint8_t */
|
||||
#define SETTINGS_KEY_CHANNEL_MASK TCC('C','M') /*!< Channel mask, uint16_t */
|
||||
|
||||
#define SETTINGS_KEY_MAC_CONF TCC('M','C') /*!< MAC Layer Config, uint8_t */
|
||||
/*****************************************************************************/
|
||||
// MARK: - Constants
|
||||
|
||||
|
|
|
@ -365,6 +365,8 @@ powercycle_turn_radio_on(void)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
volatile uint8_t mcusleepcycle=16;
|
||||
|
||||
static void
|
||||
powercycle_wrapper(struct rtimer *t, void *ptr)
|
||||
{
|
||||
|
@ -479,8 +481,8 @@ powercycle(struct rtimer *t, void *ptr)
|
|||
break;
|
||||
}
|
||||
|
||||
schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
|
||||
PT_YIELD(&pt);
|
||||
// schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
|
||||
// PT_YIELD(&pt);
|
||||
}
|
||||
if(radio_is_on) {
|
||||
if(!(NETSTACK_RADIO.receiving_packet() ||
|
||||
|
@ -500,14 +502,15 @@ powercycle(struct rtimer *t, void *ptr)
|
|||
ensure an occasional wake cycle or foreground processing will
|
||||
be blocked until a packet is detected */
|
||||
#if RDC_CONF_MCU_SLEEP
|
||||
|
||||
static uint8_t sleepcycle;
|
||||
if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
|
||||
rtimer_arch_sleep(RTIMER_NOW() - cycle_start);
|
||||
if((sleepcycle++ < mcusleepcycle) && !we_are_sending && !radio_is_on && !(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet())) {
|
||||
rtimer_arch_sleep(cycle_start - RTIMER_NOW());
|
||||
} else {
|
||||
sleepcycle = 0;
|
||||
#ifndef RDC_CONF_PT_YIELD_OFF
|
||||
schedule_powercycle_fixed(t, cycle_start);
|
||||
PT_YIELD(&pt);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
schedule_powercycle_fixed(t, cycle_start);
|
||||
|
@ -548,11 +551,11 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
rtimer_clock_t t0;
|
||||
#if WITH_PHASE_OPTIMIZATION
|
||||
rtimer_clock_t encounter_time = 0;
|
||||
uint8_t is_known_receiver = 0;
|
||||
#endif
|
||||
int strobes;
|
||||
uint8_t got_strobe_ack = 0;
|
||||
uint8_t is_broadcast = 0;
|
||||
uint8_t is_known_receiver = 0;
|
||||
uint8_t collisions;
|
||||
int transmit_len;
|
||||
int ret;
|
||||
|
@ -712,11 +715,13 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
|
||||
watchdog_periodic();
|
||||
|
||||
#if WITH_PHASE_OPTIMIZATION
|
||||
if(!is_broadcast && (is_receiver_awake || is_known_receiver) &&
|
||||
!RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
|
||||
PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
|
||||
break;
|
||||
}
|
||||
#endif /* WITH_PHASE_OPTIMIZATION */
|
||||
|
||||
#if !RDC_CONF_HARDWARE_ACK
|
||||
len = 0;
|
||||
|
|
151
core/sys/log-conf.h
Normal file
151
core/sys/log-conf.h
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Inria.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Default log levels for a number of modules
|
||||
* \author
|
||||
* Simon Duquennoy <simon.duquennoy@inria.fr>
|
||||
*/
|
||||
|
||||
/** \addtogroup sys
|
||||
* @{ */
|
||||
|
||||
/** \addtogroup log
|
||||
* @{ */
|
||||
|
||||
#ifndef __LOG_CONF_H__
|
||||
#define __LOG_CONF_H__
|
||||
|
||||
/* Log only the last 16 bytes of link-layer and IPv6 addresses */
|
||||
#ifdef LOG_CONF_WITH_COMPACT_ADDR
|
||||
#define LOG_WITH_COMPACT_ADDR LOG_CONF_WITH_COMPACT_ADDR
|
||||
#else /* LOG_CONF_WITH_COMPACT_ADDR */
|
||||
#define LOG_WITH_COMPACT_ADDR 0
|
||||
#endif /* LOG_CONF_WITH_COMPACT_ADDR */
|
||||
|
||||
/* Prefix all logs with file name and line-of-code */
|
||||
#ifdef LOG_CONF_WITH_LOC
|
||||
#define LOG_WITH_LOC LOG_CONF_WITH_LOC
|
||||
#else /* LOG_CONF_WITH_LOC */
|
||||
#define LOG_WITH_LOC 0
|
||||
#endif /* LOG_CONF_WITH_LOC */
|
||||
|
||||
/* Prefix all logs with Module name and logging level */
|
||||
#ifdef LOG_CONF_WITH_MODULE_PREFIX
|
||||
#define LOG_WITH_MODULE_PREFIX LOG_CONF_WITH_MODULE_PREFIX
|
||||
#else /* LOG_CONF_WITH_MODULE_PREFIX */
|
||||
#define LOG_WITH_MODULE_PREFIX 1
|
||||
#endif /* LOG_CONF_WITH_MODULE_PREFIX */
|
||||
|
||||
/* Cooja annotations */
|
||||
#ifdef LOG_CONF_WITH_ANNOTATE
|
||||
#define LOG_WITH_ANNOTATE LOG_CONF_WITH_ANNOTATE
|
||||
#else /* LOG_CONF_WITH_ANNOTATE */
|
||||
#define LOG_WITH_ANNOTATE 0
|
||||
#endif /* LOG_CONF_WITH_ANNOTATE */
|
||||
|
||||
/* Custom output function -- default is printf */
|
||||
#ifdef LOG_CONF_OUTPUT
|
||||
#define LOG_OUTPUT(...) LOG_CONF_OUTPUT(__VA_ARGS__)
|
||||
#else /* LOG_CONF_OUTPUT */
|
||||
#define LOG_OUTPUT(...) printf(__VA_ARGS__)
|
||||
#endif /* LOG_CONF_OUTPUT */
|
||||
|
||||
/*
|
||||
* Custom output function to prefix logs with level and module.
|
||||
*
|
||||
* This will only be called when LOG_CONF_WITH_MODULE_PREFIX is enabled and
|
||||
* all implementations should be based on LOG_OUTPUT.
|
||||
*
|
||||
* \param level The log level
|
||||
* \param levelstr The log level as string
|
||||
* \param module The module string descriptor
|
||||
*/
|
||||
#ifdef LOG_CONF_OUTPUT_PREFIX
|
||||
#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_CONF_OUTPUT_PREFIX(level, levelstr, module)
|
||||
#else /* LOG_CONF_OUTPUT_PREFIX */
|
||||
#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_OUTPUT("[%-4s: %-10s] ", levelstr, module)
|
||||
#endif /* LOG_CONF_OUTPUT_PREFIX */
|
||||
|
||||
/******************************************************************************/
|
||||
/********************* A list of currently supported modules ******************/
|
||||
/******************************************************************************/
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_RPL
|
||||
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_NONE /* Only for rpl-lite */
|
||||
#endif /* LOG_CONF_LEVEL_RPL */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_TCPIP
|
||||
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_TCPIP */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_IPV6
|
||||
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_IPV6 */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_6LOWPAN
|
||||
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_6LOWPAN */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_NULLNET
|
||||
#define LOG_CONF_LEVEL_NULLNET LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_NULLNET */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_MAC
|
||||
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_MAC */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_FRAMER
|
||||
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_FRAMER */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_6TOP
|
||||
#define LOG_CONF_LEVEL_6TOP LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_6TOP */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_COAP
|
||||
#define LOG_CONF_LEVEL_COAP LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_COAP */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_LWM2M
|
||||
#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_NONE
|
||||
#endif /* LOG_CONF_LEVEL_LWM2M */
|
||||
|
||||
#ifndef LOG_CONF_LEVEL_MAIN
|
||||
#define LOG_CONF_LEVEL_MAIN LOG_LEVEL_INFO
|
||||
#endif /* LOG_CONF_LEVEL_MAIN */
|
||||
|
||||
#endif /* __LOG_CONF_H__ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
|
@ -12,8 +12,9 @@ CONTIKI_CPU=$(CONTIKI)/cpu/avr
|
|||
|
||||
### These directories will be searched for the specified source files
|
||||
### TARGETLIBS are platform-specific routines in the contiki library path
|
||||
CONTIKI_CPU_DIRS = . dev
|
||||
AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c watchdog.c rtimer-arch.c bootloader.c
|
||||
CONTIKI_CPU_DIRS = . dev dev/arduino
|
||||
AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c \
|
||||
watchdog.c rtimer-arch.c bootloader.c
|
||||
ELFLOADER = elfloader.c elfloader-avr.c symtab-avr.c
|
||||
TARGETLIBS = random.c leds.c
|
||||
|
||||
|
@ -88,6 +89,7 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
|
|||
|
||||
### Compiler definitions
|
||||
CC = avr-gcc
|
||||
CXX = avr-g++
|
||||
LD = avr-gcc
|
||||
AS = avr-as
|
||||
AR = avr-ar
|
||||
|
@ -129,6 +131,12 @@ $(OBJECTDIR)/%.o: %.c | $(OBJECTDIR)
|
|||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJECTDIR)/%.o: %.cpp | $(OBJECTDIR)
|
||||
$(CXX) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.ko: %.o
|
||||
$(STRIP) -K _init -K _fini --strip-unneeded -g -x $< -o $@
|
||||
|
||||
|
@ -194,22 +202,18 @@ endif
|
|||
### Upload image
|
||||
#Let avrdude use defaults if port or programmer not defined
|
||||
AVRDUDE ?= avrdude
|
||||
ifdef AVRDUDE_PORT
|
||||
AVRDUDE_PORT:=-P $(AVRDUDE_PORT)
|
||||
endif
|
||||
ifdef AVRDUDE_PROGRAMMER
|
||||
AVRDUDE_PROGRAMMER:=-c $(AVRDUDE_PROGRAMMER)
|
||||
endif
|
||||
ifdef AVRDUDE_MCU
|
||||
AVRDUDE_MCU:=-p $(AVRDUDE_MCU)
|
||||
DUDE_MCU:=-p $(AVRDUDE_MCU)
|
||||
else
|
||||
AVRDUDE_MCU:=-p $(MCU)
|
||||
DUDE_MCU:=-p $(MCU)
|
||||
endif
|
||||
%.u: %.hex
|
||||
$(AVRDUDE) $(AVRDUDE_MCU) $(AVRDUDE_OPTIONS) $(AVRDUDE_PORT) $(AVRDUDE_PROGRAMMER) -U flash:w:$<
|
||||
$(AVRDUDE) $(DUDE_MCU) $(AVRDUDE_OPTIONS) -P $(AVRDUDE_PORT) \
|
||||
-c $(AVRDUDE_PROGRAMMER) -U flash:w:$<:i
|
||||
|
||||
%.eu: %.eep
|
||||
$(AVRDUDE) $(AVRDUDE_MCU) ${AVRDUDE_OPTIONS} ${AVRDUDE_PORT} ${AVRDUDE_PROGRAMMER} -U eeprom:w:$<
|
||||
$(AVRDUDE) $(DUDE_MCU) ${AVRDUDE_OPTIONS} -P ${AVRDUDE_PORT} \
|
||||
-c ${AVRDUDE_PROGRAMMER} -U eeprom:w:$<:i
|
||||
|
||||
symbols.c:
|
||||
cp ${CONTIKI}/tools/empty-symbols.c symbols.c
|
||||
|
|
84
cpu/avr/dev/adc.c
Normal file
84
cpu/avr/dev/adc.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2012, BinaryLabs.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: adc.c,v 1.1 2010/08/25 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* ADC file for Atmega128rfa1.
|
||||
* \author
|
||||
* Paulo Louro <paulolouro@binarylabs.dk>
|
||||
*/
|
||||
|
||||
#include "adc.h"
|
||||
|
||||
static uint8_t analog_reference = ADC_DEFAULT;
|
||||
|
||||
/*
|
||||
* For arduino interface for setting external reference voltage
|
||||
* Note that applying an external voltage *and* then setting the analog
|
||||
* reference to something internal will short the internal and the
|
||||
* external reference voltage and most likely destroy the processor.
|
||||
*/
|
||||
void analogReference(uint8_t mode)
|
||||
{
|
||||
analog_reference = mode;
|
||||
}
|
||||
|
||||
int readADC(uint8_t pin)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
adc_setup (analog_reference, pin);
|
||||
result = adc_read ();
|
||||
adc_fin ();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return Internal temperature in 0.01C, e.g. 25C is 2500
|
||||
*/
|
||||
int readInternalTemp(void)
|
||||
{
|
||||
int reading = 0;
|
||||
|
||||
ADCSRB |= _BV(MUX5);
|
||||
ADMUX = _BV(REFS1) | _BV(REFS0) | 0b1001 ;
|
||||
ADCSRA = _BV(ADEN) | _BV(ADPS0) | _BV(ADPS2) ;
|
||||
|
||||
ADCSRA |= 1 << ADSC;
|
||||
loop_until_bit_is_clear(ADCSRA,ADSC);
|
||||
reading = ADC;
|
||||
|
||||
ADCSRB=0; //disable ADC, need to write B first for MUX5 bit
|
||||
ADCSRA=0; //disable ADC
|
||||
ADMUX=0; //turn off internal vref
|
||||
|
||||
return reading * 113 - 27280;
|
||||
}
|
65
cpu/avr/dev/adc.h
Normal file
65
cpu/avr/dev/adc.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
#ifndef __ADC_ARCH_H__
|
||||
#define __ADC_ARCH_H__
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
/*
|
||||
* Reference voltage
|
||||
* The default is 1.6V reference voltage
|
||||
* The selected reference voltage is the maximum voltage that can be
|
||||
* measured.
|
||||
* Directly provide shifted variants so we don't need to shift.
|
||||
*/
|
||||
#define ADC_1_5 (2<<6)
|
||||
#define ADC_1_6 (3<<6)
|
||||
#define ADC_1_8 (1<<6)
|
||||
#define ADC_EXTERNAL (0<<6)
|
||||
#define ADC_DEFAULT ADC_1_6
|
||||
|
||||
/* sometimes it's desirable to decouple setup / finish from sampling */
|
||||
|
||||
static inline void adc_setup (uint8_t ref_volt, uint8_t pin)
|
||||
{
|
||||
ADMUX = ref_volt | (pin & 0x7);
|
||||
ADCSRA = _BV(ADEN) | _BV(ADPS0) | _BV(ADPS2);
|
||||
}
|
||||
|
||||
static inline int adc_read (void)
|
||||
{
|
||||
ADCSRA |= (1 << ADSC);
|
||||
loop_until_bit_is_clear (ADCSRA, ADSC);
|
||||
return ADC;
|
||||
}
|
||||
|
||||
static inline void adc_fin (void)
|
||||
{
|
||||
ADCSRA = 0;
|
||||
ADMUX = 0;
|
||||
}
|
||||
|
||||
static inline void adc_init (void)
|
||||
{
|
||||
uint8_t temp;
|
||||
ADCSRC = 0;
|
||||
ADCSRB = 0;
|
||||
adc_fin ();
|
||||
/*
|
||||
* Disable JTAG interface
|
||||
* Hardware manual about JTD bit:
|
||||
* "In order to avoid unintentional disabling or enabling of the
|
||||
* JTAG interface, a timed sequence must be followed when changing
|
||||
* this bit: The application software must write this bit to the
|
||||
* desired value twice within four cycles to change its value."
|
||||
* 15.4.1 "MCUCR - MCU Control Register", p. 219
|
||||
*/
|
||||
temp = MCUCR | (1 << JTD);
|
||||
MCUCR = temp;
|
||||
MCUCR = temp;
|
||||
}
|
||||
|
||||
int readADC(uint8_t pin);
|
||||
long readVcc();
|
||||
int readInternalTemp(void);
|
||||
void analogReference(uint8_t mode);
|
||||
|
||||
#endif /* __ADC_ARCH_H__ */
|
174
cpu/avr/dev/arduino/Arduino.h
Normal file
174
cpu/avr/dev/arduino/Arduino.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
#include <hw-arduino.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "binary.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#define HIGH 0x1
|
||||
#define LOW 0x0
|
||||
|
||||
#define INPUT 0x0
|
||||
#define OUTPUT 0x1
|
||||
#define INPUT_PULLUP 0x2
|
||||
|
||||
#define true 0x1
|
||||
#define false 0x0
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
|
||||
#define SERIAL 0x0
|
||||
#define DISPLAY 0x1
|
||||
|
||||
#define LSBFIRST 0
|
||||
#define MSBFIRST 1
|
||||
|
||||
#define CHANGE 1
|
||||
#define FALLING 2
|
||||
#define RISING 3
|
||||
|
||||
#define DEFAULT ADC_DEFAULT
|
||||
#define EXTERNAL ADC_EXTERNAL
|
||||
|
||||
// undefine stdlib's abs if encountered
|
||||
#ifdef abs
|
||||
#undef abs
|
||||
#endif
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define abs(x) ((x)>0?(x):-(x))
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#define sq(x) ((x)*(x))
|
||||
|
||||
#define interrupts() sei()
|
||||
#define noInterrupts() cli()
|
||||
|
||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||
|
||||
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||
#define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L) )
|
||||
|
||||
typedef unsigned int word;
|
||||
|
||||
#define bit(b) (1UL << (b))
|
||||
|
||||
typedef uint8_t boolean;
|
||||
typedef uint8_t byte;
|
||||
|
||||
void pinMode(uint8_t, uint8_t);
|
||||
void digitalWrite(uint8_t, uint8_t);
|
||||
int digitalRead(uint8_t);
|
||||
|
||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||
|
||||
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
||||
|
||||
void attachInterrupt(uint8_t, void (*)(void), int mode);
|
||||
void detachInterrupt(uint8_t);
|
||||
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
// Get the bit location within the hardware port of the given virtual pin.
|
||||
// This comes from the pins_*.c file for the active board configuration.
|
||||
|
||||
#define analogInPinToBit(P) (P)
|
||||
|
||||
// On the ATmega1280, the addresses of some of the port registers are
|
||||
// greater than 255, so we can't store them in uint8_t's.
|
||||
extern const uint16_t PROGMEM port_to_mode_PGM[];
|
||||
extern const uint16_t PROGMEM port_to_input_PGM[];
|
||||
extern const uint16_t PROGMEM port_to_output_PGM[];
|
||||
|
||||
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
|
||||
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
|
||||
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
|
||||
|
||||
// Get the bit location within the hardware port of the given virtual pin.
|
||||
// This comes from the pins_*.c file for the active board configuration.
|
||||
//
|
||||
// These perform slightly better as macros compared to inline functions
|
||||
//
|
||||
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
|
||||
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
|
||||
#define analogInPinToBit(P) (P)
|
||||
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
|
||||
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
|
||||
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
|
||||
|
||||
#define NOT_A_PIN 0
|
||||
#define NOT_A_PORT 0
|
||||
|
||||
#ifdef ARDUINO_MAIN
|
||||
#define PA 1
|
||||
#define PB 2
|
||||
#define PC 3
|
||||
#define PD 4
|
||||
#define PE 5
|
||||
#define PF 6
|
||||
#define PG 7
|
||||
#define PH 8
|
||||
#define PJ 10
|
||||
#define PK 11
|
||||
#define PL 12
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
// look at this again when considering implementing serial
|
||||
#include "WCharacter.h"
|
||||
#include "WString.h"
|
||||
#include "HardwareSerial.h"
|
||||
|
||||
uint16_t makeWord(uint16_t w);
|
||||
uint16_t makeWord(byte h, byte l);
|
||||
|
||||
#define word(...) makeWord(__VA_ARGS__)
|
||||
|
||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||
|
||||
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||
void noTone(uint8_t _pin);
|
||||
|
||||
// WMath prototypes
|
||||
long random(long);
|
||||
long random(long, long);
|
||||
void randomSeed(unsigned int);
|
||||
long map(long, long, long, long, long);
|
||||
|
||||
#endif
|
||||
|
||||
#include "pins_arduino.h"
|
||||
|
||||
#include "dev/arduino/arduino-compat.h"
|
||||
|
||||
#endif
|
146
cpu/avr/dev/arduino/EEPROM.h
Normal file
146
cpu/avr/dev/arduino/EEPROM.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
EEPROM.h - EEPROM library
|
||||
Original Copyright (c) 2006 David A. Mellis. All right reserved.
|
||||
New version by Christopher Andrews 2015.
|
||||
|
||||
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 EEPROM_h
|
||||
#define EEPROM_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
/***
|
||||
EERef class.
|
||||
|
||||
This object references an EEPROM cell.
|
||||
Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM.
|
||||
This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell.
|
||||
***/
|
||||
|
||||
struct EERef{
|
||||
|
||||
EERef( const int index )
|
||||
: index( index ) {}
|
||||
|
||||
//Access/read members.
|
||||
uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); }
|
||||
operator const uint8_t() const { return **this; }
|
||||
|
||||
//Assignment/write members.
|
||||
EERef &operator=( const EERef &ref ) { return *this = *ref; }
|
||||
EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; }
|
||||
EERef &operator +=( uint8_t in ) { return *this = **this + in; }
|
||||
EERef &operator -=( uint8_t in ) { return *this = **this - in; }
|
||||
EERef &operator *=( uint8_t in ) { return *this = **this * in; }
|
||||
EERef &operator /=( uint8_t in ) { return *this = **this / in; }
|
||||
EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; }
|
||||
EERef &operator %=( uint8_t in ) { return *this = **this % in; }
|
||||
EERef &operator &=( uint8_t in ) { return *this = **this & in; }
|
||||
EERef &operator |=( uint8_t in ) { return *this = **this | in; }
|
||||
EERef &operator <<=( uint8_t in ) { return *this = **this << in; }
|
||||
EERef &operator >>=( uint8_t in ) { return *this = **this >> in; }
|
||||
|
||||
EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; }
|
||||
|
||||
/** Prefix increment/decrement **/
|
||||
EERef& operator++() { return *this += 1; }
|
||||
EERef& operator--() { return *this -= 1; }
|
||||
|
||||
/** Postfix increment/decrement **/
|
||||
uint8_t operator++ (int){
|
||||
uint8_t ret = **this;
|
||||
return ++(*this), ret;
|
||||
}
|
||||
|
||||
uint8_t operator-- (int){
|
||||
uint8_t ret = **this;
|
||||
return --(*this), ret;
|
||||
}
|
||||
|
||||
int index; //Index of current EEPROM cell.
|
||||
};
|
||||
|
||||
/***
|
||||
EEPtr class.
|
||||
|
||||
This object is a bidirectional pointer to EEPROM cells represented by EERef objects.
|
||||
Just like a normal pointer type, this can be dereferenced and repositioned using
|
||||
increment/decrement operators.
|
||||
***/
|
||||
|
||||
struct EEPtr{
|
||||
|
||||
EEPtr( const int index )
|
||||
: index( index ) {}
|
||||
|
||||
operator const int() const { return index; }
|
||||
EEPtr &operator=( int in ) { return index = in, *this; }
|
||||
|
||||
//Iterator functionality.
|
||||
bool operator!=( const EEPtr &ptr ) { return index != ptr.index; }
|
||||
EERef operator*() { return index; }
|
||||
|
||||
/** Prefix & Postfix increment/decrement **/
|
||||
EEPtr& operator++() { return ++index, *this; }
|
||||
EEPtr& operator--() { return --index, *this; }
|
||||
EEPtr operator++ (int) { return index++; }
|
||||
EEPtr operator-- (int) { return index--; }
|
||||
|
||||
int index; //Index of current EEPROM cell.
|
||||
};
|
||||
|
||||
/***
|
||||
EEPROMClass class.
|
||||
|
||||
This object represents the entire EEPROM space.
|
||||
It wraps the functionality of EEPtr and EERef into a basic interface.
|
||||
This class is also 100% backwards compatible with earlier Arduino core releases.
|
||||
***/
|
||||
|
||||
struct EEPROMClass{
|
||||
|
||||
//Basic user access methods.
|
||||
EERef operator[]( const int idx ) { return idx; }
|
||||
uint8_t read( int idx ) { return EERef( idx ); }
|
||||
void write( int idx, uint8_t val ) { (EERef( idx )) = val; }
|
||||
void update( int idx, uint8_t val ) { EERef( idx ).update( val ); }
|
||||
|
||||
//STL and C++11 iteration capability.
|
||||
EEPtr begin() { return 0x00; }
|
||||
EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
|
||||
uint16_t length() { return E2END + 1; }
|
||||
|
||||
//Functionality to 'get' and 'put' objects to and from EEPROM.
|
||||
template< typename T > T &get( int idx, T &t ){
|
||||
EEPtr e = idx;
|
||||
uint8_t *ptr = (uint8_t*) &t;
|
||||
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
|
||||
return t;
|
||||
}
|
||||
|
||||
template< typename T > const T &put( int idx, const T &t ){
|
||||
EEPtr e = idx;
|
||||
const uint8_t *ptr = (const uint8_t*) &t;
|
||||
for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ );
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
static EEPROMClass EEPROM;
|
||||
#endif
|
250
cpu/avr/dev/arduino/HardwareSerial.cpp
Normal file
250
cpu/avr/dev/arduino/HardwareSerial.cpp
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
HardwareSerial.cpp - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
Modified 3 December 2013 by Matthijs Kooijman
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "HardwareSerial_private.h"
|
||||
|
||||
// this next line disables the entire HardwareSerial.cpp,
|
||||
// this is so I can support Attiny series and any other chip without a uart
|
||||
#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3)
|
||||
|
||||
// SerialEvent functions are weak, so when the user doesn't define them,
|
||||
// the linker just sets their address to 0 (which is checked below).
|
||||
// The Serialx_available is just a wrapper around Serialx.available(),
|
||||
// but we can refer to it weakly so we don't pull in the entire
|
||||
// HardwareSerial instance if the user doesn't also refer to it.
|
||||
#if defined(HAVE_HWSERIAL0)
|
||||
void serialEvent() __attribute__((weak));
|
||||
bool Serial0_available() __attribute__((weak));
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_HWSERIAL1)
|
||||
void serialEvent1() __attribute__((weak));
|
||||
bool Serial1_available() __attribute__((weak));
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_HWSERIAL2)
|
||||
void serialEvent2() __attribute__((weak));
|
||||
bool Serial2_available() __attribute__((weak));
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_HWSERIAL3)
|
||||
void serialEvent3() __attribute__((weak));
|
||||
bool Serial3_available() __attribute__((weak));
|
||||
#endif
|
||||
|
||||
void serialEventRun(void)
|
||||
{
|
||||
#if defined(HAVE_HWSERIAL0)
|
||||
if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
|
||||
#endif
|
||||
#if defined(HAVE_HWSERIAL1)
|
||||
if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1();
|
||||
#endif
|
||||
#if defined(HAVE_HWSERIAL2)
|
||||
if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2();
|
||||
#endif
|
||||
#if defined(HAVE_HWSERIAL3)
|
||||
if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Actual interrupt handlers //////////////////////////////////////////////////////////////
|
||||
|
||||
void HardwareSerial::_tx_udr_empty_irq(void)
|
||||
{
|
||||
// If interrupts are enabled, there must be more data in the output
|
||||
// buffer. Send the next byte
|
||||
unsigned char c = _tx_buffer[_tx_buffer_tail];
|
||||
_tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;
|
||||
|
||||
*_udr = c;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
sbi(*_ucsra, TXC0);
|
||||
|
||||
if (_tx_buffer_head == _tx_buffer_tail) {
|
||||
// Buffer empty, so disable interrupts
|
||||
cbi(*_ucsrb, UDRIE0);
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
void HardwareSerial::begin(unsigned long baud, byte config)
|
||||
{
|
||||
// Try u2x mode first
|
||||
uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||
*_ucsra = 1 << U2X0;
|
||||
|
||||
// hardcoded exception for 57600 for compatibility with the bootloader
|
||||
// shipped with the Duemilanove and previous boards and the firmware
|
||||
// on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot
|
||||
// be > 4095, so switch back to non-u2x mode if the baud rate is too
|
||||
// low.
|
||||
if (((F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095))
|
||||
{
|
||||
*_ucsra = 0;
|
||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||
}
|
||||
|
||||
// assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register)
|
||||
*_ubrrh = baud_setting >> 8;
|
||||
*_ubrrl = baud_setting;
|
||||
|
||||
_written = false;
|
||||
|
||||
//set the data bits, parity, and stop bits
|
||||
#if defined(__AVR_ATmega8__)
|
||||
config |= 0x80; // select UCSRC register (shared with UBRRH)
|
||||
#endif
|
||||
*_ucsrc = config;
|
||||
|
||||
sbi(*_ucsrb, RXEN0);
|
||||
sbi(*_ucsrb, TXEN0);
|
||||
sbi(*_ucsrb, RXCIE0);
|
||||
cbi(*_ucsrb, UDRIE0);
|
||||
}
|
||||
|
||||
void HardwareSerial::end()
|
||||
{
|
||||
// wait for transmission of outgoing data
|
||||
flush();
|
||||
|
||||
cbi(*_ucsrb, RXEN0);
|
||||
cbi(*_ucsrb, TXEN0);
|
||||
cbi(*_ucsrb, RXCIE0);
|
||||
cbi(*_ucsrb, UDRIE0);
|
||||
|
||||
// clear any received data
|
||||
_rx_buffer_head = _rx_buffer_tail;
|
||||
}
|
||||
|
||||
int HardwareSerial::available(void)
|
||||
{
|
||||
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
int HardwareSerial::peek(void)
|
||||
{
|
||||
if (_rx_buffer_head == _rx_buffer_tail) {
|
||||
return -1;
|
||||
} else {
|
||||
return _rx_buffer[_rx_buffer_tail];
|
||||
}
|
||||
}
|
||||
|
||||
int HardwareSerial::read(void)
|
||||
{
|
||||
// if the head isn't ahead of the tail, we don't have any characters
|
||||
if (_rx_buffer_head == _rx_buffer_tail) {
|
||||
return -1;
|
||||
} else {
|
||||
unsigned char c = _rx_buffer[_rx_buffer_tail];
|
||||
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int HardwareSerial::availableForWrite(void)
|
||||
{
|
||||
#if (SERIAL_TX_BUFFER_SIZE>256)
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
#endif
|
||||
tx_buffer_index_t head = _tx_buffer_head;
|
||||
tx_buffer_index_t tail = _tx_buffer_tail;
|
||||
#if (SERIAL_TX_BUFFER_SIZE>256)
|
||||
SREG = oldSREG;
|
||||
#endif
|
||||
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
|
||||
return tail - head - 1;
|
||||
}
|
||||
|
||||
void HardwareSerial::flush()
|
||||
{
|
||||
// If we have never written a byte, no need to flush. This special
|
||||
// case is needed since there is no way to force the TXC (transmit
|
||||
// complete) bit to 1 during initialization
|
||||
if (!_written)
|
||||
return;
|
||||
|
||||
while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) {
|
||||
if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0))
|
||||
// Interrupts are globally disabled, but the DR empty
|
||||
// interrupt should be enabled, so poll the DR empty flag to
|
||||
// prevent deadlock
|
||||
if (bit_is_set(*_ucsra, UDRE0))
|
||||
_tx_udr_empty_irq();
|
||||
}
|
||||
// If we get here, nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished tranmission (TXC is set).
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(uint8_t c)
|
||||
{
|
||||
_written = true;
|
||||
// If the buffer and the data register is empty, just write the byte
|
||||
// to the data register and be done. This shortcut helps
|
||||
// significantly improve the effective datarate at high (>
|
||||
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
|
||||
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
|
||||
*_udr = c;
|
||||
sbi(*_ucsra, TXC0);
|
||||
return 1;
|
||||
}
|
||||
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
|
||||
|
||||
// If the output buffer is full, there's nothing for it other than to
|
||||
// wait for the interrupt handler to empty it a bit
|
||||
while (i == _tx_buffer_tail) {
|
||||
if (bit_is_clear(SREG, SREG_I)) {
|
||||
// Interrupts are disabled, so we'll have to poll the data
|
||||
// register empty flag ourselves. If it is set, pretend an
|
||||
// interrupt has happened and call the handler to free up
|
||||
// space for us.
|
||||
if(bit_is_set(*_ucsra, UDRE0))
|
||||
_tx_udr_empty_irq();
|
||||
} else {
|
||||
// nop, the interrupt handler will free up space for us
|
||||
}
|
||||
}
|
||||
|
||||
_tx_buffer[_tx_buffer_head] = c;
|
||||
_tx_buffer_head = i;
|
||||
|
||||
sbi(*_ucsrb, UDRIE0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // whole file
|
161
cpu/avr/dev/arduino/HardwareSerial.h
Normal file
161
cpu/avr/dev/arduino/HardwareSerial.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
HardwareSerial.h - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
Modified 3 December 2013 by Matthijs Kooijman
|
||||
*/
|
||||
|
||||
#ifndef HardwareSerial_h
|
||||
#define HardwareSerial_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
// using a ring buffer (I think), in which head is the index of the location
|
||||
// to which to write the next incoming character and tail is the index of the
|
||||
// location from which to read.
|
||||
// NOTE: a "power of 2" buffer size is reccomended to dramatically
|
||||
// optimize all the modulo operations for ring buffers.
|
||||
// WARNING: When buffer sizes are increased to > 256, the buffer index
|
||||
// variables are automatically increased in size, but the extra
|
||||
// atomicity guards needed for that are not implemented. This will
|
||||
// often work, but occasionally a race condition can occur that makes
|
||||
// Serial behave erratically. See https://github.com/arduino/Arduino/issues/2405
|
||||
#if !defined(SERIAL_TX_BUFFER_SIZE)
|
||||
#if ((RAMEND - RAMSTART) < 1023)
|
||||
#define SERIAL_TX_BUFFER_SIZE 16
|
||||
#else
|
||||
#define SERIAL_TX_BUFFER_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(SERIAL_RX_BUFFER_SIZE)
|
||||
#if ((RAMEND - RAMSTART) < 1023)
|
||||
#define SERIAL_RX_BUFFER_SIZE 16
|
||||
#else
|
||||
#define SERIAL_RX_BUFFER_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
#if (SERIAL_TX_BUFFER_SIZE>256)
|
||||
typedef uint16_t tx_buffer_index_t;
|
||||
#else
|
||||
typedef uint8_t tx_buffer_index_t;
|
||||
#endif
|
||||
#if (SERIAL_RX_BUFFER_SIZE>256)
|
||||
typedef uint16_t rx_buffer_index_t;
|
||||
#else
|
||||
typedef uint8_t rx_buffer_index_t;
|
||||
#endif
|
||||
|
||||
// Define config for Serial.begin(baud, config);
|
||||
#define SERIAL_5N1 0x00
|
||||
#define SERIAL_6N1 0x02
|
||||
#define SERIAL_7N1 0x04
|
||||
#define SERIAL_8N1 0x06
|
||||
#define SERIAL_5N2 0x08
|
||||
#define SERIAL_6N2 0x0A
|
||||
#define SERIAL_7N2 0x0C
|
||||
#define SERIAL_8N2 0x0E
|
||||
#define SERIAL_5E1 0x20
|
||||
#define SERIAL_6E1 0x22
|
||||
#define SERIAL_7E1 0x24
|
||||
#define SERIAL_8E1 0x26
|
||||
#define SERIAL_5E2 0x28
|
||||
#define SERIAL_6E2 0x2A
|
||||
#define SERIAL_7E2 0x2C
|
||||
#define SERIAL_8E2 0x2E
|
||||
#define SERIAL_5O1 0x30
|
||||
#define SERIAL_6O1 0x32
|
||||
#define SERIAL_7O1 0x34
|
||||
#define SERIAL_8O1 0x36
|
||||
#define SERIAL_5O2 0x38
|
||||
#define SERIAL_6O2 0x3A
|
||||
#define SERIAL_7O2 0x3C
|
||||
#define SERIAL_8O2 0x3E
|
||||
|
||||
class HardwareSerial : public Stream
|
||||
{
|
||||
protected:
|
||||
volatile uint8_t * const _ubrrh;
|
||||
volatile uint8_t * const _ubrrl;
|
||||
volatile uint8_t * const _ucsra;
|
||||
volatile uint8_t * const _ucsrb;
|
||||
volatile uint8_t * const _ucsrc;
|
||||
volatile uint8_t * const _udr;
|
||||
// Has any byte been written to the UART since begin()
|
||||
bool _written;
|
||||
|
||||
volatile rx_buffer_index_t _rx_buffer_head;
|
||||
volatile rx_buffer_index_t _rx_buffer_tail;
|
||||
volatile tx_buffer_index_t _tx_buffer_head;
|
||||
volatile tx_buffer_index_t _tx_buffer_tail;
|
||||
|
||||
// Don't put any members after these buffers, since only the first
|
||||
// 32 bytes of this struct can be accessed quickly using the ldd
|
||||
// instruction.
|
||||
unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
|
||||
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];
|
||||
|
||||
public:
|
||||
inline HardwareSerial(
|
||||
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||
volatile uint8_t *ucsrc, volatile uint8_t *udr);
|
||||
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
|
||||
void begin(unsigned long, uint8_t);
|
||||
void end();
|
||||
virtual int available(void);
|
||||
virtual int peek(void);
|
||||
virtual int read(void);
|
||||
int availableForWrite(void);
|
||||
virtual void flush(void);
|
||||
virtual size_t write(uint8_t);
|
||||
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||
inline size_t write(long n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||
inline size_t write(int n) { return write((uint8_t)n); }
|
||||
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||
operator bool() { return true; }
|
||||
|
||||
// Interrupt handlers - Not intended to be called externally
|
||||
inline void _rx_complete_irq(void);
|
||||
void _tx_udr_empty_irq(void);
|
||||
};
|
||||
|
||||
#if defined(UBRRH) || defined(UBRR0H)
|
||||
extern HardwareSerial Serial;
|
||||
#define HAVE_HWSERIAL0
|
||||
#endif
|
||||
#if defined(UBRR1H)
|
||||
extern HardwareSerial Serial1;
|
||||
#define HAVE_HWSERIAL1
|
||||
#endif
|
||||
#if defined(UBRR2H)
|
||||
extern HardwareSerial Serial2;
|
||||
#define HAVE_HWSERIAL2
|
||||
#endif
|
||||
#if defined(UBRR3H)
|
||||
extern HardwareSerial Serial3;
|
||||
#define HAVE_HWSERIAL3
|
||||
#endif
|
||||
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
|
||||
#endif
|
79
cpu/avr/dev/arduino/HardwareSerial0.cpp
Normal file
79
cpu/avr/dev/arduino/HardwareSerial0.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
HardwareSerial0.cpp - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
Modified 3 December 2013 by Matthijs Kooijman
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "HardwareSerial_private.h"
|
||||
|
||||
// Each HardwareSerial is defined in its own file, sine the linker pulls
|
||||
// in the entire file when any element inside is used. --gc-sections can
|
||||
// additionally cause unused symbols to be dropped, but ISRs have the
|
||||
// "used" attribute so are never dropped and they keep the
|
||||
// HardwareSerial instance in as well. Putting each instance in its own
|
||||
// file prevents the linker from pulling in any unused instances in the
|
||||
// first place.
|
||||
|
||||
#if defined(HAVE_HWSERIAL0)
|
||||
|
||||
#if defined(USART_RX_vect)
|
||||
ISR(USART_RX_vect)
|
||||
#elif defined(USART0_RX_vect)
|
||||
ISR(USART0_RX_vect)
|
||||
#elif defined(USART_RXC_vect)
|
||||
ISR(USART_RXC_vect) // ATmega8
|
||||
#else
|
||||
#error "Don't know what the Data Received vector is called for Serial"
|
||||
#endif
|
||||
{
|
||||
Serial._rx_complete_irq();
|
||||
}
|
||||
|
||||
#if defined(UART0_UDRE_vect)
|
||||
ISR(UART0_UDRE_vect)
|
||||
#elif defined(UART_UDRE_vect)
|
||||
ISR(UART_UDRE_vect)
|
||||
#elif defined(USART0_UDRE_vect)
|
||||
ISR(USART0_UDRE_vect)
|
||||
#elif defined(USART_UDRE_vect)
|
||||
ISR(USART_UDRE_vect)
|
||||
#else
|
||||
#error "Don't know what the Data Register Empty vector is called for Serial"
|
||||
#endif
|
||||
{
|
||||
Serial._tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
#if defined(UBRRH) && defined(UBRRL)
|
||||
HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
|
||||
#else
|
||||
HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0);
|
||||
#endif
|
||||
|
||||
// Function that can be weakly referenced by serialEventRun to prevent
|
||||
// pulling in this file if it's not otherwise used.
|
||||
bool Serial0_available() {
|
||||
return Serial.available();
|
||||
}
|
||||
|
||||
#endif // HAVE_HWSERIAL0
|
69
cpu/avr/dev/arduino/HardwareSerial1.cpp
Normal file
69
cpu/avr/dev/arduino/HardwareSerial1.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
HardwareSerial1.cpp - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
Modified 3 December 2013 by Matthijs Kooijman
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "HardwareSerial_private.h"
|
||||
|
||||
// Each HardwareSerial is defined in its own file, sine the linker pulls
|
||||
// in the entire file when any element inside is used. --gc-sections can
|
||||
// additionally cause unused symbols to be dropped, but ISRs have the
|
||||
// "used" attribute so are never dropped and they keep the
|
||||
// HardwareSerial instance in as well. Putting each instance in its own
|
||||
// file prevents the linker from pulling in any unused instances in the
|
||||
// first place.
|
||||
|
||||
#if defined(HAVE_HWSERIAL1)
|
||||
|
||||
#if defined(UART1_RX_vect)
|
||||
ISR(UART1_RX_vect)
|
||||
#elif defined(USART1_RX_vect)
|
||||
ISR(USART1_RX_vect)
|
||||
#else
|
||||
#error "Don't know what the Data Register Empty vector is called for Serial1"
|
||||
#endif
|
||||
{
|
||||
Serial1._rx_complete_irq();
|
||||
}
|
||||
|
||||
#if defined(UART1_UDRE_vect)
|
||||
ISR(UART1_UDRE_vect)
|
||||
#elif defined(USART1_UDRE_vect)
|
||||
ISR(USART1_UDRE_vect)
|
||||
#else
|
||||
#error "Don't know what the Data Register Empty vector is called for Serial1"
|
||||
#endif
|
||||
{
|
||||
Serial1._tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1);
|
||||
|
||||
// Function that can be weakly referenced by serialEventRun to prevent
|
||||
// pulling in this file if it's not otherwise used.
|
||||
bool Serial1_available() {
|
||||
return Serial1.available();
|
||||
}
|
||||
|
||||
#endif // HAVE_HWSERIAL1
|
123
cpu/avr/dev/arduino/HardwareSerial_private.h
Normal file
123
cpu/avr/dev/arduino/HardwareSerial_private.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
HardwareSerial_private.h - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
*/
|
||||
|
||||
#include "wiring_private.h"
|
||||
|
||||
// this next line disables the entire HardwareSerial.cpp,
|
||||
// this is so I can support Attiny series and any other chip without a uart
|
||||
#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3)
|
||||
|
||||
// Ensure that the various bit positions we use are available with a 0
|
||||
// postfix, so we can always use the values for UART0 for all UARTs. The
|
||||
// alternative, passing the various values for each UART to the
|
||||
// HardwareSerial constructor also works, but makes the code bigger and
|
||||
// slower.
|
||||
#if !defined(TXC0)
|
||||
#if defined(TXC)
|
||||
// Some chips like ATmega8 don't have UPE, only PE. The other bits are
|
||||
// named as expected.
|
||||
#if !defined(UPE) && defined(PE)
|
||||
#define UPE PE
|
||||
#endif
|
||||
// On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc.
|
||||
#define TXC0 TXC
|
||||
#define RXEN0 RXEN
|
||||
#define TXEN0 TXEN
|
||||
#define RXCIE0 RXCIE
|
||||
#define UDRIE0 UDRIE
|
||||
#define U2X0 U2X
|
||||
#define UPE0 UPE
|
||||
#define UDRE0 UDRE
|
||||
#elif defined(TXC1)
|
||||
// Some devices have uart1 but no uart0
|
||||
#define TXC0 TXC1
|
||||
#define RXEN0 RXEN1
|
||||
#define TXEN0 TXEN1
|
||||
#define RXCIE0 RXCIE1
|
||||
#define UDRIE0 UDRIE1
|
||||
#define U2X0 U2X1
|
||||
#define UPE0 UPE1
|
||||
#define UDRE0 UDRE1
|
||||
#else
|
||||
#error No UART found in HardwareSerial.cpp
|
||||
#endif
|
||||
#endif // !defined TXC0
|
||||
|
||||
// Check at compiletime that it is really ok to use the bit positions of
|
||||
// UART0 for the other UARTs as well, in case these values ever get
|
||||
// changed for future hardware.
|
||||
#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \
|
||||
UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \
|
||||
UDRE1 != UDRE0)
|
||||
#error "Not all bit positions for UART1 are the same as for UART0"
|
||||
#endif
|
||||
#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \
|
||||
UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \
|
||||
UDRE2 != UDRE0)
|
||||
#error "Not all bit positions for UART2 are the same as for UART0"
|
||||
#endif
|
||||
#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \
|
||||
UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \
|
||||
UDRE3 != UDRE0)
|
||||
#error "Not all bit positions for UART3 are the same as for UART0"
|
||||
#endif
|
||||
|
||||
// Constructors ////////////////////////////////////////////////////////////////
|
||||
|
||||
HardwareSerial::HardwareSerial(
|
||||
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||
volatile uint8_t *ucsrc, volatile uint8_t *udr) :
|
||||
_ubrrh(ubrrh), _ubrrl(ubrrl),
|
||||
_ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc),
|
||||
_udr(udr),
|
||||
_rx_buffer_head(0), _rx_buffer_tail(0),
|
||||
_tx_buffer_head(0), _tx_buffer_tail(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Actual interrupt handlers //////////////////////////////////////////////////////////////
|
||||
|
||||
void HardwareSerial::_rx_complete_irq(void)
|
||||
{
|
||||
if (bit_is_clear(*_ucsra, UPE0)) {
|
||||
// No Parity error, read byte and store it in the buffer if there is
|
||||
// room
|
||||
unsigned char c = *_udr;
|
||||
rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if (i != _rx_buffer_tail) {
|
||||
_rx_buffer[_rx_buffer_head] = c;
|
||||
_rx_buffer_head = i;
|
||||
}
|
||||
} else {
|
||||
// Parity error, read byte but discard it
|
||||
*_udr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // whole file
|
265
cpu/avr/dev/arduino/Print.cpp
Normal file
265
cpu/avr/dev/arduino/Print.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
Print.cpp - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 03 August 2015 by Chuck Todd
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
/* default implementation: may be overridden */
|
||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (write(*buffer++)) n++;
|
||||
else break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
unsigned char c = pgm_read_byte(p++);
|
||||
if (c == 0) break;
|
||||
if (write(c)) n++;
|
||||
else break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const String &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[])
|
||||
{
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c)
|
||||
{
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base)
|
||||
{
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base)
|
||||
{
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base)
|
||||
{
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base)
|
||||
{
|
||||
if (base == 0) {
|
||||
return write(n);
|
||||
} else if (base == 10) {
|
||||
if (n < 0) {
|
||||
int t = print('-');
|
||||
n = -n;
|
||||
return printNumber(n, 10) + t;
|
||||
}
|
||||
return printNumber(n, 10);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base)
|
||||
{
|
||||
if (base == 0) return write(n);
|
||||
else return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits)
|
||||
{
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
size_t n = print(ifsh);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
{
|
||||
return x.printTo(*this);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
return write("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const String &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[])
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c)
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base)
|
||||
{
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits)
|
||||
{
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const Printable& x)
|
||||
{
|
||||
size_t n = print(x);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if (base < 2) base = 10;
|
||||
|
||||
do {
|
||||
unsigned long m = n;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if (isnan(number)) return print("nan");
|
||||
if (isinf(number)) return print("inf");
|
||||
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
|
||||
// Handle negative numbers
|
||||
if (number < 0.0)
|
||||
{
|
||||
n += print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i=0; i<digits; ++i)
|
||||
rounding /= 10.0;
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long)number;
|
||||
double remainder = number - (double)int_part;
|
||||
n += print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0) {
|
||||
n += print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0)
|
||||
{
|
||||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
n += print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
84
cpu/avr/dev/arduino/Print.h
Normal file
84
cpu/avr/dev/arduino/Print.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Print.h - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right 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 Print_h
|
||||
#define Print_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h> // for size_t
|
||||
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
class Print
|
||||
{
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long, uint8_t);
|
||||
size_t printFloat(double, uint8_t);
|
||||
protected:
|
||||
void setWriteError(int err = 1) { write_error = err; }
|
||||
public:
|
||||
Print() : write_error(0) {}
|
||||
|
||||
int getWriteError() { return write_error; }
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
size_t print(const __FlashStringHelper *);
|
||||
size_t print(const String &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
size_t print(unsigned char, int = DEC);
|
||||
size_t print(int, int = DEC);
|
||||
size_t print(unsigned int, int = DEC);
|
||||
size_t print(long, int = DEC);
|
||||
size_t print(unsigned long, int = DEC);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(const Printable&);
|
||||
|
||||
size_t println(const __FlashStringHelper *);
|
||||
size_t println(const String &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
size_t println(unsigned char, int = DEC);
|
||||
size_t println(int, int = DEC);
|
||||
size_t println(unsigned int, int = DEC);
|
||||
size_t println(long, int = DEC);
|
||||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
size_t println(const Printable&);
|
||||
size_t println(void);
|
||||
};
|
||||
|
||||
#endif
|
40
cpu/avr/dev/arduino/Printable.h
Normal file
40
cpu/avr/dev/arduino/Printable.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Printable.h - Interface class that allows printing of complex types
|
||||
Copyright (c) 2011 Adrian McEwen. All right 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 Printable_h
|
||||
#define Printable_h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Print;
|
||||
|
||||
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||
for users to print out instances of this class by passing them into the usual
|
||||
Print::print and Print::println methods.
|
||||
*/
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
201
cpu/avr/dev/arduino/SPI.cpp
Normal file
201
cpu/avr/dev/arduino/SPI.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
|
||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||
* SPI Master library for arduino.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
|
||||
SPIClass SPI;
|
||||
|
||||
uint8_t SPIClass::initialized = 0;
|
||||
uint8_t SPIClass::interruptMode = 0;
|
||||
uint8_t SPIClass::interruptMask = 0;
|
||||
uint8_t SPIClass::interruptSave = 0;
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
uint8_t SPIClass::inTransactionFlag = 0;
|
||||
#endif
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
if (!initialized) {
|
||||
// Set SS to high so a connected chip will be "deselected" by default
|
||||
uint8_t port = digitalPinToPort(SS);
|
||||
uint8_t bit = digitalPinToBitMask(SS);
|
||||
volatile uint8_t *reg = portModeRegister(port);
|
||||
|
||||
// if the SS pin is not already configured as an output
|
||||
// then set it high (to enable the internal pull-up resistor)
|
||||
if(!(*reg & bit)){
|
||||
digitalWrite(SS, HIGH);
|
||||
}
|
||||
|
||||
// When the SS pin is set as OUTPUT, it can be used as
|
||||
// a general purpose output port (it doesn't influence
|
||||
// SPI operations).
|
||||
pinMode(SS, OUTPUT);
|
||||
|
||||
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
|
||||
// automatically switches to Slave, so the data direction of
|
||||
// the SS pin MUST be kept as OUTPUT.
|
||||
SPCR |= _BV(MSTR);
|
||||
SPCR |= _BV(SPE);
|
||||
|
||||
// Set direction register for SCK and MOSI pin.
|
||||
// MISO pin automatically overrides to INPUT.
|
||||
// By doing this AFTER enabling SPI, we avoid accidentally
|
||||
// clocking in a single bit since the lines go directly
|
||||
// from "input" to SPI control.
|
||||
// http://code.google.com/p/arduino/issues/detail?id=888
|
||||
pinMode(SCK, OUTPUT);
|
||||
pinMode(MOSI, OUTPUT);
|
||||
}
|
||||
initialized++; // reference count
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
void SPIClass::end() {
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
// Decrease the reference counter
|
||||
if (initialized)
|
||||
initialized--;
|
||||
// If there are no more references disable SPI
|
||||
if (!initialized) {
|
||||
SPCR &= ~_BV(SPE);
|
||||
interruptMode = 0;
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
inTransactionFlag = 0;
|
||||
#endif
|
||||
}
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
|
||||
#if defined(__AVR_ATmega32U4__)
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#define SPI_INT3_MASK (1<<INT3)
|
||||
#define SPI_INT4_MASK (1<<INT6)
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#define SPI_INT3_MASK (1<<INT3)
|
||||
#define SPI_INT4_MASK (1<<INT4)
|
||||
#define SPI_INT5_MASK (1<<INT5)
|
||||
#define SPI_INT6_MASK (1<<INT6)
|
||||
#define SPI_INT7_MASK (1<<INT7)
|
||||
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
#define SPI_INT0_MASK (1<<INT4)
|
||||
#define SPI_INT1_MASK (1<<INT5)
|
||||
#define SPI_INT2_MASK (1<<INT0)
|
||||
#define SPI_INT3_MASK (1<<INT1)
|
||||
#define SPI_INT4_MASK (1<<INT2)
|
||||
#define SPI_INT5_MASK (1<<INT3)
|
||||
#define SPI_INT6_MASK (1<<INT6)
|
||||
#define SPI_INT7_MASK (1<<INT7)
|
||||
#else
|
||||
#ifdef INT0
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#endif
|
||||
#ifdef INT1
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#endif
|
||||
#ifdef INT2
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
switch (interruptNumber) {
|
||||
#ifdef SPI_INT0_MASK
|
||||
case 0: mask = SPI_INT0_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT1_MASK
|
||||
case 1: mask = SPI_INT1_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT2_MASK
|
||||
case 2: mask = SPI_INT2_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT3_MASK
|
||||
case 3: mask = SPI_INT3_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT4_MASK
|
||||
case 4: mask = SPI_INT4_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT5_MASK
|
||||
case 5: mask = SPI_INT5_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT6_MASK
|
||||
case 6: mask = SPI_INT6_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT7_MASK
|
||||
case 7: mask = SPI_INT7_MASK; break;
|
||||
#endif
|
||||
default:
|
||||
interruptMode = 2;
|
||||
break;
|
||||
}
|
||||
interruptMask |= mask;
|
||||
if (!interruptMode)
|
||||
interruptMode = 1;
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
// Once in mode 2 we can't go back to 0 without a proper reference count
|
||||
if (interruptMode == 2)
|
||||
return;
|
||||
uint8_t mask = 0;
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
switch (interruptNumber) {
|
||||
#ifdef SPI_INT0_MASK
|
||||
case 0: mask = SPI_INT0_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT1_MASK
|
||||
case 1: mask = SPI_INT1_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT2_MASK
|
||||
case 2: mask = SPI_INT2_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT3_MASK
|
||||
case 3: mask = SPI_INT3_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT4_MASK
|
||||
case 4: mask = SPI_INT4_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT5_MASK
|
||||
case 5: mask = SPI_INT5_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT6_MASK
|
||||
case 6: mask = SPI_INT6_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT7_MASK
|
||||
case 7: mask = SPI_INT7_MASK; break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
// this case can't be reached
|
||||
}
|
||||
interruptMask &= ~mask;
|
||||
if (!interruptMask)
|
||||
interruptMode = 0;
|
||||
SREG = sreg;
|
||||
}
|
324
cpu/avr/dev/arduino/SPI.h
Normal file
324
cpu/avr/dev/arduino/SPI.h
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
|
||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||
* SPI Master library for arduino.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _SPI_H_INCLUDED
|
||||
#define _SPI_H_INCLUDED
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
|
||||
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
|
||||
#define SPI_HAS_TRANSACTION 1
|
||||
|
||||
// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method
|
||||
#define SPI_HAS_NOTUSINGINTERRUPT 1
|
||||
|
||||
// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version.
|
||||
// This way when there is a bug fix you can check this define to alert users
|
||||
// of your code if it uses better version of this library.
|
||||
// This also implies everything that SPI_HAS_TRANSACTION as documented above is
|
||||
// available too.
|
||||
#define SPI_ATOMIC_VERSION 1
|
||||
|
||||
// Uncomment this line to add detection of mismatched begin/end transactions.
|
||||
// A mismatch occurs if other libraries fail to use SPI.endTransaction() for
|
||||
// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn
|
||||
// on if any mismatch is ever detected.
|
||||
//#define SPI_TRANSACTION_MISMATCH_LED 5
|
||||
|
||||
#ifndef LSBFIRST
|
||||
#define LSBFIRST 0
|
||||
#endif
|
||||
#ifndef MSBFIRST
|
||||
#define MSBFIRST 1
|
||||
#endif
|
||||
|
||||
#define SPI_CLOCK_DIV4 0x00
|
||||
#define SPI_CLOCK_DIV16 0x01
|
||||
#define SPI_CLOCK_DIV64 0x02
|
||||
#define SPI_CLOCK_DIV128 0x03
|
||||
#define SPI_CLOCK_DIV2 0x04
|
||||
#define SPI_CLOCK_DIV8 0x05
|
||||
#define SPI_CLOCK_DIV32 0x06
|
||||
|
||||
#define SPI_MODE0 0x00
|
||||
#define SPI_MODE1 0x04
|
||||
#define SPI_MODE2 0x08
|
||||
#define SPI_MODE3 0x0C
|
||||
|
||||
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
|
||||
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
|
||||
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
|
||||
|
||||
// define SPI_AVR_EIMSK for AVR boards with external interrupt pins
|
||||
#if defined(EIMSK)
|
||||
#define SPI_AVR_EIMSK EIMSK
|
||||
#elif defined(GICR)
|
||||
#define SPI_AVR_EIMSK GICR
|
||||
#elif defined(GIMSK)
|
||||
#define SPI_AVR_EIMSK GIMSK
|
||||
#endif
|
||||
|
||||
class SPISettings {
|
||||
public:
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
if (__builtin_constant_p(clock)) {
|
||||
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||
} else {
|
||||
init_MightInline(clock, bitOrder, dataMode);
|
||||
}
|
||||
}
|
||||
SPISettings() {
|
||||
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
|
||||
}
|
||||
private:
|
||||
void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||
}
|
||||
void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
|
||||
__attribute__((__always_inline__)) {
|
||||
// Clock settings are defined as follows. Note that this shows SPI2X
|
||||
// inverted, so the bits form increasing numbers. Also note that
|
||||
// fosc/64 appears twice
|
||||
// SPR1 SPR0 ~SPI2X Freq
|
||||
// 0 0 0 fosc/2
|
||||
// 0 0 1 fosc/4
|
||||
// 0 1 0 fosc/8
|
||||
// 0 1 1 fosc/16
|
||||
// 1 0 0 fosc/32
|
||||
// 1 0 1 fosc/64
|
||||
// 1 1 0 fosc/64
|
||||
// 1 1 1 fosc/128
|
||||
|
||||
// We find the fastest clock that is less than or equal to the
|
||||
// given clock rate. The clock divider that results in clock_setting
|
||||
// is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
|
||||
// slowest (128 == 2 ^^ 7, so clock_div = 6).
|
||||
uint8_t clockDiv;
|
||||
|
||||
// When the clock is known at compiletime, use this if-then-else
|
||||
// cascade, which the compiler knows how to completely optimize
|
||||
// away. When clock is not known, use a loop instead, which generates
|
||||
// shorter code.
|
||||
if (__builtin_constant_p(clock)) {
|
||||
if (clock >= F_CPU / 2) {
|
||||
clockDiv = 0;
|
||||
} else if (clock >= F_CPU / 4) {
|
||||
clockDiv = 1;
|
||||
} else if (clock >= F_CPU / 8) {
|
||||
clockDiv = 2;
|
||||
} else if (clock >= F_CPU / 16) {
|
||||
clockDiv = 3;
|
||||
} else if (clock >= F_CPU / 32) {
|
||||
clockDiv = 4;
|
||||
} else if (clock >= F_CPU / 64) {
|
||||
clockDiv = 5;
|
||||
} else {
|
||||
clockDiv = 6;
|
||||
}
|
||||
} else {
|
||||
uint32_t clockSetting = F_CPU / 2;
|
||||
clockDiv = 0;
|
||||
while (clockDiv < 6 && clock < clockSetting) {
|
||||
clockSetting /= 2;
|
||||
clockDiv++;
|
||||
}
|
||||
}
|
||||
|
||||
// Compensate for the duplicate fosc/64
|
||||
if (clockDiv == 6)
|
||||
clockDiv = 7;
|
||||
|
||||
// Invert the SPI2X bit
|
||||
clockDiv ^= 0x1;
|
||||
|
||||
// Pack into the SPISettings class
|
||||
spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
|
||||
(dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
|
||||
spsr = clockDiv & SPI_2XCLOCK_MASK;
|
||||
}
|
||||
uint8_t spcr;
|
||||
uint8_t spsr;
|
||||
friend class SPIClass;
|
||||
};
|
||||
|
||||
|
||||
class SPIClass {
|
||||
public:
|
||||
// Initialize the SPI library
|
||||
static void begin();
|
||||
|
||||
// If SPI is used from within an interrupt, this function registers
|
||||
// that interrupt with the SPI library, so beginTransaction() can
|
||||
// prevent conflicts. The input interruptNumber is the number used
|
||||
// with attachInterrupt. If SPI is used from a different interrupt
|
||||
// (eg, a timer), interruptNumber should be 255.
|
||||
static void usingInterrupt(uint8_t interruptNumber);
|
||||
// And this does the opposite.
|
||||
static void notUsingInterrupt(uint8_t interruptNumber);
|
||||
// Note: the usingInterrupt and notUsingInterrupt functions should
|
||||
// not to be called from ISR context or inside a transaction.
|
||||
// For details see:
|
||||
// https://github.com/arduino/Arduino/pull/2381
|
||||
// https://github.com/arduino/Arduino/pull/2449
|
||||
|
||||
// Before using SPI.transfer() or asserting chip select pins,
|
||||
// this function is used to gain exclusive access to the SPI bus
|
||||
// and configure the correct settings.
|
||||
inline static void beginTransaction(SPISettings settings) {
|
||||
if (interruptMode > 0) {
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts();
|
||||
|
||||
#ifdef SPI_AVR_EIMSK
|
||||
if (interruptMode == 1) {
|
||||
interruptSave = SPI_AVR_EIMSK;
|
||||
SPI_AVR_EIMSK &= ~interruptMask;
|
||||
SREG = sreg;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
interruptSave = sreg;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
if (inTransactionFlag) {
|
||||
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
|
||||
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
|
||||
}
|
||||
inTransactionFlag = 1;
|
||||
#endif
|
||||
|
||||
SPCR = settings.spcr;
|
||||
SPSR = settings.spsr;
|
||||
}
|
||||
|
||||
// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
|
||||
inline static uint8_t transfer(uint8_t data) {
|
||||
SPDR = data;
|
||||
/*
|
||||
* The following NOP introduces a small delay that can prevent the wait
|
||||
* loop form iterating when running at the maximum speed. This gives
|
||||
* about 10% more speed, even if it seems counter-intuitive. At lower
|
||||
* speeds it is unnoticed.
|
||||
*/
|
||||
asm volatile("nop");
|
||||
while (!(SPSR & _BV(SPIF))) ; // wait
|
||||
return SPDR;
|
||||
}
|
||||
inline static uint16_t transfer16(uint16_t data) {
|
||||
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
|
||||
in.val = data;
|
||||
if (!(SPCR & _BV(DORD))) {
|
||||
SPDR = in.msb;
|
||||
asm volatile("nop"); // See transfer(uint8_t) function
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
out.msb = SPDR;
|
||||
SPDR = in.lsb;
|
||||
asm volatile("nop");
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
out.lsb = SPDR;
|
||||
} else {
|
||||
SPDR = in.lsb;
|
||||
asm volatile("nop");
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
out.lsb = SPDR;
|
||||
SPDR = in.msb;
|
||||
asm volatile("nop");
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
out.msb = SPDR;
|
||||
}
|
||||
return out.val;
|
||||
}
|
||||
inline static void transfer(void *buf, size_t count) {
|
||||
if (count == 0) return;
|
||||
uint8_t *p = (uint8_t *)buf;
|
||||
SPDR = *p;
|
||||
while (--count > 0) {
|
||||
uint8_t out = *(p + 1);
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
uint8_t in = SPDR;
|
||||
SPDR = out;
|
||||
*p++ = in;
|
||||
}
|
||||
while (!(SPSR & _BV(SPIF))) ;
|
||||
*p = SPDR;
|
||||
}
|
||||
// After performing a group of transfers and releasing the chip select
|
||||
// signal, this function allows others to access the SPI bus
|
||||
inline static void endTransaction(void) {
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
if (!inTransactionFlag) {
|
||||
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
|
||||
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
|
||||
}
|
||||
inTransactionFlag = 0;
|
||||
#endif
|
||||
|
||||
if (interruptMode > 0) {
|
||||
#ifdef SPI_AVR_EIMSK
|
||||
uint8_t sreg = SREG;
|
||||
#endif
|
||||
noInterrupts();
|
||||
#ifdef SPI_AVR_EIMSK
|
||||
if (interruptMode == 1) {
|
||||
SPI_AVR_EIMSK = interruptSave;
|
||||
SREG = sreg;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
SREG = interruptSave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the SPI bus
|
||||
static void end();
|
||||
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
inline static void setBitOrder(uint8_t bitOrder) {
|
||||
if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
|
||||
else SPCR &= ~(_BV(DORD));
|
||||
}
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
inline static void setDataMode(uint8_t dataMode) {
|
||||
SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
|
||||
}
|
||||
// This function is deprecated. New applications should use
|
||||
// beginTransaction() to configure SPI settings.
|
||||
inline static void setClockDivider(uint8_t clockDiv) {
|
||||
SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
|
||||
SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
|
||||
}
|
||||
// These undocumented functions should not be used. SPI.transfer()
|
||||
// polls the hardware flag which is automatically cleared as the
|
||||
// AVR responds to SPI's interrupt
|
||||
inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
|
||||
inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
|
||||
|
||||
private:
|
||||
static uint8_t initialized;
|
||||
static uint8_t interruptMode; // 0=none, 1=mask, 2=global
|
||||
static uint8_t interruptMask; // which interrupts to mask
|
||||
static uint8_t interruptSave; // temp storage, to restore state
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
static uint8_t inTransactionFlag;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern SPIClass SPI;
|
||||
|
||||
#endif
|
319
cpu/avr/dev/arduino/Stream.cpp
Normal file
319
cpu/avr/dev/arduino/Stream.cpp
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 David A. Mellis. All right 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
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
|
||||
findMulti/findUntil routines written by Jim Leonard/Xuth
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = timedPeek();
|
||||
|
||||
if( c < 0 ||
|
||||
c == '-' ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
(detectDecimal && c == '.')) return c;
|
||||
|
||||
switch( lookahead ){
|
||||
case SKIP_NONE: return -1; // Fail code.
|
||||
case SKIP_WHITESPACE:
|
||||
switch( c ){
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n': break;
|
||||
default: return -1; // Fail code.
|
||||
}
|
||||
case SKIP_ALL:
|
||||
break;
|
||||
}
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(char *target)
|
||||
{
|
||||
return findUntil(target, strlen(target), NULL, 0);
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(char *target, char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||
{
|
||||
if (terminator == NULL) {
|
||||
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||
return findMulti(t, 1) == 0 ? true : false;
|
||||
} else {
|
||||
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||
return findMulti(t, 2) == 0 ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// lookahead determines how parseInt looks ahead in the stream.
|
||||
// See LookaheadMode enumeration at the top of the file.
|
||||
// Lookahead is terminated by the first character that is not a valid part of an integer.
|
||||
// Once parsing commences, 'ignore' will be skipped in the stream.
|
||||
long Stream::parseInt(LookaheadMode lookahead, char ignore)
|
||||
{
|
||||
bool isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit(lookahead, false);
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == ignore)
|
||||
; // ignore this character
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c >= '0' && c <= '9') // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || c == ignore );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat(LookaheadMode lookahead, char ignore)
|
||||
{
|
||||
bool isNegative = false;
|
||||
bool isFraction = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
float fraction = 1.0;
|
||||
|
||||
c = peekNextDigit(lookahead, true);
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == ignore)
|
||||
; // ignore
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if (c == '.')
|
||||
isFraction = true;
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction)
|
||||
fraction *= 0.1;
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
if(isFraction)
|
||||
return value * fraction;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0) break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// as readBytes with terminator character
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
if (length < 1) return 0;
|
||||
size_t index = 0;
|
||||
while (index < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0 || c == terminator) break;
|
||||
*buffer++ = (char)c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0 && c != terminator)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||
// any zero length target string automatically matches and would make
|
||||
// a mess of the rest of the algorithm.
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
if (t->len <= 0)
|
||||
return t - targets;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
// the simple case is if we match, deal with that first.
|
||||
if (c == t->str[t->index]) {
|
||||
if (++t->index == t->len)
|
||||
return t - targets;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not we need to walk back and see if we could have matched further
|
||||
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||
// but it will match the second position so we can't just reset the current
|
||||
// index to 0 when we find a mismatch.
|
||||
if (t->index == 0)
|
||||
continue;
|
||||
|
||||
int origIndex = t->index;
|
||||
do {
|
||||
--t->index;
|
||||
// first check if current char works against the new current index
|
||||
if (c != t->str[t->index])
|
||||
continue;
|
||||
|
||||
// if it's the only char then we're good, nothing more to check
|
||||
if (t->index == 0) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we need to check the rest of the found string
|
||||
int diff = origIndex - t->index;
|
||||
size_t i;
|
||||
for (i = 0; i < t->index; ++i) {
|
||||
if (t->str[i] != t->str[i + diff])
|
||||
break;
|
||||
}
|
||||
|
||||
// if we successfully got through the previous loop then our current
|
||||
// index is good.
|
||||
if (i == t->index) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we just try the next index
|
||||
} while (t->index);
|
||||
}
|
||||
}
|
||||
// unreachable
|
||||
return -1;
|
||||
}
|
129
cpu/avr/dev/arduino/Stream.h
Normal file
129
cpu/avr/dev/arduino/Stream.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
Stream.h - base class for character-based streams.
|
||||
Copyright (c) 2010 David A. Mellis. All right 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
|
||||
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#ifndef Stream_h
|
||||
#define Stream_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
// compatability macros for testing
|
||||
/*
|
||||
#define getInt() parseInt()
|
||||
#define getInt(ignore) parseInt(ignore)
|
||||
#define getFloat() parseFloat()
|
||||
#define getFloat(ignore) parseFloat(ignore)
|
||||
#define getString( pre_string, post_string, buffer, length)
|
||||
readBytesBetween( pre_string, terminator, buffer, length)
|
||||
*/
|
||||
|
||||
// This enumeration provides the lookahead options for parseInt(), parseFloat()
|
||||
// The rules set out here are used until either the first valid character is found
|
||||
// or a time out occurs due to lack of input.
|
||||
enum LookaheadMode{
|
||||
SKIP_ALL, // All invalid characters are ignored.
|
||||
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
|
||||
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
|
||||
};
|
||||
|
||||
#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field
|
||||
|
||||
class Stream : public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
|
||||
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream() {_timeout=1000;}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
|
||||
bool find(char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target) { return find ((char *)target); }
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool find(char target) { return find (&target, 1); }
|
||||
|
||||
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
|
||||
|
||||
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
||||
|
||||
long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// lookahead determines how parseInt looks ahead in the stream.
|
||||
// See LookaheadMode enumeration at the top of the file.
|
||||
// Lookahead is terminated by the first character that is not a valid part of an integer.
|
||||
// Once parsing commences, 'ignore' will be skipped in the stream.
|
||||
|
||||
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
|
||||
// float version of parseInt
|
||||
|
||||
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
|
||||
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
|
||||
// These overload exists for compatibility with any class that has derived
|
||||
// Stream and used parseFloat/Int with a custom ignore character. To keep
|
||||
// the public API simple, these overload remains protected.
|
||||
|
||||
struct MultiTarget {
|
||||
const char *str; // string you're searching for
|
||||
size_t len; // length of string you're searching for
|
||||
size_t index; // index used by the search routine.
|
||||
};
|
||||
|
||||
// This allows you to search for an arbitrary number of strings.
|
||||
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||
int findMulti(struct MultiTarget *targets, int tCount);
|
||||
};
|
||||
|
||||
#undef NO_IGNORE_CHAR
|
||||
#endif
|
168
cpu/avr/dev/arduino/WCharacter.h
Normal file
168
cpu/avr/dev/arduino/WCharacter.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||
Copyright (c) 2010 Hernando Barragan. All right 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 Character_h
|
||||
#define Character_h
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
// WCharacter.h prototypes
|
||||
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||
inline boolean isControl(int c) __attribute__((always_inline));
|
||||
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||
inline int toAscii(int c) __attribute__((always_inline));
|
||||
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||
|
||||
|
||||
// Checks for an alphanumeric character.
|
||||
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||
inline boolean isAlphaNumeric(int c)
|
||||
{
|
||||
return ( isalnum(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an alphabetic character.
|
||||
// It is equivalent to (isupper(c) || islower(c)).
|
||||
inline boolean isAlpha(int c)
|
||||
{
|
||||
return ( isalpha(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks whether c is a 7-bit unsigned char value
|
||||
// that fits into the ASCII character set.
|
||||
inline boolean isAscii(int c)
|
||||
{
|
||||
return ( isascii (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a blank character, that is, a space or a tab.
|
||||
inline boolean isWhitespace(int c)
|
||||
{
|
||||
return ( isblank (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a control character.
|
||||
inline boolean isControl(int c)
|
||||
{
|
||||
return ( iscntrl (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a digit (0 through 9).
|
||||
inline boolean isDigit(int c)
|
||||
{
|
||||
return ( isdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character except space.
|
||||
inline boolean isGraph(int c)
|
||||
{
|
||||
return ( isgraph (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a lower-case character.
|
||||
inline boolean isLowerCase(int c)
|
||||
{
|
||||
return (islower (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character including space.
|
||||
inline boolean isPrintable(int c)
|
||||
{
|
||||
return ( isprint (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character which is not a space
|
||||
// or an alphanumeric character.
|
||||
inline boolean isPunct(int c)
|
||||
{
|
||||
return ( ispunct (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for white-space characters. For the avr-libc library,
|
||||
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||
inline boolean isSpace(int c)
|
||||
{
|
||||
return ( isspace (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an uppercase letter.
|
||||
inline boolean isUpperCase(int c)
|
||||
{
|
||||
return ( isupper (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||
// 8 9 a b c d e f A B C D E F.
|
||||
inline boolean isHexadecimalDigit(int c)
|
||||
{
|
||||
return ( isxdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Converts c to a 7-bit unsigned char value that fits into the
|
||||
// ASCII character set, by clearing the high-order bits.
|
||||
inline int toAscii(int c)
|
||||
{
|
||||
return toascii (c);
|
||||
}
|
||||
|
||||
|
||||
// Warning:
|
||||
// Many people will be unhappy if you use this function.
|
||||
// This function will convert accented letters into random
|
||||
// characters.
|
||||
|
||||
// Converts the letter c to lower case, if possible.
|
||||
inline int toLowerCase(int c)
|
||||
{
|
||||
return tolower (c);
|
||||
}
|
||||
|
||||
|
||||
// Converts the letter c to upper case, if possible.
|
||||
inline int toUpperCase(int c)
|
||||
{
|
||||
return toupper (c);
|
||||
}
|
||||
|
||||
#endif
|
58
cpu/avr/dev/arduino/WMath.cpp
Normal file
58
cpu/avr/dev/arduino/WMath.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Wiring project - http://wiring.org.co
|
||||
Copyright (c) 2004-06 Hernando Barragan
|
||||
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
|
||||
|
||||
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., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "stdlib.h"
|
||||
}
|
||||
|
||||
void randomSeed(unsigned long seed)
|
||||
{
|
||||
if (seed != 0) {
|
||||
srandom(seed);
|
||||
}
|
||||
}
|
||||
|
||||
long random(long howbig)
|
||||
{
|
||||
if (howbig == 0) {
|
||||
return 0;
|
||||
}
|
||||
return random() % howbig;
|
||||
}
|
||||
|
||||
long random(long howsmall, long howbig)
|
||||
{
|
||||
if (howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
long diff = howbig - howsmall;
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
unsigned int makeWord(unsigned int w) { return w; }
|
||||
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
|
745
cpu/avr/dev/arduino/WString.cpp
Normal file
745
cpu/avr/dev/arduino/WString.cpp
Normal file
|
@ -0,0 +1,745 @@
|
|||
/*
|
||||
WString.cpp - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
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 "WString.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Constructors */
|
||||
/*********************************************/
|
||||
|
||||
String::String(const char *cstr)
|
||||
{
|
||||
init();
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
String::String(const String &value)
|
||||
{
|
||||
init();
|
||||
*this = value;
|
||||
}
|
||||
|
||||
String::String(const __FlashStringHelper *pstr)
|
||||
{
|
||||
init();
|
||||
*this = pstr;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String::String(String &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
String::String(StringSumHelper &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
String::String(char c)
|
||||
{
|
||||
init();
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned char value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned char)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(int)];
|
||||
itoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned int)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(long)];
|
||||
ltoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned long)];
|
||||
ultoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(float value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::String(double value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Memory Management */
|
||||
/*********************************************/
|
||||
|
||||
inline void String::init(void)
|
||||
{
|
||||
buffer = NULL;
|
||||
capacity = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void String::invalidate(void)
|
||||
{
|
||||
if (buffer) free(buffer);
|
||||
buffer = NULL;
|
||||
capacity = len = 0;
|
||||
}
|
||||
|
||||
unsigned char String::reserve(unsigned int size)
|
||||
{
|
||||
if (buffer && capacity >= size) return 1;
|
||||
if (changeBuffer(size)) {
|
||||
if (len == 0) buffer[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||
{
|
||||
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||
if (newbuffer) {
|
||||
buffer = newbuffer;
|
||||
capacity = maxStrLen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Copy and Move */
|
||||
/*********************************************/
|
||||
|
||||
String & String::copy(const char *cstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy(buffer, cstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy_P(buffer, (PGM_P)pstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void String::move(String &rhs)
|
||||
{
|
||||
if (buffer) {
|
||||
if (capacity >= rhs.len) {
|
||||
strcpy(buffer, rhs.buffer);
|
||||
len = rhs.len;
|
||||
rhs.len = 0;
|
||||
return;
|
||||
} else {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
buffer = rhs.buffer;
|
||||
capacity = rhs.capacity;
|
||||
len = rhs.len;
|
||||
rhs.buffer = NULL;
|
||||
rhs.capacity = 0;
|
||||
rhs.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const String &rhs)
|
||||
{
|
||||
if (this == &rhs) return *this;
|
||||
|
||||
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & String::operator = (String &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (StringSumHelper &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const char *cstr)
|
||||
{
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (const __FlashStringHelper *pstr)
|
||||
{
|
||||
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* concat */
|
||||
/*********************************************/
|
||||
|
||||
unsigned char String::concat(const String &s)
|
||||
{
|
||||
return concat(s.buffer, s.len);
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||
{
|
||||
unsigned int newlen = len + length;
|
||||
if (!cstr) return 0;
|
||||
if (length == 0) return 1;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy(buffer + len, cstr);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr)
|
||||
{
|
||||
if (!cstr) return 0;
|
||||
return concat(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
unsigned char String::concat(char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
return concat(buf, 1);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned char num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned char)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(int num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(int)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned int num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned int)];
|
||||
utoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(long num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(long)];
|
||||
ltoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned long num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned long)];
|
||||
ultoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(float num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(double num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(const __FlashStringHelper * str)
|
||||
{
|
||||
if (!str) return 0;
|
||||
int length = strlen_P((const char *) str);
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy_P(buffer + len, (const char *) str);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Concatenate */
|
||||
/*********************************************/
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(c)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Comparison */
|
||||
/*********************************************/
|
||||
|
||||
int String::compareTo(const String &s) const
|
||||
{
|
||||
if (!buffer || !s.buffer) {
|
||||
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer, s.buffer);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const String &s2) const
|
||||
{
|
||||
return (len == s2.len && compareTo(s2) == 0);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const char *cstr) const
|
||||
{
|
||||
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||
if (cstr == NULL) return buffer[0] == 0;
|
||||
return strcmp(buffer, cstr) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||
{
|
||||
if (this == &s2) return 1;
|
||||
if (len != s2.len) return 0;
|
||||
if (len == 0) return 1;
|
||||
const char *p1 = buffer;
|
||||
const char *p2 = s2.buffer;
|
||||
while (*p1) {
|
||||
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2 ) const
|
||||
{
|
||||
if (len < s2.len) return 0;
|
||||
return startsWith(s2, 0);
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||
{
|
||||
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::endsWith( const String &s2 ) const
|
||||
{
|
||||
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Character Access */
|
||||
/*********************************************/
|
||||
|
||||
char String::charAt(unsigned int loc) const
|
||||
{
|
||||
return operator[](loc);
|
||||
}
|
||||
|
||||
void String::setCharAt(unsigned int loc, char c)
|
||||
{
|
||||
if (loc < len) buffer[loc] = c;
|
||||
}
|
||||
|
||||
char & String::operator[](unsigned int index)
|
||||
{
|
||||
static char dummy_writable_char;
|
||||
if (index >= len || !buffer) {
|
||||
dummy_writable_char = 0;
|
||||
return dummy_writable_char;
|
||||
}
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
char String::operator[]( unsigned int index ) const
|
||||
{
|
||||
if (index >= len || !buffer) return 0;
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||
{
|
||||
if (!bufsize || !buf) return;
|
||||
if (index >= len) {
|
||||
buf[0] = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int n = bufsize - 1;
|
||||
if (n > len - index) n = len - index;
|
||||
strncpy((char *)buf, buffer + index, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Search */
|
||||
/*********************************************/
|
||||
|
||||
int String::indexOf(char c) const
|
||||
{
|
||||
return indexOf(c, 0);
|
||||
}
|
||||
|
||||
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char* temp = strchr(buffer + fromIndex, ch);
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2) const
|
||||
{
|
||||
return indexOf(s2, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||
if (found == NULL) return -1;
|
||||
return found - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf( char theChar ) const
|
||||
{
|
||||
return lastIndexOf(theChar, len - 1);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
char tempchar = buffer[fromIndex + 1];
|
||||
buffer[fromIndex + 1] = '\0';
|
||||
char* temp = strrchr( buffer, ch );
|
||||
buffer[fromIndex + 1] = tempchar;
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2) const
|
||||
{
|
||||
return lastIndexOf(s2, len - s2.len);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||
if (fromIndex >= len) fromIndex = len - 1;
|
||||
int found = -1;
|
||||
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||
p = strstr(p, s2.buffer);
|
||||
if (!p) break;
|
||||
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
String String::substring(unsigned int left, unsigned int right) const
|
||||
{
|
||||
if (left > right) {
|
||||
unsigned int temp = right;
|
||||
right = left;
|
||||
left = temp;
|
||||
}
|
||||
String out;
|
||||
if (left >= len) return out;
|
||||
if (right > len) right = len;
|
||||
char temp = buffer[right]; // save the replaced character
|
||||
buffer[right] = '\0';
|
||||
out = buffer + left; // pointer arithmetic
|
||||
buffer[right] = temp; //restore character
|
||||
return out;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Modification */
|
||||
/*********************************************/
|
||||
|
||||
void String::replace(char find, char replace)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
if (*p == find) *p = replace;
|
||||
}
|
||||
}
|
||||
|
||||
void String::replace(const String& find, const String& replace)
|
||||
{
|
||||
if (len == 0 || find.len == 0) return;
|
||||
int diff = replace.len - find.len;
|
||||
char *readFrom = buffer;
|
||||
char *foundAt;
|
||||
if (diff == 0) {
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
memcpy(foundAt, replace.buffer, replace.len);
|
||||
readFrom = foundAt + replace.len;
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
char *writeTo = buffer;
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
unsigned int n = foundAt - readFrom;
|
||||
memcpy(writeTo, readFrom, n);
|
||||
writeTo += n;
|
||||
memcpy(writeTo, replace.buffer, replace.len);
|
||||
writeTo += replace.len;
|
||||
readFrom = foundAt + find.len;
|
||||
len += diff;
|
||||
}
|
||||
strcpy(writeTo, readFrom);
|
||||
} else {
|
||||
unsigned int size = len; // compute size needed for result
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
readFrom = foundAt + find.len;
|
||||
size += diff;
|
||||
}
|
||||
if (size == len) return;
|
||||
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||
int index = len - 1;
|
||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = buffer + index + find.len;
|
||||
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||
len += diff;
|
||||
buffer[len] = 0;
|
||||
memcpy(buffer + index, replace.buffer, replace.len);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index){
|
||||
// Pass the biggest integer as the count. The remove method
|
||||
// below will take care of truncating it at the end of the
|
||||
// string.
|
||||
remove(index, (unsigned int)-1);
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index, unsigned int count){
|
||||
if (index >= len) { return; }
|
||||
if (count <= 0) { return; }
|
||||
if (count > len - index) { count = len - index; }
|
||||
char *writeTo = buffer + index;
|
||||
len = len - count;
|
||||
strncpy(writeTo, buffer + index + count,len - index);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
void String::toLowerCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::toUpperCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::trim(void)
|
||||
{
|
||||
if (!buffer || len == 0) return;
|
||||
char *begin = buffer;
|
||||
while (isspace(*begin)) begin++;
|
||||
char *end = buffer + len - 1;
|
||||
while (isspace(*end) && end >= begin) end--;
|
||||
len = end + 1 - begin;
|
||||
if (begin > buffer) memcpy(buffer, begin, len);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Parsing / Conversion */
|
||||
/*********************************************/
|
||||
|
||||
long String::toInt(void) const
|
||||
{
|
||||
if (buffer) return atol(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float String::toFloat(void) const
|
||||
{
|
||||
if (buffer) return float(atof(buffer));
|
||||
return 0;
|
||||
}
|
224
cpu/avr/dev/arduino/WString.h
Normal file
224
cpu/avr/dev/arduino/WString.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
WString.h - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
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 String_class_h
|
||||
#define String_class_h
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// When compiling programs with this class, the following gcc parameters
|
||||
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||
// with little or no increase in code size.
|
||||
// -felide-constructors
|
||||
// -std=c++0x
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
class StringSumHelper;
|
||||
|
||||
// The string class
|
||||
class String
|
||||
{
|
||||
// use a function pointer to allow for "if (s)" without the
|
||||
// complications of an operator bool(). for more information, see:
|
||||
// http://www.artima.com/cppsource/safebool.html
|
||||
typedef void (String::*StringIfHelperType)() const;
|
||||
void StringIfHelper() const {}
|
||||
|
||||
public:
|
||||
// constructors
|
||||
// creates a copy of the initial value.
|
||||
// if the initial value is null or invalid, or if memory allocation
|
||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||
// be false).
|
||||
String(const char *cstr = "");
|
||||
String(const String &str);
|
||||
String(const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String(String &&rval);
|
||||
String(StringSumHelper &&rval);
|
||||
#endif
|
||||
explicit String(char c);
|
||||
explicit String(unsigned char, unsigned char base=10);
|
||||
explicit String(int, unsigned char base=10);
|
||||
explicit String(unsigned int, unsigned char base=10);
|
||||
explicit String(long, unsigned char base=10);
|
||||
explicit String(unsigned long, unsigned char base=10);
|
||||
explicit String(float, unsigned char decimalPlaces=2);
|
||||
explicit String(double, unsigned char decimalPlaces=2);
|
||||
~String(void);
|
||||
|
||||
// memory management
|
||||
// return true on success, false on failure (in which case, the string
|
||||
// is left unchanged). reserve(0), if successful, will validate an
|
||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||
unsigned char reserve(unsigned int size);
|
||||
inline unsigned int length(void) const {return len;}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
// marked as invalid ("if (s)" will be false).
|
||||
String & operator = (const String &rhs);
|
||||
String & operator = (const char *cstr);
|
||||
String & operator = (const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & operator = (String &&rval);
|
||||
String & operator = (StringSumHelper &&rval);
|
||||
#endif
|
||||
|
||||
// concatenate (works w/ built-in types)
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsucessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(char c);
|
||||
unsigned char concat(unsigned char c);
|
||||
unsigned char concat(int num);
|
||||
unsigned char concat(unsigned int num);
|
||||
unsigned char concat(long num);
|
||||
unsigned char concat(unsigned long num);
|
||||
unsigned char concat(float num);
|
||||
unsigned char concat(double num);
|
||||
unsigned char concat(const __FlashStringHelper * str);
|
||||
|
||||
// if there's not enough memory for the concatenated value, the string
|
||||
// will be left unchanged (but this isn't signalled in any way)
|
||||
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||
String & operator += (char c) {concat(c); return (*this);}
|
||||
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||
String & operator += (int num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||
String & operator += (long num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||
String & operator += (float num) {concat(num); return (*this);}
|
||||
String & operator += (double num) {concat(num); return (*this);}
|
||||
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||
|
||||
// comparison (only works w/ Strings and "strings")
|
||||
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||
int compareTo(const String &s) const;
|
||||
unsigned char equals(const String &s) const;
|
||||
unsigned char equals(const char *cstr) const;
|
||||
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
||||
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
||||
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
||||
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
||||
unsigned char operator < (const String &rhs) const;
|
||||
unsigned char operator > (const String &rhs) const;
|
||||
unsigned char operator <= (const String &rhs) const;
|
||||
unsigned char operator >= (const String &rhs) const;
|
||||
unsigned char equalsIgnoreCase(const String &s) const;
|
||||
unsigned char startsWith( const String &prefix) const;
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
|
||||
// character acccess
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [] (unsigned int index) const;
|
||||
char& operator [] (unsigned int index);
|
||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||
{getBytes((unsigned char *)buf, bufsize, index);}
|
||||
const char * c_str() const { return buffer; }
|
||||
|
||||
// search
|
||||
int indexOf( char ch ) const;
|
||||
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||
int indexOf( const String &str ) const;
|
||||
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( char ch ) const;
|
||||
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( const String &str ) const;
|
||||
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||
|
||||
// modification
|
||||
void replace(char find, char replace);
|
||||
void replace(const String& find, const String& replace);
|
||||
void remove(unsigned int index);
|
||||
void remove(unsigned int index, unsigned int count);
|
||||
void toLowerCase(void);
|
||||
void toUpperCase(void);
|
||||
void trim(void);
|
||||
|
||||
// parsing/conversion
|
||||
long toInt(void) const;
|
||||
float toFloat(void) const;
|
||||
|
||||
protected:
|
||||
char *buffer; // the actual char array
|
||||
unsigned int capacity; // the array length minus one (for the '\0')
|
||||
unsigned int len; // the String length (not counting the '\0')
|
||||
protected:
|
||||
void init(void);
|
||||
void invalidate(void);
|
||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||
unsigned char concat(const char *cstr, unsigned int length);
|
||||
|
||||
// copy and move
|
||||
String & copy(const char *cstr, unsigned int length);
|
||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void move(String &rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringSumHelper : public String
|
||||
{
|
||||
public:
|
||||
StringSumHelper(const String &s) : String(s) {}
|
||||
StringSumHelper(const char *p) : String(p) {}
|
||||
StringSumHelper(char c) : String(c) {}
|
||||
StringSumHelper(unsigned char num) : String(num) {}
|
||||
StringSumHelper(int num) : String(num) {}
|
||||
StringSumHelper(unsigned int num) : String(num) {}
|
||||
StringSumHelper(long num) : String(num) {}
|
||||
StringSumHelper(unsigned long num) : String(num) {}
|
||||
StringSumHelper(float num) : String(num) {}
|
||||
StringSumHelper(double num) : String(num) {}
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // String_class_h
|
330
cpu/avr/dev/arduino/Wire.cpp
Normal file
330
cpu/avr/dev/arduino/Wire.cpp
Normal file
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
TwoWire.cpp - TWI/I2C library for Wiring & Arduino
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "twi.h"
|
||||
}
|
||||
|
||||
#include "Wire.h"
|
||||
|
||||
// Initialize Class Variables //////////////////////////////////////////////////
|
||||
|
||||
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
|
||||
uint8_t TwoWire::rxBufferIndex = 0;
|
||||
uint8_t TwoWire::rxBufferLength = 0;
|
||||
|
||||
uint8_t TwoWire::txAddress = 0;
|
||||
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
|
||||
uint8_t TwoWire::txBufferIndex = 0;
|
||||
uint8_t TwoWire::txBufferLength = 0;
|
||||
|
||||
uint8_t TwoWire::transmitting = 0;
|
||||
void (*TwoWire::user_onRequest)(void);
|
||||
void (*TwoWire::user_onReceive)(int);
|
||||
|
||||
// Constructors ////////////////////////////////////////////////////////////////
|
||||
|
||||
TwoWire::TwoWire()
|
||||
{
|
||||
}
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
void TwoWire::begin(void)
|
||||
{
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = 0;
|
||||
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
|
||||
twi_init();
|
||||
}
|
||||
|
||||
void TwoWire::begin(uint8_t address)
|
||||
{
|
||||
twi_setAddress(address);
|
||||
twi_attachSlaveTxEvent(onRequestService);
|
||||
twi_attachSlaveRxEvent(onReceiveService);
|
||||
begin();
|
||||
}
|
||||
|
||||
void TwoWire::begin(int address)
|
||||
{
|
||||
begin((uint8_t)address);
|
||||
}
|
||||
|
||||
void TwoWire::end(void)
|
||||
{
|
||||
twi_disable();
|
||||
}
|
||||
|
||||
void TwoWire::setClock(uint32_t frequency)
|
||||
{
|
||||
TWBR = ((F_CPU / frequency) - 16) / 2;
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
|
||||
{
|
||||
if (isize > 0) {
|
||||
// send internal address; this mode allows sending a repeated start to access
|
||||
// some devices' internal registers. This function is executed by the hardware
|
||||
// TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)
|
||||
|
||||
beginTransmission(address);
|
||||
|
||||
// the maximum size of internal address is 3 bytes
|
||||
if (isize > 3){
|
||||
isize = 3;
|
||||
}
|
||||
|
||||
// write internal register address - most significant byte first
|
||||
while (isize-- > 0)
|
||||
write((uint8_t)(iaddress >> (isize*8)));
|
||||
endTransmission(false);
|
||||
}
|
||||
|
||||
// clamp to buffer length
|
||||
if(quantity > BUFFER_LENGTH){
|
||||
quantity = BUFFER_LENGTH;
|
||||
}
|
||||
// perform blocking read into buffer
|
||||
uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
|
||||
// set rx buffer iterator vars
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = read;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
|
||||
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)sendStop);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
|
||||
{
|
||||
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity)
|
||||
{
|
||||
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
|
||||
{
|
||||
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address)
|
||||
{
|
||||
// indicate that we are transmitting
|
||||
transmitting = 1;
|
||||
// set address of targeted slave
|
||||
txAddress = address;
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address)
|
||||
{
|
||||
beginTransmission((uint8_t)address);
|
||||
}
|
||||
|
||||
//
|
||||
// Originally, 'endTransmission' was an f(void) function.
|
||||
// It has been modified to take one parameter indicating
|
||||
// whether or not a STOP should be performed on the bus.
|
||||
// Calling endTransmission(false) allows a sketch to
|
||||
// perform a repeated start.
|
||||
//
|
||||
// WARNING: Nothing in the library keeps track of whether
|
||||
// the bus tenure has been properly ended with a STOP. It
|
||||
// is very possible to leave the bus in a hung state if
|
||||
// no call to endTransmission(true) is made. Some I2C
|
||||
// devices will behave oddly if they do not see a STOP.
|
||||
//
|
||||
uint8_t TwoWire::endTransmission(uint8_t sendStop)
|
||||
{
|
||||
// transmit buffer (blocking)
|
||||
int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
// indicate that we are done transmitting
|
||||
transmitting = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This provides backwards compatibility with the original
|
||||
// definition, and expected behaviour, of endTransmission
|
||||
//
|
||||
uint8_t TwoWire::endTransmission(void)
|
||||
{
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave tx event callback
|
||||
// or after beginTransmission(address)
|
||||
size_t TwoWire::write(uint8_t data)
|
||||
{
|
||||
if(transmitting){
|
||||
// in master transmitter mode
|
||||
// don't bother if buffer is full
|
||||
if(txBufferLength >= BUFFER_LENGTH){
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
// put byte in tx buffer
|
||||
txBuffer[txBufferIndex] = data;
|
||||
++txBufferIndex;
|
||||
// update amount in buffer
|
||||
txBufferLength = txBufferIndex;
|
||||
}else{
|
||||
// in slave send mode
|
||||
// reply to master
|
||||
twi_transmit(&data, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave tx event callback
|
||||
// or after beginTransmission(address)
|
||||
size_t TwoWire::write(const uint8_t *data, size_t quantity)
|
||||
{
|
||||
if(transmitting){
|
||||
// in master transmitter mode
|
||||
for(size_t i = 0; i < quantity; ++i){
|
||||
write(data[i]);
|
||||
}
|
||||
}else{
|
||||
// in slave send mode
|
||||
// reply to master
|
||||
twi_transmit(data, quantity);
|
||||
}
|
||||
return quantity;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::available(void)
|
||||
{
|
||||
return rxBufferLength - rxBufferIndex;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::read(void)
|
||||
{
|
||||
int value = -1;
|
||||
|
||||
// get each successive byte on each call
|
||||
if(rxBufferIndex < rxBufferLength){
|
||||
value = rxBuffer[rxBufferIndex];
|
||||
++rxBufferIndex;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::peek(void)
|
||||
{
|
||||
int value = -1;
|
||||
|
||||
if(rxBufferIndex < rxBufferLength){
|
||||
value = rxBuffer[rxBufferIndex];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void TwoWire::flush(void)
|
||||
{
|
||||
// XXX: to be implemented.
|
||||
}
|
||||
|
||||
// behind the scenes function that is called when data is received
|
||||
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
|
||||
{
|
||||
// don't bother if user hasn't registered a callback
|
||||
if(!user_onReceive){
|
||||
return;
|
||||
}
|
||||
// don't bother if rx buffer is in use by a master requestFrom() op
|
||||
// i know this drops data, but it allows for slight stupidity
|
||||
// meaning, they may not have read all the master requestFrom() data yet
|
||||
if(rxBufferIndex < rxBufferLength){
|
||||
return;
|
||||
}
|
||||
// copy twi rx buffer into local read buffer
|
||||
// this enables new reads to happen in parallel
|
||||
for(uint8_t i = 0; i < numBytes; ++i){
|
||||
rxBuffer[i] = inBytes[i];
|
||||
}
|
||||
// set rx iterator vars
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = numBytes;
|
||||
// alert user program
|
||||
user_onReceive(numBytes);
|
||||
}
|
||||
|
||||
// behind the scenes function that is called when data is requested
|
||||
void TwoWire::onRequestService(void)
|
||||
{
|
||||
// don't bother if user hasn't registered a callback
|
||||
if(!user_onRequest){
|
||||
return;
|
||||
}
|
||||
// reset tx buffer iterator vars
|
||||
// !!! this will kill any pending pre-master sendTo() activity
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
// alert user program
|
||||
user_onRequest();
|
||||
}
|
||||
|
||||
// sets function called on slave write
|
||||
void TwoWire::onReceive( void (*function)(int) )
|
||||
{
|
||||
user_onReceive = function;
|
||||
}
|
||||
|
||||
// sets function called on slave read
|
||||
void TwoWire::onRequest( void (*function)(void) )
|
||||
{
|
||||
user_onRequest = function;
|
||||
}
|
||||
|
||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||
|
||||
TwoWire Wire = TwoWire();
|
||||
|
85
cpu/avr/dev/arduino/Wire.h
Normal file
85
cpu/avr/dev/arduino/Wire.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
TwoWire.h - TWI/I2C library for Arduino & Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
#ifndef TwoWire_h
|
||||
#define TwoWire_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Stream.h"
|
||||
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
// WIRE_HAS_END means Wire has end()
|
||||
#define WIRE_HAS_END 1
|
||||
|
||||
class TwoWire : public Stream
|
||||
{
|
||||
private:
|
||||
static uint8_t rxBuffer[];
|
||||
static uint8_t rxBufferIndex;
|
||||
static uint8_t rxBufferLength;
|
||||
|
||||
static uint8_t txAddress;
|
||||
static uint8_t txBuffer[];
|
||||
static uint8_t txBufferIndex;
|
||||
static uint8_t txBufferLength;
|
||||
|
||||
static uint8_t transmitting;
|
||||
static void (*user_onRequest)(void);
|
||||
static void (*user_onReceive)(int);
|
||||
static void onRequestService(void);
|
||||
static void onReceiveService(uint8_t*, int);
|
||||
public:
|
||||
TwoWire();
|
||||
void begin();
|
||||
void begin(uint8_t);
|
||||
void begin(int);
|
||||
void end();
|
||||
void setClock(uint32_t);
|
||||
void beginTransmission(uint8_t);
|
||||
void beginTransmission(int);
|
||||
uint8_t endTransmission(void);
|
||||
uint8_t endTransmission(uint8_t);
|
||||
uint8_t requestFrom(uint8_t, uint8_t);
|
||||
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
|
||||
uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t);
|
||||
uint8_t requestFrom(int, int);
|
||||
uint8_t requestFrom(int, int, int);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *, size_t);
|
||||
virtual int available(void);
|
||||
virtual int read(void);
|
||||
virtual int peek(void);
|
||||
virtual void flush(void);
|
||||
void onReceive( void (*)(int) );
|
||||
void onRequest( void (*)(void) );
|
||||
|
||||
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||
inline size_t write(long n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||
inline size_t write(int n) { return write((uint8_t)n); }
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
extern TwoWire Wire;
|
||||
|
||||
#endif
|
||||
|
515
cpu/avr/dev/arduino/binary.h
Normal file
515
cpu/avr/dev/arduino/binary.h
Normal file
|
@ -0,0 +1,515 @@
|
|||
#ifndef Binary_h
|
||||
#define Binary_h
|
||||
|
||||
#define B0 0
|
||||
#define B00 0
|
||||
#define B000 0
|
||||
#define B0000 0
|
||||
#define B00000 0
|
||||
#define B000000 0
|
||||
#define B0000000 0
|
||||
#define B00000000 0
|
||||
#define B1 1
|
||||
#define B01 1
|
||||
#define B001 1
|
||||
#define B0001 1
|
||||
#define B00001 1
|
||||
#define B000001 1
|
||||
#define B0000001 1
|
||||
#define B00000001 1
|
||||
#define B10 2
|
||||
#define B010 2
|
||||
#define B0010 2
|
||||
#define B00010 2
|
||||
#define B000010 2
|
||||
#define B0000010 2
|
||||
#define B00000010 2
|
||||
#define B11 3
|
||||
#define B011 3
|
||||
#define B0011 3
|
||||
#define B00011 3
|
||||
#define B000011 3
|
||||
#define B0000011 3
|
||||
#define B00000011 3
|
||||
#define B100 4
|
||||
#define B0100 4
|
||||
#define B00100 4
|
||||
#define B000100 4
|
||||
#define B0000100 4
|
||||
#define B00000100 4
|
||||
#define B101 5
|
||||
#define B0101 5
|
||||
#define B00101 5
|
||||
#define B000101 5
|
||||
#define B0000101 5
|
||||
#define B00000101 5
|
||||
#define B110 6
|
||||
#define B0110 6
|
||||
#define B00110 6
|
||||
#define B000110 6
|
||||
#define B0000110 6
|
||||
#define B00000110 6
|
||||
#define B111 7
|
||||
#define B0111 7
|
||||
#define B00111 7
|
||||
#define B000111 7
|
||||
#define B0000111 7
|
||||
#define B00000111 7
|
||||
#define B1000 8
|
||||
#define B01000 8
|
||||
#define B001000 8
|
||||
#define B0001000 8
|
||||
#define B00001000 8
|
||||
#define B1001 9
|
||||
#define B01001 9
|
||||
#define B001001 9
|
||||
#define B0001001 9
|
||||
#define B00001001 9
|
||||
#define B1010 10
|
||||
#define B01010 10
|
||||
#define B001010 10
|
||||
#define B0001010 10
|
||||
#define B00001010 10
|
||||
#define B1011 11
|
||||
#define B01011 11
|
||||
#define B001011 11
|
||||
#define B0001011 11
|
||||
#define B00001011 11
|
||||
#define B1100 12
|
||||
#define B01100 12
|
||||
#define B001100 12
|
||||
#define B0001100 12
|
||||
#define B00001100 12
|
||||
#define B1101 13
|
||||
#define B01101 13
|
||||
#define B001101 13
|
||||
#define B0001101 13
|
||||
#define B00001101 13
|
||||
#define B1110 14
|
||||
#define B01110 14
|
||||
#define B001110 14
|
||||
#define B0001110 14
|
||||
#define B00001110 14
|
||||
#define B1111 15
|
||||
#define B01111 15
|
||||
#define B001111 15
|
||||
#define B0001111 15
|
||||
#define B00001111 15
|
||||
#define B10000 16
|
||||
#define B010000 16
|
||||
#define B0010000 16
|
||||
#define B00010000 16
|
||||
#define B10001 17
|
||||
#define B010001 17
|
||||
#define B0010001 17
|
||||
#define B00010001 17
|
||||
#define B10010 18
|
||||
#define B010010 18
|
||||
#define B0010010 18
|
||||
#define B00010010 18
|
||||
#define B10011 19
|
||||
#define B010011 19
|
||||
#define B0010011 19
|
||||
#define B00010011 19
|
||||
#define B10100 20
|
||||
#define B010100 20
|
||||
#define B0010100 20
|
||||
#define B00010100 20
|
||||
#define B10101 21
|
||||
#define B010101 21
|
||||
#define B0010101 21
|
||||
#define B00010101 21
|
||||
#define B10110 22
|
||||
#define B010110 22
|
||||
#define B0010110 22
|
||||
#define B00010110 22
|
||||
#define B10111 23
|
||||
#define B010111 23
|
||||
#define B0010111 23
|
||||
#define B00010111 23
|
||||
#define B11000 24
|
||||
#define B011000 24
|
||||
#define B0011000 24
|
||||
#define B00011000 24
|
||||
#define B11001 25
|
||||
#define B011001 25
|
||||
#define B0011001 25
|
||||
#define B00011001 25
|
||||
#define B11010 26
|
||||
#define B011010 26
|
||||
#define B0011010 26
|
||||
#define B00011010 26
|
||||
#define B11011 27
|
||||
#define B011011 27
|
||||
#define B0011011 27
|
||||
#define B00011011 27
|
||||
#define B11100 28
|
||||
#define B011100 28
|
||||
#define B0011100 28
|
||||
#define B00011100 28
|
||||
#define B11101 29
|
||||
#define B011101 29
|
||||
#define B0011101 29
|
||||
#define B00011101 29
|
||||
#define B11110 30
|
||||
#define B011110 30
|
||||
#define B0011110 30
|
||||
#define B00011110 30
|
||||
#define B11111 31
|
||||
#define B011111 31
|
||||
#define B0011111 31
|
||||
#define B00011111 31
|
||||
#define B100000 32
|
||||
#define B0100000 32
|
||||
#define B00100000 32
|
||||
#define B100001 33
|
||||
#define B0100001 33
|
||||
#define B00100001 33
|
||||
#define B100010 34
|
||||
#define B0100010 34
|
||||
#define B00100010 34
|
||||
#define B100011 35
|
||||
#define B0100011 35
|
||||
#define B00100011 35
|
||||
#define B100100 36
|
||||
#define B0100100 36
|
||||
#define B00100100 36
|
||||
#define B100101 37
|
||||
#define B0100101 37
|
||||
#define B00100101 37
|
||||
#define B100110 38
|
||||
#define B0100110 38
|
||||
#define B00100110 38
|
||||
#define B100111 39
|
||||
#define B0100111 39
|
||||
#define B00100111 39
|
||||
#define B101000 40
|
||||
#define B0101000 40
|
||||
#define B00101000 40
|
||||
#define B101001 41
|
||||
#define B0101001 41
|
||||
#define B00101001 41
|
||||
#define B101010 42
|
||||
#define B0101010 42
|
||||
#define B00101010 42
|
||||
#define B101011 43
|
||||
#define B0101011 43
|
||||
#define B00101011 43
|
||||
#define B101100 44
|
||||
#define B0101100 44
|
||||
#define B00101100 44
|
||||
#define B101101 45
|
||||
#define B0101101 45
|
||||
#define B00101101 45
|
||||
#define B101110 46
|
||||
#define B0101110 46
|
||||
#define B00101110 46
|
||||
#define B101111 47
|
||||
#define B0101111 47
|
||||
#define B00101111 47
|
||||
#define B110000 48
|
||||
#define B0110000 48
|
||||
#define B00110000 48
|
||||
#define B110001 49
|
||||
#define B0110001 49
|
||||
#define B00110001 49
|
||||
#define B110010 50
|
||||
#define B0110010 50
|
||||
#define B00110010 50
|
||||
#define B110011 51
|
||||
#define B0110011 51
|
||||
#define B00110011 51
|
||||
#define B110100 52
|
||||
#define B0110100 52
|
||||
#define B00110100 52
|
||||
#define B110101 53
|
||||
#define B0110101 53
|
||||
#define B00110101 53
|
||||
#define B110110 54
|
||||
#define B0110110 54
|
||||
#define B00110110 54
|
||||
#define B110111 55
|
||||
#define B0110111 55
|
||||
#define B00110111 55
|
||||
#define B111000 56
|
||||
#define B0111000 56
|
||||
#define B00111000 56
|
||||
#define B111001 57
|
||||
#define B0111001 57
|
||||
#define B00111001 57
|
||||
#define B111010 58
|
||||
#define B0111010 58
|
||||
#define B00111010 58
|
||||
#define B111011 59
|
||||
#define B0111011 59
|
||||
#define B00111011 59
|
||||
#define B111100 60
|
||||
#define B0111100 60
|
||||
#define B00111100 60
|
||||
#define B111101 61
|
||||
#define B0111101 61
|
||||
#define B00111101 61
|
||||
#define B111110 62
|
||||
#define B0111110 62
|
||||
#define B00111110 62
|
||||
#define B111111 63
|
||||
#define B0111111 63
|
||||
#define B00111111 63
|
||||
#define B1000000 64
|
||||
#define B01000000 64
|
||||
#define B1000001 65
|
||||
#define B01000001 65
|
||||
#define B1000010 66
|
||||
#define B01000010 66
|
||||
#define B1000011 67
|
||||
#define B01000011 67
|
||||
#define B1000100 68
|
||||
#define B01000100 68
|
||||
#define B1000101 69
|
||||
#define B01000101 69
|
||||
#define B1000110 70
|
||||
#define B01000110 70
|
||||
#define B1000111 71
|
||||
#define B01000111 71
|
||||
#define B1001000 72
|
||||
#define B01001000 72
|
||||
#define B1001001 73
|
||||
#define B01001001 73
|
||||
#define B1001010 74
|
||||
#define B01001010 74
|
||||
#define B1001011 75
|
||||
#define B01001011 75
|
||||
#define B1001100 76
|
||||
#define B01001100 76
|
||||
#define B1001101 77
|
||||
#define B01001101 77
|
||||
#define B1001110 78
|
||||
#define B01001110 78
|
||||
#define B1001111 79
|
||||
#define B01001111 79
|
||||
#define B1010000 80
|
||||
#define B01010000 80
|
||||
#define B1010001 81
|
||||
#define B01010001 81
|
||||
#define B1010010 82
|
||||
#define B01010010 82
|
||||
#define B1010011 83
|
||||
#define B01010011 83
|
||||
#define B1010100 84
|
||||
#define B01010100 84
|
||||
#define B1010101 85
|
||||
#define B01010101 85
|
||||
#define B1010110 86
|
||||
#define B01010110 86
|
||||
#define B1010111 87
|
||||
#define B01010111 87
|
||||
#define B1011000 88
|
||||
#define B01011000 88
|
||||
#define B1011001 89
|
||||
#define B01011001 89
|
||||
#define B1011010 90
|
||||
#define B01011010 90
|
||||
#define B1011011 91
|
||||
#define B01011011 91
|
||||
#define B1011100 92
|
||||
#define B01011100 92
|
||||
#define B1011101 93
|
||||
#define B01011101 93
|
||||
#define B1011110 94
|
||||
#define B01011110 94
|
||||
#define B1011111 95
|
||||
#define B01011111 95
|
||||
#define B1100000 96
|
||||
#define B01100000 96
|
||||
#define B1100001 97
|
||||
#define B01100001 97
|
||||
#define B1100010 98
|
||||
#define B01100010 98
|
||||
#define B1100011 99
|
||||
#define B01100011 99
|
||||
#define B1100100 100
|
||||
#define B01100100 100
|
||||
#define B1100101 101
|
||||
#define B01100101 101
|
||||
#define B1100110 102
|
||||
#define B01100110 102
|
||||
#define B1100111 103
|
||||
#define B01100111 103
|
||||
#define B1101000 104
|
||||
#define B01101000 104
|
||||
#define B1101001 105
|
||||
#define B01101001 105
|
||||
#define B1101010 106
|
||||
#define B01101010 106
|
||||
#define B1101011 107
|
||||
#define B01101011 107
|
||||
#define B1101100 108
|
||||
#define B01101100 108
|
||||
#define B1101101 109
|
||||
#define B01101101 109
|
||||
#define B1101110 110
|
||||
#define B01101110 110
|
||||
#define B1101111 111
|
||||
#define B01101111 111
|
||||
#define B1110000 112
|
||||
#define B01110000 112
|
||||
#define B1110001 113
|
||||
#define B01110001 113
|
||||
#define B1110010 114
|
||||
#define B01110010 114
|
||||
#define B1110011 115
|
||||
#define B01110011 115
|
||||
#define B1110100 116
|
||||
#define B01110100 116
|
||||
#define B1110101 117
|
||||
#define B01110101 117
|
||||
#define B1110110 118
|
||||
#define B01110110 118
|
||||
#define B1110111 119
|
||||
#define B01110111 119
|
||||
#define B1111000 120
|
||||
#define B01111000 120
|
||||
#define B1111001 121
|
||||
#define B01111001 121
|
||||
#define B1111010 122
|
||||
#define B01111010 122
|
||||
#define B1111011 123
|
||||
#define B01111011 123
|
||||
#define B1111100 124
|
||||
#define B01111100 124
|
||||
#define B1111101 125
|
||||
#define B01111101 125
|
||||
#define B1111110 126
|
||||
#define B01111110 126
|
||||
#define B1111111 127
|
||||
#define B01111111 127
|
||||
#define B10000000 128
|
||||
#define B10000001 129
|
||||
#define B10000010 130
|
||||
#define B10000011 131
|
||||
#define B10000100 132
|
||||
#define B10000101 133
|
||||
#define B10000110 134
|
||||
#define B10000111 135
|
||||
#define B10001000 136
|
||||
#define B10001001 137
|
||||
#define B10001010 138
|
||||
#define B10001011 139
|
||||
#define B10001100 140
|
||||
#define B10001101 141
|
||||
#define B10001110 142
|
||||
#define B10001111 143
|
||||
#define B10010000 144
|
||||
#define B10010001 145
|
||||
#define B10010010 146
|
||||
#define B10010011 147
|
||||
#define B10010100 148
|
||||
#define B10010101 149
|
||||
#define B10010110 150
|
||||
#define B10010111 151
|
||||
#define B10011000 152
|
||||
#define B10011001 153
|
||||
#define B10011010 154
|
||||
#define B10011011 155
|
||||
#define B10011100 156
|
||||
#define B10011101 157
|
||||
#define B10011110 158
|
||||
#define B10011111 159
|
||||
#define B10100000 160
|
||||
#define B10100001 161
|
||||
#define B10100010 162
|
||||
#define B10100011 163
|
||||
#define B10100100 164
|
||||
#define B10100101 165
|
||||
#define B10100110 166
|
||||
#define B10100111 167
|
||||
#define B10101000 168
|
||||
#define B10101001 169
|
||||
#define B10101010 170
|
||||
#define B10101011 171
|
||||
#define B10101100 172
|
||||
#define B10101101 173
|
||||
#define B10101110 174
|
||||
#define B10101111 175
|
||||
#define B10110000 176
|
||||
#define B10110001 177
|
||||
#define B10110010 178
|
||||
#define B10110011 179
|
||||
#define B10110100 180
|
||||
#define B10110101 181
|
||||
#define B10110110 182
|
||||
#define B10110111 183
|
||||
#define B10111000 184
|
||||
#define B10111001 185
|
||||
#define B10111010 186
|
||||
#define B10111011 187
|
||||
#define B10111100 188
|
||||
#define B10111101 189
|
||||
#define B10111110 190
|
||||
#define B10111111 191
|
||||
#define B11000000 192
|
||||
#define B11000001 193
|
||||
#define B11000010 194
|
||||
#define B11000011 195
|
||||
#define B11000100 196
|
||||
#define B11000101 197
|
||||
#define B11000110 198
|
||||
#define B11000111 199
|
||||
#define B11001000 200
|
||||
#define B11001001 201
|
||||
#define B11001010 202
|
||||
#define B11001011 203
|
||||
#define B11001100 204
|
||||
#define B11001101 205
|
||||
#define B11001110 206
|
||||
#define B11001111 207
|
||||
#define B11010000 208
|
||||
#define B11010001 209
|
||||
#define B11010010 210
|
||||
#define B11010011 211
|
||||
#define B11010100 212
|
||||
#define B11010101 213
|
||||
#define B11010110 214
|
||||
#define B11010111 215
|
||||
#define B11011000 216
|
||||
#define B11011001 217
|
||||
#define B11011010 218
|
||||
#define B11011011 219
|
||||
#define B11011100 220
|
||||
#define B11011101 221
|
||||
#define B11011110 222
|
||||
#define B11011111 223
|
||||
#define B11100000 224
|
||||
#define B11100001 225
|
||||
#define B11100010 226
|
||||
#define B11100011 227
|
||||
#define B11100100 228
|
||||
#define B11100101 229
|
||||
#define B11100110 230
|
||||
#define B11100111 231
|
||||
#define B11101000 232
|
||||
#define B11101001 233
|
||||
#define B11101010 234
|
||||
#define B11101011 235
|
||||
#define B11101100 236
|
||||
#define B11101101 237
|
||||
#define B11101110 238
|
||||
#define B11101111 239
|
||||
#define B11110000 240
|
||||
#define B11110001 241
|
||||
#define B11110010 242
|
||||
#define B11110011 243
|
||||
#define B11110100 244
|
||||
#define B11110101 245
|
||||
#define B11110110 246
|
||||
#define B11110111 247
|
||||
#define B11111000 248
|
||||
#define B11111001 249
|
||||
#define B11111010 250
|
||||
#define B11111011 251
|
||||
#define B11111100 252
|
||||
#define B11111101 253
|
||||
#define B11111110 254
|
||||
#define B11111111 255
|
||||
|
||||
#endif
|
83
cpu/avr/dev/arduino/hw-arduino.h
Normal file
83
cpu/avr/dev/arduino/hw-arduino.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Ralf Schlatterbeck Open Source Consulting
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup compatibility Arduino - Contiki
|
||||
*
|
||||
* This defines contiki-compatible hardware definitions for running
|
||||
* arduino sketches (or just to call arduino-compatible function).
|
||||
* For now only for osd hardware, a similar file should exist for each
|
||||
* arduino-compatible hardware.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for arduino compatibility
|
||||
* \author
|
||||
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#include "contiki.h"
|
||||
|
||||
/*
|
||||
* The OSD hardware only supports timer 3 for PWM, timer 2 is used by
|
||||
* contiki for sleep/wakeup timing and is not usable for PWM.
|
||||
*/
|
||||
#define digitalPinToTimer(pin) \
|
||||
( (pin) == 2 \
|
||||
? TIMER3A \
|
||||
: ( (pin) == 3 \
|
||||
? TIMER3B \
|
||||
: ((pin == 4) ? TIMER3C : NOT_ON_TIMER) \
|
||||
) \
|
||||
)
|
||||
|
||||
/* Only init timer 3 with phase correct pwm 8-bit and prescaler 64 */
|
||||
#define arduino_pwm_timer_init() \
|
||||
(hwtimer_ini (3, HWT_WGM_PWM_PHASE_8_BIT, HWT_CLOCK_PRESCALER_64, 0))
|
||||
|
||||
/*
|
||||
* VI settings, see coding style
|
||||
* ex:ts=8:et:sw=2
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
/** @} */
|
36
cpu/avr/dev/arduino/new.cpp
Normal file
36
cpu/avr/dev/arduino/new.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright (c) 2014 Arduino. All right 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 <stdlib.h>
|
||||
|
||||
void *operator new(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void * ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
30
cpu/avr/dev/arduino/new.h
Normal file
30
cpu/avr/dev/arduino/new.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
Copyright (c) 2014 Arduino. All right 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 NEW_H
|
||||
#define NEW_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void * operator new(size_t size);
|
||||
void * operator new[](size_t size);
|
||||
void operator delete(void * ptr);
|
||||
void operator delete[](void * ptr);
|
||||
|
||||
#endif
|
||||
|
545
cpu/avr/dev/arduino/twi.c
Normal file
545
cpu/avr/dev/arduino/twi.c
Normal file
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
twi.c - TWI/I2C library for Wiring & Arduino
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <compat/twi.h>
|
||||
#include "Arduino.h" // for digitalWrite
|
||||
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
#include "pins_arduino.h"
|
||||
#include "twi.h"
|
||||
|
||||
static volatile uint8_t twi_state;
|
||||
static volatile uint8_t twi_slarw;
|
||||
static volatile uint8_t twi_sendStop; // should the transaction end with a stop
|
||||
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
|
||||
|
||||
static void (*twi_onSlaveTransmit)(void);
|
||||
static void (*twi_onSlaveReceive)(uint8_t*, int);
|
||||
|
||||
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
|
||||
static volatile uint8_t twi_masterBufferIndex;
|
||||
static volatile uint8_t twi_masterBufferLength;
|
||||
|
||||
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
static volatile uint8_t twi_txBufferIndex;
|
||||
static volatile uint8_t twi_txBufferLength;
|
||||
|
||||
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
|
||||
static volatile uint8_t twi_rxBufferIndex;
|
||||
|
||||
static volatile uint8_t twi_error;
|
||||
|
||||
/*
|
||||
* Function twi_init
|
||||
* Desc readys twi pins and sets twi bitrate
|
||||
* Input none
|
||||
* Output none
|
||||
*/
|
||||
void twi_init(void)
|
||||
{
|
||||
// initialize state
|
||||
twi_state = TWI_READY;
|
||||
twi_sendStop = true; // default value
|
||||
twi_inRepStart = false;
|
||||
|
||||
// activate internal pullups for twi.
|
||||
digitalWrite(SDA, 1);
|
||||
digitalWrite(SCL, 1);
|
||||
|
||||
// initialize twi prescaler and bit rate
|
||||
cbi(TWSR, TWPS0);
|
||||
cbi(TWSR, TWPS1);
|
||||
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
|
||||
|
||||
/* twi bit rate formula from atmega128 manual pg 204
|
||||
SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||
note: TWBR should be 10 or higher for master mode
|
||||
It is 72 for a 16mhz Wiring board with 100kHz TWI */
|
||||
|
||||
// enable twi module, acks, and twi interrupt
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_disable
|
||||
* Desc disables twi pins
|
||||
* Input none
|
||||
* Output none
|
||||
*/
|
||||
void twi_disable(void)
|
||||
{
|
||||
// disable twi module, acks, and twi interrupt
|
||||
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
|
||||
|
||||
// deactivate internal pullups for twi.
|
||||
digitalWrite(SDA, 0);
|
||||
digitalWrite(SCL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_slaveInit
|
||||
* Desc sets slave address and enables interrupt
|
||||
* Input none
|
||||
* Output none
|
||||
*/
|
||||
void twi_setAddress(uint8_t address)
|
||||
{
|
||||
// set twi slave address (skip over TWGCE bit)
|
||||
TWAR = address << 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_readFrom
|
||||
* Desc attempts to become twi bus master and read a
|
||||
* series of bytes from a device on the bus
|
||||
* Input address: 7bit i2c device address
|
||||
* data: pointer to byte array
|
||||
* length: number of bytes to read into array
|
||||
* sendStop: Boolean indicating whether to send a stop at the end
|
||||
* Output number of bytes read
|
||||
*/
|
||||
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
// ensure data will fit into buffer
|
||||
if(TWI_BUFFER_LENGTH < length){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// wait until twi is ready, become master receiver
|
||||
while(TWI_READY != twi_state){
|
||||
continue;
|
||||
}
|
||||
twi_state = TWI_MRX;
|
||||
twi_sendStop = sendStop;
|
||||
// reset error state (0xFF.. no error occured)
|
||||
twi_error = 0xFF;
|
||||
|
||||
// initialize buffer iteration vars
|
||||
twi_masterBufferIndex = 0;
|
||||
twi_masterBufferLength = length-1; // This is not intuitive, read on...
|
||||
// On receive, the previously configured ACK/NACK setting is transmitted in
|
||||
// response to the received byte before the interrupt is signalled.
|
||||
// Therefor we must actually set NACK when the _next_ to last byte is
|
||||
// received, causing that NACK to be sent in response to receiving the last
|
||||
// expected byte of data.
|
||||
|
||||
// build sla+w, slave device address + w bit
|
||||
twi_slarw = TW_READ;
|
||||
twi_slarw |= address << 1;
|
||||
|
||||
if (true == twi_inRepStart) {
|
||||
// if we're in the repeated start state, then we've already sent the start,
|
||||
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
|
||||
// We need to remove ourselves from the repeated start state before we enable interrupts,
|
||||
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
|
||||
// up. Also, don't enable the START interrupt. There may be one pending from the
|
||||
// repeated start that we sent outselves, and that would really confuse things.
|
||||
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
|
||||
do {
|
||||
TWDR = twi_slarw;
|
||||
} while(TWCR & _BV(TWWC));
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
|
||||
}
|
||||
else
|
||||
// send start condition
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
|
||||
|
||||
// wait for read operation to complete
|
||||
while(TWI_MRX == twi_state){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (twi_masterBufferIndex < length)
|
||||
length = twi_masterBufferIndex;
|
||||
|
||||
// copy twi buffer to data
|
||||
for(i = 0; i < length; ++i){
|
||||
data[i] = twi_masterBuffer[i];
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_writeTo
|
||||
* Desc attempts to become twi bus master and write a
|
||||
* series of bytes to a device on the bus
|
||||
* Input address: 7bit i2c device address
|
||||
* data: pointer to byte array
|
||||
* length: number of bytes in array
|
||||
* wait: boolean indicating to wait for write or not
|
||||
* sendStop: boolean indicating whether or not to send a stop at the end
|
||||
* Output 0 .. success
|
||||
* 1 .. length to long for buffer
|
||||
* 2 .. address send, NACK received
|
||||
* 3 .. data send, NACK received
|
||||
* 4 .. other twi error (lost bus arbitration, bus error, ..)
|
||||
*/
|
||||
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
// ensure data will fit into buffer
|
||||
if(TWI_BUFFER_LENGTH < length){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// wait until twi is ready, become master transmitter
|
||||
while(TWI_READY != twi_state){
|
||||
continue;
|
||||
}
|
||||
twi_state = TWI_MTX;
|
||||
twi_sendStop = sendStop;
|
||||
// reset error state (0xFF.. no error occured)
|
||||
twi_error = 0xFF;
|
||||
|
||||
// initialize buffer iteration vars
|
||||
twi_masterBufferIndex = 0;
|
||||
twi_masterBufferLength = length;
|
||||
|
||||
// copy data to twi buffer
|
||||
for(i = 0; i < length; ++i){
|
||||
twi_masterBuffer[i] = data[i];
|
||||
}
|
||||
|
||||
// build sla+w, slave device address + w bit
|
||||
twi_slarw = TW_WRITE;
|
||||
twi_slarw |= address << 1;
|
||||
|
||||
// if we're in a repeated start, then we've already sent the START
|
||||
// in the ISR. Don't do it again.
|
||||
//
|
||||
if (true == twi_inRepStart) {
|
||||
// if we're in the repeated start state, then we've already sent the start,
|
||||
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
|
||||
// We need to remove ourselves from the repeated start state before we enable interrupts,
|
||||
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
|
||||
// up. Also, don't enable the START interrupt. There may be one pending from the
|
||||
// repeated start that we sent outselves, and that would really confuse things.
|
||||
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
|
||||
do {
|
||||
TWDR = twi_slarw;
|
||||
} while(TWCR & _BV(TWWC));
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
|
||||
}
|
||||
else
|
||||
// send start condition
|
||||
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
|
||||
|
||||
// wait for write operation to complete
|
||||
while(wait && (TWI_MTX == twi_state)){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (twi_error == 0xFF)
|
||||
return 0; // success
|
||||
else if (twi_error == TW_MT_SLA_NACK)
|
||||
return 2; // error: address send, nack received
|
||||
else if (twi_error == TW_MT_DATA_NACK)
|
||||
return 3; // error: data send, nack received
|
||||
else
|
||||
return 4; // other twi error
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_transmit
|
||||
* Desc fills slave tx buffer with data
|
||||
* must be called in slave tx event callback
|
||||
* Input data: pointer to byte array
|
||||
* length: number of bytes in array
|
||||
* Output 1 length too long for buffer
|
||||
* 2 not slave transmitter
|
||||
* 0 ok
|
||||
*/
|
||||
uint8_t twi_transmit(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
// ensure data will fit into buffer
|
||||
if(TWI_BUFFER_LENGTH < length){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ensure we are currently a slave transmitter
|
||||
if(TWI_STX != twi_state){
|
||||
return 2;
|
||||
}
|
||||
|
||||
// set length and copy data into tx buffer
|
||||
twi_txBufferLength = length;
|
||||
for(i = 0; i < length; ++i){
|
||||
twi_txBuffer[i] = data[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_attachSlaveRxEvent
|
||||
* Desc sets function called before a slave read operation
|
||||
* Input function: callback function to use
|
||||
* Output none
|
||||
*/
|
||||
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) )
|
||||
{
|
||||
twi_onSlaveReceive = function;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_attachSlaveTxEvent
|
||||
* Desc sets function called before a slave write operation
|
||||
* Input function: callback function to use
|
||||
* Output none
|
||||
*/
|
||||
void twi_attachSlaveTxEvent( void (*function)(void) )
|
||||
{
|
||||
twi_onSlaveTransmit = function;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_reply
|
||||
* Desc sends byte or readys receive line
|
||||
* Input ack: byte indicating to ack or to nack
|
||||
* Output none
|
||||
*/
|
||||
void twi_reply(uint8_t ack)
|
||||
{
|
||||
// transmit master read ready signal, with or without ack
|
||||
if(ack){
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
|
||||
}else{
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_stop
|
||||
* Desc relinquishes bus master status
|
||||
* Input none
|
||||
* Output none
|
||||
*/
|
||||
void twi_stop(void)
|
||||
{
|
||||
// send stop condition
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
|
||||
|
||||
// wait for stop condition to be exectued on bus
|
||||
// TWINT is not set after a stop condition!
|
||||
while(TWCR & _BV(TWSTO)){
|
||||
continue;
|
||||
}
|
||||
|
||||
// update twi state
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function twi_releaseBus
|
||||
* Desc releases bus control
|
||||
* Input none
|
||||
* Output none
|
||||
*/
|
||||
void twi_releaseBus(void)
|
||||
{
|
||||
// release bus
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
|
||||
|
||||
// update twi state
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
|
||||
ISR(TWI_vect)
|
||||
{
|
||||
switch(TW_STATUS){
|
||||
// All Master
|
||||
case TW_START: // sent start condition
|
||||
case TW_REP_START: // sent repeated start condition
|
||||
// copy device address and r/w bit to output register and ack
|
||||
TWDR = twi_slarw;
|
||||
twi_reply(1);
|
||||
break;
|
||||
|
||||
// Master Transmitter
|
||||
case TW_MT_SLA_ACK: // slave receiver acked address
|
||||
case TW_MT_DATA_ACK: // slave receiver acked data
|
||||
// if there is data to send, send it, otherwise stop
|
||||
if(twi_masterBufferIndex < twi_masterBufferLength){
|
||||
// copy data to output register and ack
|
||||
TWDR = twi_masterBuffer[twi_masterBufferIndex++];
|
||||
twi_reply(1);
|
||||
}else{
|
||||
if (twi_sendStop)
|
||||
twi_stop();
|
||||
else {
|
||||
twi_inRepStart = true; // we're gonna send the START
|
||||
// don't enable the interrupt. We'll generate the start, but we
|
||||
// avoid handling the interrupt until we're in the next transaction,
|
||||
// at the point where we would normally issue the start.
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TW_MT_SLA_NACK: // address sent, nack received
|
||||
twi_error = TW_MT_SLA_NACK;
|
||||
twi_stop();
|
||||
break;
|
||||
case TW_MT_DATA_NACK: // data sent, nack received
|
||||
twi_error = TW_MT_DATA_NACK;
|
||||
twi_stop();
|
||||
break;
|
||||
case TW_MT_ARB_LOST: // lost bus arbitration
|
||||
twi_error = TW_MT_ARB_LOST;
|
||||
twi_releaseBus();
|
||||
break;
|
||||
|
||||
// Master Receiver
|
||||
case TW_MR_DATA_ACK: // data received, ack sent
|
||||
// put byte into buffer
|
||||
twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
|
||||
case TW_MR_SLA_ACK: // address sent, ack received
|
||||
// ack if more bytes are expected, otherwise nack
|
||||
if(twi_masterBufferIndex < twi_masterBufferLength){
|
||||
twi_reply(1);
|
||||
}else{
|
||||
twi_reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_MR_DATA_NACK: // data received, nack sent
|
||||
// put final byte into buffer
|
||||
twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
|
||||
if (twi_sendStop)
|
||||
twi_stop();
|
||||
else {
|
||||
twi_inRepStart = true; // we're gonna send the START
|
||||
// don't enable the interrupt. We'll generate the start, but we
|
||||
// avoid handling the interrupt until we're in the next transaction,
|
||||
// at the point where we would normally issue the start.
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
break;
|
||||
case TW_MR_SLA_NACK: // address sent, nack received
|
||||
twi_stop();
|
||||
break;
|
||||
// TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case
|
||||
|
||||
// Slave Receiver
|
||||
case TW_SR_SLA_ACK: // addressed, returned ack
|
||||
case TW_SR_GCALL_ACK: // addressed generally, returned ack
|
||||
case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
|
||||
// enter slave receiver mode
|
||||
twi_state = TWI_SRX;
|
||||
// indicate that rx buffer can be overwritten and ack
|
||||
twi_rxBufferIndex = 0;
|
||||
twi_reply(1);
|
||||
break;
|
||||
case TW_SR_DATA_ACK: // data received, returned ack
|
||||
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
|
||||
// if there is still room in the rx buffer
|
||||
if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
|
||||
// put byte in buffer and ack
|
||||
twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
|
||||
twi_reply(1);
|
||||
}else{
|
||||
// otherwise nack
|
||||
twi_reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_SR_STOP: // stop or repeated start condition received
|
||||
// ack future responses and leave slave receiver state
|
||||
twi_releaseBus();
|
||||
// put a null char after data if there's room
|
||||
if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
|
||||
twi_rxBuffer[twi_rxBufferIndex] = '\0';
|
||||
}
|
||||
// callback to user defined callback
|
||||
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
|
||||
// since we submit rx buffer to "wire" library, we can reset it
|
||||
twi_rxBufferIndex = 0;
|
||||
break;
|
||||
case TW_SR_DATA_NACK: // data received, returned nack
|
||||
case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
|
||||
// nack back at master
|
||||
twi_reply(0);
|
||||
break;
|
||||
|
||||
// Slave Transmitter
|
||||
case TW_ST_SLA_ACK: // addressed, returned ack
|
||||
case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
|
||||
// enter slave transmitter mode
|
||||
twi_state = TWI_STX;
|
||||
// ready the tx buffer index for iteration
|
||||
twi_txBufferIndex = 0;
|
||||
// set tx buffer length to be zero, to verify if user changes it
|
||||
twi_txBufferLength = 0;
|
||||
// request for txBuffer to be filled and length to be set
|
||||
// note: user must call twi_transmit(bytes, length) to do this
|
||||
twi_onSlaveTransmit();
|
||||
// if they didn't change buffer & length, initialize it
|
||||
if(0 == twi_txBufferLength){
|
||||
twi_txBufferLength = 1;
|
||||
twi_txBuffer[0] = 0x00;
|
||||
}
|
||||
// transmit first byte from buffer, fall
|
||||
case TW_ST_DATA_ACK: // byte sent, ack returned
|
||||
// copy data to output register
|
||||
TWDR = twi_txBuffer[twi_txBufferIndex++];
|
||||
// if there is more to send, ack, otherwise nack
|
||||
if(twi_txBufferIndex < twi_txBufferLength){
|
||||
twi_reply(1);
|
||||
}else{
|
||||
twi_reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_ST_DATA_NACK: // received nack, we are done
|
||||
case TW_ST_LAST_DATA: // received ack, but we are done already!
|
||||
// ack future responses
|
||||
twi_reply(1);
|
||||
// leave slave receiver state
|
||||
twi_state = TWI_READY;
|
||||
break;
|
||||
|
||||
// All
|
||||
case TW_NO_INFO: // no state information
|
||||
break;
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
twi_error = TW_BUS_ERROR;
|
||||
twi_stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
54
cpu/avr/dev/arduino/twi.h
Normal file
54
cpu/avr/dev/arduino/twi.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
twi.h - TWI/I2C library for Wiring & Arduino
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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 twi_h
|
||||
#define twi_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
//#define ATMEGA8
|
||||
|
||||
#ifndef TWI_FREQ
|
||||
#define TWI_FREQ 100000L
|
||||
#endif
|
||||
|
||||
#ifndef TWI_BUFFER_LENGTH
|
||||
#define TWI_BUFFER_LENGTH 32
|
||||
#endif
|
||||
|
||||
#define TWI_READY 0
|
||||
#define TWI_MRX 1
|
||||
#define TWI_MTX 2
|
||||
#define TWI_SRX 3
|
||||
#define TWI_STX 4
|
||||
|
||||
void twi_init(void);
|
||||
void twi_disable(void);
|
||||
void twi_setAddress(uint8_t);
|
||||
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
|
||||
uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
|
||||
uint8_t twi_transmit(const uint8_t*, uint8_t);
|
||||
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
|
||||
void twi_attachSlaveTxEvent( void (*)(void) );
|
||||
void twi_reply(uint8_t);
|
||||
void twi_stop(void);
|
||||
void twi_releaseBus(void);
|
||||
|
||||
#endif
|
||||
|
104
cpu/avr/dev/arduino/wiring_digital.c
Normal file
104
cpu/avr/dev/arduino/wiring_digital.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
wiring_digital.c - digital input and output functions
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
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., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
|
||||
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||
*/
|
||||
|
||||
#define ARDUINO_MAIN
|
||||
#include "wiring_private.h"
|
||||
#include "pins_arduino.h"
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
uint8_t bit = digitalPinToBitMask(pin);
|
||||
uint8_t port = digitalPinToPort(pin);
|
||||
volatile uint8_t *reg, *out;
|
||||
|
||||
if (port == NOT_A_PIN) return;
|
||||
|
||||
// JWS: can I let the optimizer do this?
|
||||
reg = portModeRegister(port);
|
||||
out = portOutputRegister(port);
|
||||
|
||||
if (mode == INPUT) {
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
*reg &= ~bit;
|
||||
*out &= ~bit;
|
||||
SREG = oldSREG;
|
||||
} else if (mode == INPUT_PULLUP) {
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
*reg &= ~bit;
|
||||
*out |= bit;
|
||||
SREG = oldSREG;
|
||||
} else {
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
*reg |= bit;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
uint8_t timer = digitalPinToTimer(pin);
|
||||
uint8_t bit = digitalPinToBitMask(pin);
|
||||
uint8_t port = digitalPinToPort(pin);
|
||||
volatile uint8_t *out;
|
||||
|
||||
if (port == NOT_A_PIN) return;
|
||||
|
||||
// If the pin that support PWM output, we need to turn it off
|
||||
// before doing a digital write.
|
||||
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
|
||||
|
||||
out = portOutputRegister(port);
|
||||
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
|
||||
if (val == LOW) {
|
||||
*out &= ~bit;
|
||||
} else {
|
||||
*out |= bit;
|
||||
}
|
||||
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
int digitalRead(uint8_t pin)
|
||||
{
|
||||
uint8_t timer = digitalPinToTimer(pin);
|
||||
uint8_t bit = digitalPinToBitMask(pin);
|
||||
uint8_t port = digitalPinToPort(pin);
|
||||
|
||||
if (port == NOT_A_PIN) return LOW;
|
||||
|
||||
// If the pin that support PWM output, we need to turn it off
|
||||
// before getting a digital reading.
|
||||
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
|
||||
|
||||
if (*portInputRegister(port) & bit) return HIGH;
|
||||
return LOW;
|
||||
}
|
69
cpu/avr/dev/arduino/wiring_private.h
Normal file
69
cpu/avr/dev/arduino/wiring_private.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
wiring_private.h - Internal header file.
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
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., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
|
||||
*/
|
||||
|
||||
#ifndef WiringPrivate_h
|
||||
#define WiringPrivate_h
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
#define EXTERNAL_INT_0 0
|
||||
#define EXTERNAL_INT_1 1
|
||||
#define EXTERNAL_INT_2 2
|
||||
#define EXTERNAL_INT_3 3
|
||||
#define EXTERNAL_INT_4 4
|
||||
#define EXTERNAL_INT_5 5
|
||||
#define EXTERNAL_INT_6 6
|
||||
#define EXTERNAL_INT_7 7
|
||||
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define EXTERNAL_NUM_INTERRUPTS 8
|
||||
#elif defined(__AVR_ATmega128RFA1__)
|
||||
#define EXTERNAL_NUM_INTERRUPTS 8
|
||||
#else
|
||||
#define EXTERNAL_NUM_INTERRUPTS 2
|
||||
#endif
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
55
cpu/avr/dev/batmon.c
Normal file
55
cpu/avr/dev/batmon.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "contiki.h"
|
||||
#include "batmon.h"
|
||||
#include <util/delay.h>
|
||||
|
||||
|
||||
|
||||
|
||||
int8_t batmon_init()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t batmon_get_voltage(uint16_t* voltage)
|
||||
{
|
||||
uint16_t volt = 0;
|
||||
uint16_t resolution = 75;
|
||||
uint16_t offset = 2550;
|
||||
int8_t ctr = 0;
|
||||
|
||||
BATMON = 0 | _BV(BATMON_HR);
|
||||
_delay_us(2);
|
||||
|
||||
if(BATMON & _BV(BATMON_OK))
|
||||
{
|
||||
// voltage above 2.550 V
|
||||
resolution = 75;
|
||||
offset = 2550;
|
||||
for(ctr=15; ctr>=0; ctr--)
|
||||
{
|
||||
BATMON = (BATMON & 0xF0) | (ctr);
|
||||
_delay_us(2);
|
||||
if(BATMON & _BV(BATMON_OK)) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// voltage below 2.550 V
|
||||
resolution = 50;
|
||||
offset = 1700;
|
||||
|
||||
BATMON &= ~_BV(BATMON_HR);
|
||||
|
||||
for(ctr=15; ctr>=0; ctr--)
|
||||
{
|
||||
BATMON = (BATMON & 0xF0) | (ctr);
|
||||
_delay_us(2);
|
||||
if(BATMON & _BV(BATMON_OK)) break;
|
||||
}
|
||||
}
|
||||
|
||||
volt = resolution*ctr+offset;
|
||||
*voltage=volt;
|
||||
|
||||
return 0;
|
||||
}
|
8
cpu/avr/dev/batmon.h
Normal file
8
cpu/avr/dev/batmon.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef BATMON_H_
|
||||
#define BATMON_H_
|
||||
|
||||
int8_t batmon_init();
|
||||
int8_t batmon_get_voltage(uint16_t* voltage);
|
||||
|
||||
|
||||
#endif /* BATMON_H_ */
|
90
cpu/avr/dev/battery-sensor.c
Normal file
90
cpu/avr/dev/battery-sensor.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2012, BinaryLabs.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: battery-sensor.h,v 1.1 2012/08/25 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Battery sensor file for Atmega128rfa1.
|
||||
* \author
|
||||
* Paulo Louro <paulolouro@binarylabs.dk>
|
||||
* Harald Pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
*The atmel rf23x radios have a low voltage detector that can be configured in units of 75 millivolts. Here is example *code for the ATmega128rfa1, where the BATMON register is in extended io space [dak664]
|
||||
*/
|
||||
|
||||
#include "dev/battery-sensor.h"
|
||||
#include "dev/batmon.h"
|
||||
|
||||
const struct sensors_sensor battery_sensor;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \return Voltage on battery measurement with BATMON register.
|
||||
*/
|
||||
static int
|
||||
value(int type)
|
||||
{
|
||||
|
||||
uint16_t h;
|
||||
/*
|
||||
uint8_t p1;
|
||||
BATMON = 16; //give BATMON time to stabilize at highest range and lowest voltage
|
||||
|
||||
// Bandgap can't be measured against supply voltage in this chip.
|
||||
// Use BATMON register instead
|
||||
for ( p1=16; p1<31; p1++) {
|
||||
BATMON = p1;
|
||||
clock_delay_usec(100); // delay needed !!
|
||||
if ((BATMON&(1<<BATMON_OK))==0) break;
|
||||
}
|
||||
h=2550-75*16-75+75*p1; //-75 to take the floor of the 75 mv transition window
|
||||
*/
|
||||
batmon_get_voltage(&h);
|
||||
return h;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
configure(int type, int c)
|
||||
{
|
||||
// No configuration needed. readADC() handles all the config needed.
|
||||
batmon_init();
|
||||
return type == SENSORS_ACTIVE;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
status(int type)
|
||||
{
|
||||
// analog sensors are always ready
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
SENSORS_SENSOR(battery_sensor, BATTERY_SENSOR, value, configure, status);
|
48
cpu/avr/dev/battery-sensor.h
Normal file
48
cpu/avr/dev/battery-sensor.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2012, BinaryLabs.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: battery-sensor.h,v 1.1 2012/08/25 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Battery sensor header file for Atmega128rfa1.
|
||||
* \author
|
||||
* Paulo Louro <paulolouro@binarylabs.dk>
|
||||
*/
|
||||
|
||||
#ifndef __BATTERY_SENSOR_H__
|
||||
#define __BATTERY_SENSOR_H__
|
||||
|
||||
#include "lib/sensors.h"
|
||||
|
||||
extern const struct sensors_sensor battery_sensor;
|
||||
|
||||
#define BATTERY_SENSOR "Battery"
|
||||
|
||||
#endif /* __BATTERY_SENSOR_H__ */
|
88
cpu/avr/dev/button-sensor.c
Normal file
88
cpu/avr/dev/button-sensor.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* Sensor routine */
|
||||
|
||||
#include "lib/sensors.h"
|
||||
#include "dev/button-sensor.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include "led.h" // debug
|
||||
|
||||
const struct sensors_sensor button_sensor;
|
||||
|
||||
static struct timer debouncetimer;
|
||||
static int status(int type);
|
||||
static int enabled = 0;
|
||||
volatile static int bstate;
|
||||
volatile static int bstatei;
|
||||
struct sensors_sensor *sensors[1];
|
||||
unsigned char sensors_flags[1];
|
||||
|
||||
#define BUTTON_BIT INTF4
|
||||
#define BUTTON_CHECK_IRQ() (EIFR & BUTTON_BIT) ? 0 : 1
|
||||
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
ISR(INT4_vect)
|
||||
{
|
||||
if(BUTTON_CHECK_IRQ()) {
|
||||
bstatei = (PINE & _BV(PE4) ? 0 : 1);
|
||||
if(timer_expired(&debouncetimer)) {
|
||||
// led1_on();
|
||||
timer_set(&debouncetimer, CLOCK_SECOND / 16);
|
||||
bstate = (PINE & _BV(PE4) ? 0 : 1);
|
||||
if(bstate == bstatei){
|
||||
sensors_changed(&button_sensor);
|
||||
}
|
||||
// led1_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
value(int type)
|
||||
{
|
||||
//return (PINE & _BV(PE4) ? 0 : 1) || !timer_expired(&debouncetimer);
|
||||
|
||||
return bstate;
|
||||
}
|
||||
|
||||
static int
|
||||
configure(int type, int c)
|
||||
{
|
||||
switch (type) {
|
||||
case SENSORS_ACTIVE:
|
||||
if (c) {
|
||||
if(!status(SENSORS_ACTIVE)) {
|
||||
// led1_on();
|
||||
timer_set(&debouncetimer, 0);
|
||||
DDRE |= (0<<DDE4); // Set pin as input
|
||||
PORTE |= (1<<PORTE4); // Set port PORTE bint 5 with pullup resistor
|
||||
EICRB |= (1<<ISC40); // For falling edge
|
||||
EIMSK |= (1<<INT4); // Set int
|
||||
enabled = 1;
|
||||
sei();
|
||||
// led1_off();
|
||||
}
|
||||
} else {
|
||||
enabled = 0;
|
||||
EIMSK &= ~(1<<INT4); // clear int
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
status(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case SENSORS_ACTIVE:
|
||||
case SENSORS_READY:
|
||||
return enabled;//(EIMSK & (1<<INT5) ? 0 : 1);//BUTTON_IRQ_ENABLED();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SENSORS_SENSOR(button_sensor, BUTTON_SENSOR,
|
||||
value, configure, status);
|
||||
|
|
@ -371,13 +371,13 @@ volatile static uint8_t osccalhigh,osccallow;
|
|||
if (seconds < 60) { //give a minute to stabilize
|
||||
if(++lockcount >= 8192UL*128/RTIMER_ARCH_SECOND) {
|
||||
lockcount=0;
|
||||
rtimer_phase = TCNT3 & 0x0fff;
|
||||
rtimer_phase = PLAT_TCNT & 0x0fff;
|
||||
if (seconds < 2) OSCCAL=100;
|
||||
if (last_phase > rtimer_phase) osccalhigh=++OSCCAL; else osccallow=--OSCCAL;
|
||||
last_phase = rtimer_phase;
|
||||
}
|
||||
} else {
|
||||
uint8_t error = (TCNT3 - last_phase) & 0x3f;
|
||||
uint8_t error = (PLAT_TCNT - last_phase) & 0x3f;
|
||||
if (error == 0) {
|
||||
} else if (error<32) {
|
||||
OSCCAL=osccallow-1;
|
||||
|
|
125
cpu/avr/dev/dht11.c
Normal file
125
cpu/avr/dev/dht11.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
DHT-11 Library
|
||||
(c) Created by Charalampos Andrianakis on 18/12/11.
|
||||
|
||||
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 <avr/io.h>
|
||||
#include "contiki.h"
|
||||
#include "dht11.h"
|
||||
#include "led.h" // debug
|
||||
|
||||
#define udelay(u) clock_delay_usec(u)
|
||||
#define mdelay(u) clock_delay_msec(u)
|
||||
|
||||
// todo: set DHT22 or DHT11 in project file
|
||||
// define for DHT11 else for DHT22, RHT03
|
||||
// #define DHT11 1
|
||||
|
||||
uint8_t DHT_Read_Data(uint16_t *temperature, uint16_t *humidity){
|
||||
|
||||
//data[5] is 8byte table where data come from DHT are stored
|
||||
//laststate holds laststate value
|
||||
//counter is used to count microSeconds
|
||||
uint8_t data[5], laststate = 0, counter = 0, j = 0, i = 0;
|
||||
|
||||
//Clear array
|
||||
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
|
||||
|
||||
uint8_t volatile sreg;
|
||||
sreg = SREG; /* Save status register before disabling interrupts. */
|
||||
cli(); /* Disable interrupts. */
|
||||
|
||||
//Set pin Output
|
||||
//Pin High
|
||||
DHT_DRIVE();
|
||||
mdelay(100); //Wait for 100mS
|
||||
|
||||
//Send Request Signal
|
||||
//Pin Low
|
||||
OUTP_0(); //20ms Low
|
||||
mdelay(20);
|
||||
//Pin High
|
||||
OUTP_1();
|
||||
udelay(40); //40us High
|
||||
|
||||
//Set pin Input to read Bus
|
||||
//Set pin Input
|
||||
DHT_RELEASE();
|
||||
laststate=DHT_INP(); //Read Pin value
|
||||
|
||||
//Repeat for each Transistions
|
||||
for (i=0; i<MAXTIMINGS; i++) {
|
||||
//While state is the same count microseconds
|
||||
//led1_on();
|
||||
//led1_off();
|
||||
|
||||
while (laststate==DHT_INP()) {
|
||||
udelay(1);
|
||||
counter++;
|
||||
if (counter>254) break;
|
||||
}
|
||||
|
||||
if (counter>254) break;
|
||||
|
||||
//laststate==_BV(DHT_PIN) checks if laststate was High
|
||||
//ignore the first 2 transitions which are the DHT Response
|
||||
//if (laststate==_BV(DHT_PIN) && (i > 2)) {
|
||||
if ((i&0x01) && (i > 2)) {
|
||||
//Save bits in segments of bytes
|
||||
//Shift data[] value 1 position left
|
||||
//Example. 01010100 if we shift it left one time it will be
|
||||
//10101000
|
||||
|
||||
data[j/8]<<=1;
|
||||
if (counter >= 15) { //If it was high for more than 40uS
|
||||
//led1_on();
|
||||
data[j/8]|=1; //it means it is bit '1' so make a logic
|
||||
//led1_off();
|
||||
} //OR with the value (save it)
|
||||
j++; //making an OR by 1 to this value 10101000
|
||||
} //we will have the resault 10101001
|
||||
//1 in 8-bit binary is 00000001
|
||||
//j/8 changes table record every 8 bits which means a byte has been saved
|
||||
//so change to next record. 0/8=0 1/8=0 ... 7/8=0 8/8=1 ... 15/8=1 16/8=2
|
||||
laststate=DHT_INP(); //save current state
|
||||
counter=0; //reset counter
|
||||
|
||||
}
|
||||
SREG = sreg; /* Enable interrupts. */
|
||||
//printf("HUM %d %d %d %d %d %d",data[0],data[1],data[2],data[3],data[4],(uint8_t)(data[0] + data[1] + data[2] + data[3]) );
|
||||
//Check if data received are correct by checking the CheckSum
|
||||
if ((uint8_t)(data[0] + data[1] + data[2] + data[3]) == data[4]) {
|
||||
#ifdef DHT11
|
||||
*humidity = data[0]*100;
|
||||
*temperature = data[2]*100;
|
||||
#else
|
||||
*humidity = ((uint16_t)data[0]<<8 | data[1])*10;
|
||||
*temperature = ((uint16_t)data[2]<<8 | data[3])*10;
|
||||
#endif
|
||||
return 0;
|
||||
}else{
|
||||
*humidity = 2;
|
||||
*temperature = 2;
|
||||
// uart_puts("\r\nCheck Sum Error");
|
||||
}
|
||||
|
||||
return 0xff; // Check Sum Error
|
||||
}
|
67
cpu/avr/dev/dht11.h
Normal file
67
cpu/avr/dev/dht11.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
DHT-11 Library
|
||||
(c) Created by Charalampos Andrianakis on 18/12/11.
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
/* DHT 1-wire is at PortE.6 */
|
||||
#define DHT_PIN_READ PINE
|
||||
#define DHT_PIN_MASK _BV(PE6)
|
||||
#define DHT_PxOUT PORTE
|
||||
#define DHT_PxDIR DDRE
|
||||
|
||||
#define SET_PIN_INPUT() (DHT_PxDIR &= ~DHT_PIN_MASK)
|
||||
#define SET_PIN_OUTPUT() (DHT_PxDIR |= DHT_PIN_MASK)
|
||||
|
||||
#define OUTP_0() (DHT_PxOUT &= ~DHT_PIN_MASK)
|
||||
#define OUTP_1() (DHT_PxOUT |= DHT_PIN_MASK)
|
||||
|
||||
#define PIN_INIT() do{ \
|
||||
SET_PIN_INPUT(); \
|
||||
OUTP_0(); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Drive the one wire interface hight */
|
||||
#define DHT_DRIVE() do { \
|
||||
SET_PIN_OUTPUT(); \
|
||||
OUTP_1(); \
|
||||
} while (0)
|
||||
|
||||
/* Release the one wire by turning on the internal pull-up. */
|
||||
#define DHT_RELEASE() do { \
|
||||
SET_PIN_INPUT(); \
|
||||
OUTP_1(); \
|
||||
} while (0)
|
||||
|
||||
/* Read one bit. */
|
||||
#define DHT_INP() (DHT_PIN_READ & DHT_PIN_MASK)
|
||||
|
||||
//The packet size is 40bit but each bit consists of low and high state
|
||||
//so 40 x 2 = 80 transitions. Also we have 2 transistions DHT response
|
||||
//and 2 transitions which indicates End Of Frame. In total 84
|
||||
#define MAXTIMINGS 84
|
||||
|
||||
//This is the main function which requests and reads the packet
|
||||
uint8_t DHT_Read_Data(uint16_t *temperature, uint16_t *humidity);
|
291
cpu/avr/dev/ds1820.c
Normal file
291
cpu/avr/dev/ds1820.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* @(#)$Id: ds1820.c,v 1.5 2010/08/25 18:35:52 nifi Exp $
|
||||
*/
|
||||
/*
|
||||
* Device driver for the Dallas Semiconductor DS1820 chip. Heavily
|
||||
* based on the application note 126 "1-Wire Communications Through
|
||||
* Software".
|
||||
*
|
||||
* http://www.maxim-ic.com/appnotes.cfm/appnote_number/126
|
||||
*/
|
||||
|
||||
/*
|
||||
* For now we stuff in Moteiv Corporation's unique OUI.
|
||||
* From http://www.ethereal.com/distribution/manuf.txt:
|
||||
* 00:12:75 Moteiv # Moteiv Corporation
|
||||
*
|
||||
* The EUI-64 is a concatenation of the 24-bit OUI value assigned by
|
||||
* the IEEE Registration Authority and a 40-bit extension identifier
|
||||
* assigned by the organization with that OUI assignment.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <string.h>
|
||||
#include "contiki.h"
|
||||
#include "ds1820.h"
|
||||
|
||||
|
||||
unsigned char ds1820_id[8];
|
||||
unsigned char ds1820_ok[8];
|
||||
|
||||
/* 1-wire is at PortE.3 */
|
||||
#define SERIAL_ID_PIN_READ PINE
|
||||
//#define SERIAL_ID_PIN_MASK _BV(PE3)
|
||||
#define SERIAL_ID_PIN_MASK _BV(PE4)
|
||||
#define SERIAL_ID_PxOUT PORTE
|
||||
#define SERIAL_ID_PxDIR DDRE
|
||||
|
||||
#define SET_PIN_INPUT() (SERIAL_ID_PxDIR &= ~SERIAL_ID_PIN_MASK)
|
||||
#define SET_PIN_OUTPUT() (SERIAL_ID_PxDIR |= SERIAL_ID_PIN_MASK)
|
||||
|
||||
#define OUTP_0() (SERIAL_ID_PxOUT &= ~SERIAL_ID_PIN_MASK)
|
||||
#define OUTP_1() (SERIAL_ID_PxOUT |= SERIAL_ID_PIN_MASK)
|
||||
|
||||
#define PIN_INIT() do{ \
|
||||
SET_PIN_INPUT(); \
|
||||
OUTP_0(); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Drive the one wire interface low */
|
||||
#define OW_DRIVE() do { \
|
||||
SET_PIN_OUTPUT(); \
|
||||
OUTP_0(); \
|
||||
} while (0)
|
||||
|
||||
/* Release the one wire by turning on the internal pull-up. */
|
||||
#define OW_RELEASE() do { \
|
||||
SET_PIN_INPUT(); \
|
||||
OUTP_1(); \
|
||||
} while (0)
|
||||
|
||||
/* Read one bit. */
|
||||
#define INP() (SERIAL_ID_PIN_READ & SERIAL_ID_PIN_MASK)
|
||||
|
||||
|
||||
/*
|
||||
* Delay times in us.
|
||||
*/
|
||||
#define tA 6 /* min-5, recommended-6, max-15 */
|
||||
#define tB 64 /* min-59, recommended-64, max-N/A */
|
||||
#define tC 60 /* min-60, recommended-60, max-120 */
|
||||
#define tD 10 /* min-5.3, recommended-10, max-N/A */
|
||||
#define tE 9 /* min-0.3, recommended-9, max-9.3 */
|
||||
#define tF 55 /* min-50, recommended-55, max-N/A */
|
||||
#define tG 0 /* min-0, recommended-0, max-0 */
|
||||
#define tH 480 /* min-480, recommended-480, max-640 */
|
||||
#define tI 70 /* min-60.3, recommended-70, max-75.3 */
|
||||
#define tJ 410 /* min-410, recommended-410, max-N/A */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define udelay(u) clock_delay_usec(u)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
owreset(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
OW_DRIVE();
|
||||
udelay(tH); /* 480 < tH < 640 */
|
||||
OW_RELEASE(); /* Releases the bus */
|
||||
udelay(tI);
|
||||
result = INP();
|
||||
udelay(tJ);
|
||||
return result;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
owwriteb(unsigned byte)
|
||||
{
|
||||
int i = 7;
|
||||
|
||||
do {
|
||||
if(byte & 0x01) {
|
||||
OW_DRIVE();
|
||||
udelay(tA);
|
||||
OW_RELEASE(); /* Releases the bus */
|
||||
udelay(tB);
|
||||
} else {
|
||||
OW_DRIVE();
|
||||
udelay(tC);
|
||||
OW_RELEASE(); /* Releases the bus */
|
||||
udelay(tD);
|
||||
}
|
||||
if(i == 0) {
|
||||
return;
|
||||
}
|
||||
i--;
|
||||
byte >>= 1;
|
||||
} while(1);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static unsigned
|
||||
owreadb(void)
|
||||
{
|
||||
unsigned result = 0;
|
||||
int i = 7;
|
||||
|
||||
do {
|
||||
OW_DRIVE();
|
||||
udelay(tA);
|
||||
OW_RELEASE(); /* Releases the bus */
|
||||
udelay(tE);
|
||||
if (INP()){
|
||||
result |= 0x80; /* LSbit first */
|
||||
}
|
||||
udelay(tF);
|
||||
if(i == 0) {
|
||||
return result;
|
||||
}
|
||||
i--;
|
||||
result >>= 1;
|
||||
} while(1);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Polynomial ^8 + ^5 + ^4 + 1 */
|
||||
static unsigned
|
||||
crc8_add(unsigned acc, unsigned byte)
|
||||
{
|
||||
int i;
|
||||
acc ^= byte;
|
||||
for(i = 0; i < 8; i++) {
|
||||
if(acc & 1) {
|
||||
acc = (acc >> 1) ^ 0x8c;
|
||||
} else {
|
||||
acc >>= 1;
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
ds1820_init()
|
||||
{
|
||||
int i;
|
||||
unsigned family, crc, acc;
|
||||
|
||||
PIN_INIT();
|
||||
|
||||
if(owreset() == 0) { /* Something pulled down 1-wire. */
|
||||
|
||||
owwriteb(0x33); /* Read ROM command. */
|
||||
family = owreadb();
|
||||
/* We receive 6 bytes in the reverse order, LSbyte first. */
|
||||
for(i = 7; i >= 2; i--) {
|
||||
ds1820_id[i] = owreadb();
|
||||
}
|
||||
crc = owreadb();
|
||||
|
||||
/* Verify family DS1820 and that CRC match. */
|
||||
if(family != 0x10) {
|
||||
goto fail;
|
||||
}
|
||||
acc = crc8_add(0x0, family);
|
||||
for(i = 7; i >= 2; i--) {
|
||||
acc = crc8_add(acc, ds1820_id[i]);
|
||||
}
|
||||
if(acc == crc) {
|
||||
ds1820_id[0] = 0x00;
|
||||
ds1820_id[1] = 0x00;
|
||||
ds1820_id[2] = 0x00;
|
||||
return 1; /* Success! */
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
|
||||
fail:
|
||||
memset(ds1820_id, 0x0, sizeof(ds1820_id));
|
||||
return 0; /* Fail! */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
ds1820_temp()
|
||||
{
|
||||
ds1820_convert();
|
||||
// wait max 750ms pin lo
|
||||
clock_wait(CLOCK_SECOND);
|
||||
ds1820_read();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ds1820_convert()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
PIN_INIT();
|
||||
for(i=0;i<3;i++){
|
||||
if(owreset() == 0) { /* Something pulled down 1-wire. */
|
||||
owwriteb(0xCC); /* Skip ROM command. */
|
||||
owwriteb(0x44); /* Convert T command. */
|
||||
OW_RELEASE(); /* Releases the bus */
|
||||
return 1;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
return 0; /* Fail! */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
ds1820_read()
|
||||
{
|
||||
int i;
|
||||
unsigned crc, acc;
|
||||
|
||||
if(owreset() == 0) { /* Something pulled down 1-wire. */
|
||||
owwriteb(0xCC); /* Skip ROM command. */
|
||||
owwriteb(0xBE); /* Read Scratchpad command. */
|
||||
/* We receive 8 bytes in the reverse order, LSbyte first. */
|
||||
for(i = 0; i < 8; i++) {
|
||||
ds1820_id[i] = owreadb();
|
||||
}
|
||||
crc = owreadb();
|
||||
|
||||
acc=0;
|
||||
for(i = 0; i < 8; i++) {
|
||||
acc = crc8_add(acc, ds1820_id[i]);
|
||||
}
|
||||
if(acc == crc) {
|
||||
// store temp
|
||||
for(i = 0; i < 8; i++) {
|
||||
ds1820_ok[i]=ds1820_id[i];
|
||||
}
|
||||
return 1; /* Success! */
|
||||
} else {
|
||||
return 0; /* Fail! */
|
||||
}
|
||||
} else {
|
||||
return 0; /* Fail! */
|
||||
}
|
||||
return 1; /* Fail! */
|
||||
}
|
45
cpu/avr/dev/ds1820.h
Normal file
45
cpu/avr/dev/ds1820.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* @(#)$Id: ds1820.h,v 1.1 2006/06/17 22:41:16 adamdunkels Exp $
|
||||
*/
|
||||
/* -*- C -*- */
|
||||
/* @(#)$Id: ds1820.h,v 1.1 2006/06/17 22:41:16 adamdunkels Exp $ */
|
||||
|
||||
#ifndef DS1820_H
|
||||
#define DS1820_H
|
||||
|
||||
extern unsigned char ds1820_id[8];
|
||||
extern unsigned char ds1820_ok[8];
|
||||
extern int ds1820_init();
|
||||
extern int ds1820_convert();
|
||||
extern int ds1820_read();
|
||||
extern int ds1820_temp();
|
||||
#endif /* DS1820_H */
|
391
cpu/avr/dev/i2c.c
Normal file
391
cpu/avr/dev/i2c.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Ingo Gulyas Intembsys
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* I2C driver for ATMEGA128rfa1
|
||||
*
|
||||
* \author
|
||||
* Ingo Gulyas Intembsys
|
||||
* office@intembsys.at
|
||||
* www.intembsys.at
|
||||
*/
|
||||
|
||||
|
||||
#include "i2c.h"
|
||||
#include "contiki-conf.h"
|
||||
#include <stdint.h>
|
||||
#include <avr/power.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if I2C_TD != 0
|
||||
#include <stdio.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "system_mgmt.h"
|
||||
#define PRINTD(FORMAT,args...) {sleep_acquire_lock(); printf_P(PSTR(FORMAT),##args); sleep_release_lock();}
|
||||
#else
|
||||
#define PRINTD(...)
|
||||
#endif
|
||||
|
||||
#if WITH_RTDEBUG == 1
|
||||
#include "rtdebug.h"
|
||||
#define RTDEBUG_PUSH(x) rtdebug_push(x)
|
||||
#else
|
||||
#warning "I2C Driver compiling without RTDEBUG!"
|
||||
#define RTDEBUG_PUSH(x)
|
||||
#endif
|
||||
|
||||
#ifndef TIMEOUT_TIMER
|
||||
#warning "I2C Driver compiling without TIMEOUT!"
|
||||
#endif
|
||||
|
||||
|
||||
static int8_t wait_job();
|
||||
static int8_t wait_stop();
|
||||
|
||||
static int8_t i2c_ioctl(const i2c_driver* const me, uint8_t cmd, uint8_t arg);
|
||||
static int8_t i2c_read(const i2c_driver* const me, uint8_t cmd_flags, uint8_t* buffer, uint8_t len);
|
||||
static int8_t i2c_write(const i2c_driver* const me, uint8_t cmd_flags, const uint8_t* data, uint8_t len);
|
||||
|
||||
|
||||
// static linkage of member functions
|
||||
i2c_driver i2c_drv = {i2c_ioctl, i2c_read, i2c_write};
|
||||
// lock spi if driver opened to prevent further opening access
|
||||
static volatile bool i2c_lock = false;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// global functions
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
i2c_driver* i2c_open(void)
|
||||
{
|
||||
if(i2c_lock == true)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_OPEN__DEVICE_BUSY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i2c_lock = true;
|
||||
power_twi_enable();
|
||||
I2C_INIT();
|
||||
|
||||
TWBR = I2C_FREQ_STANDARD;
|
||||
TWSR &= ~((1<<TWPS1) | (1<<TWPS0));
|
||||
TWSR |= (1<<TWPS0);
|
||||
TWCR = (1<<TWEN);
|
||||
|
||||
return &i2c_drv;
|
||||
}
|
||||
|
||||
void i2c_close(i2c_driver* const me)
|
||||
{
|
||||
if(me == NULL || i2c_lock == false)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_CLOSE__NO_DEVICE);
|
||||
return;
|
||||
}
|
||||
|
||||
i2c_reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void i2c_reset(void)
|
||||
{
|
||||
TWCR &= ~(1<<TWEN);
|
||||
I2C_DEINIT();
|
||||
power_twi_disable();
|
||||
i2c_lock = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// local helper functions
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TIMEOUT_TIMER
|
||||
static int8_t wait_job()
|
||||
{
|
||||
int8_t status = I2C_OK;
|
||||
uint16_t timeout = TIMEOUT_TIMER_NOW_ADD(I2C_TIMEOUT);
|
||||
|
||||
|
||||
while (!(TWCR & (1<<TWINT)))
|
||||
{
|
||||
if(!(TIMEOUT_TIMER_LT(TIMEOUT_TIMER_NOW(), timeout)))
|
||||
{
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int8_t wait_stop()
|
||||
{
|
||||
int8_t status = I2C_OK;
|
||||
uint16_t timeout = TIMEOUT_TIMER_NOW_ADD(I2C_TIMEOUT);
|
||||
|
||||
|
||||
while (TWCR & (1<<TWSTO))
|
||||
{
|
||||
if(!(TIMEOUT_TIMER_LT(TIMEOUT_TIMER_NOW(), timeout)))
|
||||
{
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
static int8_t wait_job()
|
||||
{
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
return I2C_OK;
|
||||
}
|
||||
|
||||
static int8_t wait_stop()
|
||||
{
|
||||
while (TWCR & (1<<TWSTO));
|
||||
return I2C_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// member functions
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
static int8_t i2c_ioctl(const i2c_driver* const me, uint8_t cmd, uint8_t arg)
|
||||
{
|
||||
if(me == NULL || i2c_lock == false)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_IOCTL__DEVICE_CLOSED);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
if(cmd == I2C_IOCTL_CMD_SET_FREQ)
|
||||
{
|
||||
switch(arg)
|
||||
{
|
||||
case I2C_FREQ_400KHZ: TWBR = I2C_FREQ_400KHZ; break;
|
||||
case I2C_FREQ_250KHZ: TWBR = I2C_FREQ_250KHZ; break;
|
||||
case I2C_FREQ_100KHZ: TWBR = I2C_FREQ_100KHZ; break;
|
||||
case I2C_FREQ_50KHZ: TWBR = I2C_FREQ_50KHZ; break;
|
||||
case I2C_FREQ_10KHZ: TWBR = I2C_FREQ_10KHZ; break;
|
||||
default:
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_IOCTL__ARG_INVALID);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_IOCTL__CMD_INVALID);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
return I2C_OK;
|
||||
}
|
||||
|
||||
static int8_t i2c_read(const i2c_driver* const me, uint8_t cmd_flags, uint8_t* buffer, uint8_t len)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
int8_t status = I2C_OK;
|
||||
|
||||
|
||||
if(me == NULL || i2c_lock == false)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__DEVICE_CLOSED);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
if((len > 0) && (buffer == NULL))
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__ERROR_NULLPOINTER);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(cmd_flags & I2C_CMD_FLAG_START)
|
||||
{
|
||||
I2C_START();
|
||||
if(wait_job() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__START_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if((I2C_STATUS() != I2C_STATUS_START) && (I2C_STATUS() != I2C_STATUS_START_REP))
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__START_ERROR);
|
||||
status = I2C_ERROR_START;
|
||||
break;
|
||||
}
|
||||
PRINTD("I2C-RD-START\n");
|
||||
}
|
||||
|
||||
if(len == 0) break;
|
||||
|
||||
for(i=0; i<(len-1); i++)
|
||||
{
|
||||
I2C_READ_BYTE_ACK();
|
||||
if(wait_job() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_ACK_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if(I2C_STATUS() != I2C_STATUS_DATAR_ACK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_ACK_ERROR);
|
||||
status = I2C_ERROR_READ;
|
||||
break;
|
||||
}
|
||||
buffer[i] = I2C_RX_REG;
|
||||
PRINTD("I2C-RD-RACK: 0x%02X\n", buffer[i]);
|
||||
}
|
||||
|
||||
I2C_READ_BYTE_NACK();
|
||||
if(wait_job() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_NACK_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if(I2C_STATUS() != I2C_STATUS_DATAR_NACK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_NACK_ERROR);
|
||||
status = I2C_ERROR_READ;
|
||||
break;
|
||||
}
|
||||
buffer[i] = I2C_RX_REG;
|
||||
PRINTD("I2C-RD-RNACK: 0x%02X\n", buffer[i]);
|
||||
|
||||
} while (0);
|
||||
|
||||
if(cmd_flags & I2C_CMD_FLAG_STOP)
|
||||
{
|
||||
I2C_STOP();
|
||||
if(wait_stop() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__STOP_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
}
|
||||
PRINTD("I2C-RD_STOP\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int8_t i2c_write(const i2c_driver* const me, uint8_t cmd_flags, const uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
int8_t status = I2C_OK;
|
||||
|
||||
|
||||
if(me == NULL || i2c_lock == false)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__DEVICE_CLOSED);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
if((len > 0) && (data == NULL))
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__ERROR_NULLPOINTER);
|
||||
return I2C_ERROR_DRIVER;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(cmd_flags & I2C_CMD_FLAG_START)
|
||||
{
|
||||
I2C_START();
|
||||
if(wait_job() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__START_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if((I2C_STATUS() != I2C_STATUS_START) && (I2C_STATUS() != I2C_STATUS_START_REP))
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__START_ERROR);
|
||||
status = I2C_ERROR_START;
|
||||
break;
|
||||
}
|
||||
PRINTD("I2C-WR-START\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for(i=0; i<len; i++)
|
||||
{
|
||||
I2C_TX_REG = data[i];
|
||||
I2C_WRITE_BYTE();
|
||||
if(wait_job() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__WRITE_BYTE_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if((I2C_STATUS() != I2C_STATUS_DATAW_ACK) && (I2C_STATUS() != I2C_STATUS_SLAW_ACK) && (I2C_STATUS() != I2C_STATUS_SLAR_ACK))
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__WRITE_BYTE_ERROR);
|
||||
status = I2C_ERROR_WRITE;
|
||||
break;
|
||||
}
|
||||
PRINTD("I2C-WR-BYTE: 0x%02X\n", data[i]);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if(cmd_flags & I2C_CMD_FLAG_STOP)
|
||||
{
|
||||
I2C_STOP();
|
||||
if(wait_stop() != I2C_OK)
|
||||
{
|
||||
RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__STOP_TIMEOUT);
|
||||
status = I2C_ERROR_TIMEOUT;
|
||||
}
|
||||
PRINTD("I2C-WR-STOP\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
131
cpu/avr/dev/i2c.h
Normal file
131
cpu/avr/dev/i2c.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Ingo Gulyas Intembsys
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* I2C driver for ATMEGA128rfa1
|
||||
*
|
||||
* \author
|
||||
* Ingo Gulyas Intembsys
|
||||
* office@intembsys.at
|
||||
* www.intembsys.at
|
||||
*/
|
||||
|
||||
|
||||
#ifndef I2C_H_
|
||||
#define I2C_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CONFIGURATION SECTION:
|
||||
|
||||
#define I2C_TD 0 // compiler switch: i2c testdriver code
|
||||
|
||||
#define I2C_PORT PORTD
|
||||
#define I2C_DDR DDRD
|
||||
#define I2C_SCL_PIN 0
|
||||
#define I2C_SDA_PIN 1
|
||||
|
||||
// END OF CONFIGURATION SECTION
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define I2C_INIT() ({I2C_DDR &= ~((1<<I2C_SCL_PIN) | (1<<I2C_SDA_PIN)); I2C_PORT |= ((1<<I2C_SCL_PIN) | (1<<I2C_SDA_PIN));})
|
||||
#define I2C_DEINIT() ({I2C_DDR &= ~((1<<I2C_SCL_PIN) | (1<<I2C_SDA_PIN)); I2C_PORT |= ((1<<I2C_SCL_PIN) | (1<<I2C_SDA_PIN));})
|
||||
|
||||
#define I2C_FREQ_STANDARD I2C_FREQ_50KHZ
|
||||
|
||||
#if F_CPU == 16000000UL
|
||||
#define I2C_FREQ_400KHZ 0x03
|
||||
#define I2C_FREQ_250KHZ 0x06
|
||||
#define I2C_FREQ_100KHZ 0x12
|
||||
#define I2C_FREQ_50KHZ 0x26
|
||||
#define I2C_FREQ_10KHZ 0xC6
|
||||
#else
|
||||
#error "NO I2C FREQUENCY DEFINED -> CHECK F_CPU SETTINGS!"
|
||||
#endif
|
||||
|
||||
|
||||
#define I2C_STATUS_REG TWSR
|
||||
#define I2C_TX_REG TWDR
|
||||
#define I2C_RX_REG TWDR
|
||||
|
||||
#define I2C_START() (TWCR = (1<<TWINT) |(1<<TWSTA) | (1<<TWEN))
|
||||
#define I2C_STOP() (TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO))
|
||||
#define I2C_WRITE_BYTE() (TWCR = (1<<TWINT) | (1<<TWEN))
|
||||
#define I2C_READ_BYTE_ACK() (TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA))
|
||||
#define I2C_READ_BYTE_NACK() (TWCR = (1<<TWINT) | (1<<TWEN))
|
||||
#define I2C_STATUS() (I2C_STATUS_REG & I2C_STATUS_MASK)
|
||||
|
||||
#define I2C_STATUS_MASK 0xF8
|
||||
#define I2C_STATUS_START 0x08
|
||||
#define I2C_STATUS_START_REP 0x10
|
||||
#define I2C_STATUS_SLAW_ACK 0x18
|
||||
#define I2C_STATUS_DATAW_ACK 0x28
|
||||
#define I2C_STATUS_SLAR_ACK 0x40
|
||||
#define I2C_STATUS_DATAR_ACK 0x50
|
||||
#define I2C_STATUS_DATAR_NACK 0x58
|
||||
|
||||
#define I2C_ADR_WR(adr) ((adr<<1) & ~(1<<0))
|
||||
#define I2C_ADR_RD(adr) ((adr<<1) | (1<<0))
|
||||
|
||||
#define I2C_CMD_FLAG_NONE 0x00
|
||||
#define I2C_CMD_FLAG_START (1<<0)
|
||||
#define I2C_CMD_FLAG_STOP (1<<1)
|
||||
|
||||
|
||||
#define I2C_OK 0
|
||||
#define I2C_ERROR_DRIVER -1
|
||||
#define I2C_ERROR_TIMEOUT -2
|
||||
#define I2C_ERROR_START -3
|
||||
#define I2C_ERROR_WRITE -4
|
||||
#define I2C_ERROR_READ -5
|
||||
|
||||
|
||||
#define I2C_IOCTL_CMD_SET_FREQ 0x01
|
||||
|
||||
|
||||
typedef struct i2c_driver i2c_driver;
|
||||
struct i2c_driver
|
||||
{
|
||||
int8_t (*ioctl)(const i2c_driver* const me, uint8_t cmd, uint8_t arg);
|
||||
int8_t (*read)(const i2c_driver* const me, uint8_t cmd_flags, uint8_t* buffer, uint8_t len);
|
||||
int8_t (*write)(const i2c_driver* const me, uint8_t cmd_flags, const uint8_t* data, uint8_t len);
|
||||
};
|
||||
|
||||
i2c_driver* i2c_open(void);
|
||||
void i2c_close(i2c_driver* const me);
|
||||
void i2c_reset(void);
|
||||
|
||||
|
||||
#endif /* I2C_H_ */
|
73
cpu/avr/dev/key.c
Normal file
73
cpu/avr/dev/key.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2010 harald pichler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holders nor the names of
|
||||
* 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 AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief
|
||||
* This file provides Raven KEY support.
|
||||
*
|
||||
* \author
|
||||
* Harald Pichler harald@the-develop.net
|
||||
*
|
||||
*/
|
||||
|
||||
#include "key.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief This will intialize the KEY for button readings.
|
||||
*/
|
||||
void
|
||||
key_init(void)
|
||||
{
|
||||
/* Enter is input w/pullup */
|
||||
DDRF &= ~(1<<PINF1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief This will poll run key_task() to determine if a button has been pressed.
|
||||
*
|
||||
* \retval True if button is pressed
|
||||
* \retval False if button is not pressed
|
||||
*/
|
||||
uint8_t
|
||||
is_button(void)
|
||||
{
|
||||
/* Return true if button has been pressed. */
|
||||
if ( PINF & (1<<PINF1) ) {
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return 1;
|
||||
}
|
||||
}
|
50
cpu/avr/dev/key.h
Normal file
50
cpu/avr/dev/key.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Harald Pichler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holders nor the names of
|
||||
* 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 AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief
|
||||
* This file provides Raven Key support.
|
||||
*
|
||||
* \author
|
||||
* Harald Pixhlwe harald@the-develop.net
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KEY_H__
|
||||
#define __KEY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
void key_init(void);
|
||||
uint8_t is_button(void);
|
||||
|
||||
#endif /* __KEY_H__ */
|
89
cpu/avr/dev/led.c
Normal file
89
cpu/avr/dev/led.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2012 harald pichler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holders nor the names of
|
||||
* 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 AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief
|
||||
* This file provides Raven LED support.
|
||||
*
|
||||
* \author
|
||||
* Harald Pichler harald@the-develop.net
|
||||
*
|
||||
*/
|
||||
|
||||
#include "led.h"
|
||||
|
||||
/**
|
||||
* \addtogroup relay
|
||||
* \{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Turns the Raven LED1 on.
|
||||
*/
|
||||
void
|
||||
led1_on(void)
|
||||
{
|
||||
PORTE &= ~(1<<PINE5);
|
||||
DDRE |= (1<<PINE5);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Turns the Raven LED1 off.
|
||||
*/
|
||||
void
|
||||
led1_off(void)
|
||||
{
|
||||
PORTE |= (1<<PINE5);
|
||||
DDRE |= (1<<PINE5);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
led2_on(void)
|
||||
{
|
||||
PORTE &= ~(1<<PINE4);
|
||||
DDRE |= (1<<PINE4);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Turns the Raven LED1 off.
|
||||
*/
|
||||
void
|
||||
led2_off(void)
|
||||
{
|
||||
PORTE |= (1<<PINE4);
|
||||
DDRE |= (1<<PINE4);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
67
cpu/avr/dev/led.h
Normal file
67
cpu/avr/dev/led.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Harald Pichler
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holders nor the names of
|
||||
* 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 AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief
|
||||
* This file provides Raven LED support.
|
||||
*
|
||||
* \author
|
||||
* Harald Pichler harald@the-develop.net
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LED_H__
|
||||
#define __LED_H__
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
/* Some io.h definitions of shift vary among processors */
|
||||
#ifndef DDE0
|
||||
#define DDE0 DDRE0
|
||||
#define DDE1 DDRE1
|
||||
#define DDE2 DDRE2
|
||||
#define DDE3 DDRE3
|
||||
#define DDE4 DDRE4
|
||||
#define DDE5 DDRE5
|
||||
#define DDE6 DDRE6
|
||||
#define DDE7 DDRE7
|
||||
#endif
|
||||
|
||||
|
||||
/** @name LED Functions */
|
||||
/** @{ */
|
||||
void led1_on(void);
|
||||
void led1_off(void);
|
||||
void led2_on(void);
|
||||
void led2_off(void);
|
||||
/** @} */
|
||||
|
||||
#endif /* __LED_H__ */
|
102
cpu/avr/dev/optriac-sensor.c
Normal file
102
cpu/avr/dev/optriac-sensor.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) , Harald Pichler.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: servo-sensor.c,v 1.0 2013/02/20 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* optriac sensor header file for Atmega128rfa1.
|
||||
* \author
|
||||
* Harald Pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "Arduino.h"
|
||||
#include "dev/optriac-sensor.h"
|
||||
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
|
||||
const struct sensors_sensor optriac_sensor;
|
||||
static int status(int type);
|
||||
static int enabled = 0;
|
||||
static int optriac[2]={0,0};
|
||||
static int optriacpin[8]={OPTRIAC_PIN_1,OPTRIAC_PIN_2};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
value(int type)
|
||||
{
|
||||
return optriac[type];
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
configure(int type, int c)
|
||||
{
|
||||
switch(type) {
|
||||
case SENSORS_ACTIVE:
|
||||
if(c) {
|
||||
if(!status(SENSORS_ACTIVE)) {
|
||||
pinMode(optriacpin[OPTRIAC_SENSOR_1], OUTPUT);
|
||||
digitalWrite(optriacpin[OPTRIAC_SENSOR_1], LOW);
|
||||
pinMode(optriacpin[OPTRIAC_SENSOR_2], OUTPUT);
|
||||
digitalWrite(optriacpin[OPTRIAC_SENSOR_2], LOW);
|
||||
|
||||
enabled = 1;
|
||||
}
|
||||
} else {
|
||||
enabled = 1;
|
||||
}
|
||||
break;
|
||||
case OPTRIAC_SENSOR_1:
|
||||
case OPTRIAC_SENSOR_2:
|
||||
|
||||
if(c==0){
|
||||
digitalWrite(optriacpin[type], LOW);
|
||||
optriac[type]=0;
|
||||
}else{
|
||||
digitalWrite(optriacpin[type], HIGH);
|
||||
optriac[type]=1;
|
||||
};
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
status(int type)
|
||||
{
|
||||
switch(type) {
|
||||
case SENSORS_ACTIVE:
|
||||
case SENSORS_READY:
|
||||
return enabled;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
SENSORS_SENSOR(optriac_sensor, OPTRIAC_SENSOR, value, configure, status);
|
54
cpu/avr/dev/optriac-sensor.h
Normal file
54
cpu/avr/dev/optriac-sensor.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c), Harald Pichler.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: servo-sensor.h,v 1.0 2013/02/20 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Servo sensor header file for Atmega128rfa1.
|
||||
* \author
|
||||
* Harald Pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
#ifndef __OPTRIAC_SENSOR_H__
|
||||
#define __OPTRIAC_SENSOR_H__
|
||||
|
||||
#include "lib/sensors.h"
|
||||
|
||||
extern const struct sensors_sensor optriac_sensor;
|
||||
|
||||
#define OPTRIAC_SENSOR "TRIAC"
|
||||
#define OPTRIAC_SENSOR_1 0
|
||||
#define OPTRIAC_SENSOR_2 1
|
||||
|
||||
/* default pins Arduino-Merkurboard */
|
||||
#define OPTRIAC_PIN_1 2
|
||||
#define OPTRIAC_PIN_2 3
|
||||
|
||||
#endif /* __OPTRIAC_SENSOR_H__ */
|
85
cpu/avr/dev/pir-sensor.c
Normal file
85
cpu/avr/dev/pir-sensor.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* Sensor routine */
|
||||
#include "contiki.h"
|
||||
#include "lib/sensors.h"
|
||||
#include "dev/pir-sensor.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include "led.h" // debug
|
||||
|
||||
const struct sensors_sensor pir_sensor;
|
||||
|
||||
static struct timer debouncetimer;
|
||||
static int status(int type);
|
||||
static int enabled = 0;
|
||||
struct sensors_sensor *sensors[1];
|
||||
unsigned char sensors_flags[1];
|
||||
|
||||
#define PIR_BIT INTF6
|
||||
#define PIR_CHECK_IRQ() (EIFR & PIR_BIT) ? 0 : 1
|
||||
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
ISR(INT6_vect)
|
||||
{
|
||||
|
||||
// leds_toggle(LEDS_YELLOW);
|
||||
|
||||
if(PIR_CHECK_IRQ()) {
|
||||
if(timer_expired(&debouncetimer)) {
|
||||
// led1_on();
|
||||
timer_set(&debouncetimer, CLOCK_SECOND / 4);
|
||||
sensors_changed(&pir_sensor);
|
||||
// led1_off();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
value(int type)
|
||||
{
|
||||
return (PORTE & _BV(PE6) ? 0 : 1) || !timer_expired(&debouncetimer);
|
||||
//return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
configure(int type, int c)
|
||||
{
|
||||
switch (type) {
|
||||
case SENSORS_ACTIVE:
|
||||
if (c) {
|
||||
if(!status(SENSORS_ACTIVE)) {
|
||||
// led1_on();
|
||||
timer_set(&debouncetimer, 0);
|
||||
DDRE |= (0<<DDE6); // Set pin as input
|
||||
PORTE |= (1<<PORTE6); // Set port PORTE bint 6 with pullup resistor
|
||||
EICRB |= (3<<ISC60); // For rising edge
|
||||
EIMSK |= (1<<INT6); // Set int
|
||||
enabled = 1;
|
||||
sei();
|
||||
// led1_off();
|
||||
}
|
||||
} else {
|
||||
enabled = 0;
|
||||
EIMSK &= ~(1<<INT6); // clear int
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
status(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case SENSORS_ACTIVE:
|
||||
case SENSORS_READY:
|
||||
return enabled;//(EIMSK & (1<<INT6) ? 0 : 1);//PIR_IRQ_ENABLED();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SENSORS_SENSOR(pir_sensor, PIR_SENSOR,
|
||||
value, configure, status);
|
||||
|
48
cpu/avr/dev/pir-sensor.h
Normal file
48
cpu/avr/dev/pir-sensor.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2012, BinaryLabs.
|
||||
* 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: battery-sensor.h,v 1.1 2012/08/25 19:34:06 nifi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* PIR sensor header file for Atmega128rfa1.
|
||||
* \author
|
||||
* Harald Pichler <harald@the-develop.net>
|
||||
*/
|
||||
|
||||
#ifndef __PIR_SENSOR_H__
|
||||
#define __PIR_SENSOR_H__
|
||||
|
||||
#include "lib/sensors.h"
|
||||
|
||||
extern const struct sensors_sensor pir_sensor;
|
||||
|
||||
#define PIR_SENSOR "PIR"
|
||||
|
||||
#endif /* __PIR_SENSOR_H__ */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue