diff options
Diffstat (limited to 'lib/chibios-contrib/os/various')
62 files changed, 13231 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/various/bitmap.c b/lib/chibios-contrib/os/various/bitmap.c new file mode 100644 index 000000000..a17dfcb66 --- /dev/null +++ b/lib/chibios-contrib/os/various/bitmap.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | ChibiOS/HAL - Copyright (C) 2015 Uladzimir Pylinsky aka barthess | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file bitmap.c | ||
19 | * @brief Bit map code. | ||
20 | * | ||
21 | * @addtogroup bitmap | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #include "string.h" /* for memset() */ | ||
26 | |||
27 | #include "hal.h" | ||
28 | #include "bitmap.h" | ||
29 | |||
30 | /*===========================================================================*/ | ||
31 | /* Module local definitions. */ | ||
32 | /*===========================================================================*/ | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module exported variables. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /*===========================================================================*/ | ||
39 | /* Module local types. */ | ||
40 | /*===========================================================================*/ | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local variables. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Module local functions. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /** | ||
51 | * @brief Get word number. | ||
52 | * | ||
53 | * @param[in] bit number of the bit | ||
54 | * | ||
55 | * @return Index of the word containing specified bit. | ||
56 | */ | ||
57 | static inline size_t word(size_t bit) { | ||
58 | return bit / (sizeof(bitmap_word_t) * 8); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * @brief Get bit position in word. | ||
63 | * | ||
64 | * @param[in] bit number of the bit | ||
65 | * | ||
66 | * @return Position of the specified bit related to word start. | ||
67 | */ | ||
68 | static inline size_t pos_in_word(size_t bit) { | ||
69 | return bit % (sizeof(bitmap_word_t) * 8); | ||
70 | } | ||
71 | |||
72 | /*===========================================================================*/ | ||
73 | /* Module exported functions. */ | ||
74 | /*===========================================================================*/ | ||
75 | /** | ||
76 | * @brief Initializes an @p bitmap_t structure. | ||
77 | * | ||
78 | * @param[out] map the @p bitmap_t structure to be initialized | ||
79 | * @param[in] val the value to be written in all bitmap | ||
80 | */ | ||
81 | void bitmapObjectInit(bitmap_t *map, bitmap_word_t val) { | ||
82 | uint8_t pattern; | ||
83 | |||
84 | osalDbgCheck(val == 1 || val == 0); | ||
85 | |||
86 | if (val == 1) | ||
87 | pattern = 0xFF; | ||
88 | else | ||
89 | pattern = 0; | ||
90 | |||
91 | memset(map->array, pattern, map->len*sizeof(bitmap_word_t)); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * @brief Set single bit in an @p bitmap_t structure. | ||
96 | * | ||
97 | * @param[out] map the @p bitmap_t structure | ||
98 | * @param[in] bit number of the bit to be set | ||
99 | */ | ||
100 | void bitmapSet(bitmap_t *map, size_t bit) { | ||
101 | size_t w = word(bit); | ||
102 | |||
103 | osalDbgCheck(w < map->len); | ||
104 | map->array[w] |= (bitmap_word_t)1 << pos_in_word(bit); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * @brief Clear single bit in an @p bitmap_t structure. | ||
109 | * | ||
110 | * @param[out] map the @p bitmap_t structure | ||
111 | * @param[in] bit number of the bit to be cleared | ||
112 | */ | ||
113 | void bitmapClear(bitmap_t *map, size_t bit) { | ||
114 | size_t w = word(bit); | ||
115 | |||
116 | osalDbgCheck(w < map->len); | ||
117 | map->array[w] &= ~((bitmap_word_t)1 << pos_in_word(bit)); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * @brief Invert single bit in an @p bitmap_t structure. | ||
122 | * | ||
123 | * @param[out] map the @p bitmap_t structure | ||
124 | * @param[in] bit number of the bit to be inverted | ||
125 | */ | ||
126 | void bitmapInvert(bitmap_t *map, size_t bit) { | ||
127 | size_t w = word(bit); | ||
128 | |||
129 | osalDbgCheck(w < map->len); | ||
130 | map->array[w] ^= (bitmap_word_t)1 << pos_in_word(bit); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * @brief Get bit value from an @p bitmap_t structure. | ||
135 | * | ||
136 | * @param[in] map the @p bitmap_t structure | ||
137 | * @param[in] bit number of the requested bit | ||
138 | * | ||
139 | * @return Requested bit value. | ||
140 | */ | ||
141 | bitmap_word_t bitmapGet(const bitmap_t *map, size_t bit) { | ||
142 | size_t w = word(bit); | ||
143 | |||
144 | osalDbgCheck(w < map->len); | ||
145 | return (map->array[w] >> pos_in_word(bit)) & 1; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * @brief Get total amount of bits in an @p bitmap_t structure. | ||
150 | * | ||
151 | * @param[in] map the @p bitmap_t structure | ||
152 | * | ||
153 | * @return Bit number. | ||
154 | */ | ||
155 | size_t bitmapGetBitsCount(const bitmap_t *map) { | ||
156 | return map->len * sizeof(bitmap_word_t) * 8; | ||
157 | } | ||
158 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/bitmap.h b/lib/chibios-contrib/os/various/bitmap.h new file mode 100644 index 000000000..115b54cf8 --- /dev/null +++ b/lib/chibios-contrib/os/various/bitmap.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | ChibiOS/HAL - Copyright (C) 2015 Uladzimir Pylinsky aka barthess | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file bitmap.h | ||
19 | * @brief Bit map structures and macros. | ||
20 | * | ||
21 | * @addtogroup bitmap | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #ifndef BITMAP_H_ | ||
26 | #define BITMAP_H_ | ||
27 | |||
28 | /*===========================================================================*/ | ||
29 | /* Module constants. */ | ||
30 | /*===========================================================================*/ | ||
31 | |||
32 | /*===========================================================================*/ | ||
33 | /* Module pre-compile time settings. */ | ||
34 | /*===========================================================================*/ | ||
35 | |||
36 | /*===========================================================================*/ | ||
37 | /* Derived constants and error checks. */ | ||
38 | /*===========================================================================*/ | ||
39 | |||
40 | /*===========================================================================*/ | ||
41 | /* Module data structures and types. */ | ||
42 | /*===========================================================================*/ | ||
43 | |||
44 | typedef unsigned int bitmap_word_t; | ||
45 | |||
46 | /** | ||
47 | * @brief Type of a event timer structure. | ||
48 | */ | ||
49 | typedef struct { | ||
50 | bitmap_word_t *array; | ||
51 | size_t len; /* Array length in _words_ NOT bytes */ | ||
52 | } bitmap_t; | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Module macros. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* External declarations. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | #ifdef __cplusplus | ||
63 | extern "C" { | ||
64 | #endif | ||
65 | void bitmapObjectInit(bitmap_t *map, bitmap_word_t val); | ||
66 | void bitmapSet(bitmap_t *map, size_t bit); | ||
67 | void bitmapClear(bitmap_t *map, size_t bit); | ||
68 | void bitmapInvert(bitmap_t *map, size_t bit); | ||
69 | bitmap_word_t bitmapGet(const bitmap_t *map, size_t bit); | ||
70 | size_t bitmapGetBitsCount(const bitmap_t *map); | ||
71 | #ifdef __cplusplus | ||
72 | } | ||
73 | #endif | ||
74 | |||
75 | #endif /* BITMAP_H_ */ | ||
76 | |||
77 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/bmp.mk b/lib/chibios-contrib/os/various/bmp.mk new file mode 100644 index 000000000..1e2e63e0f --- /dev/null +++ b/lib/chibios-contrib/os/various/bmp.mk | |||
@@ -0,0 +1,57 @@ | |||
1 | ## | ||
2 | ## make targets for the Black Magic Probe | ||
3 | ## See: https://github.com/blacksphere/blackmagic (Black Magic) | ||
4 | ## See: https://github.com/blacksphere/blackmagic/wiki/Frequently-Asked-Questions (Black Magic udev rules) | ||
5 | ## | ||
6 | ## Provides the following targets: | ||
7 | ## | ||
8 | ## all: Wrapper for the elf binary | ||
9 | ## flash: Uses GDB to flash the target via Black Magic | ||
10 | ## debug: Flashes the target and allows for debugging using gdb and Black Magic | ||
11 | ## debug-tui: Flashes the target and allows for debugging using gdb's TUI and Black Magic | ||
12 | ## | ||
13 | |||
14 | GDB ?= arm-none-eabi-gdb # Path to the arm-none-eabi-gdb binary | ||
15 | GDB_PROGRAM ?= $(BUILDDIR)/$(PROJECT).elf # Path to the elf binary | ||
16 | GDB_BREAK ?= main # Function to break at when starting the debugger | ||
17 | |||
18 | BMP_GDB ?= /dev/ttyBmpGdb # Device file for the Black Magic GDB devic | ||
19 | |||
20 | all: $(GDB_PROGRAM) | ||
21 | |||
22 | flash: $(GDB_PROGRAM) | ||
23 | $(GDB) $(GDB_PROGRAM) -nx --batch \ | ||
24 | -ex 'target extended-remote $(BMP_GDB)' \ | ||
25 | -ex 'monitor swdp_scan' \ | ||
26 | -ex 'attach 1' \ | ||
27 | -ex 'load' \ | ||
28 | -ex 'compare-sections' \ | ||
29 | -ex 'kill' | ||
30 | |||
31 | debug: $(GDB_PROGRAM) | ||
32 | $(GDB) $(GDB_PROGRAM) -nx \ | ||
33 | -ex 'target extended-remote $(BMP_GDB)' \ | ||
34 | -ex 'monitor swdp_scan' \ | ||
35 | -ex 'attach 1' \ | ||
36 | -ex 'load' \ | ||
37 | -ex 'compare-sections' \ | ||
38 | -ex 'set mem inaccessible-by-default off' \ | ||
39 | -ex 'break $(GDB_BREAK)' \ | ||
40 | -ex 'c' | ||
41 | |||
42 | debug-tui: $(GDB_PROGRAM) | ||
43 | $(GDB) $(GDB_PROGRAM) -nx \ | ||
44 | -ex 'target extended-remote $(BMP_GDB)' \ | ||
45 | -ex 'monitor swdp_scan' \ | ||
46 | -ex 'attach 1' \ | ||
47 | -ex 'load' \ | ||
48 | -ex 'compare-sections' \ | ||
49 | -ex 'set mem inaccessible-by-default off' \ | ||
50 | -ex 'set pagination off' \ | ||
51 | -ex 'focus cmd' \ | ||
52 | -ex 'layout src' \ | ||
53 | -ex 'break $(GDB_BREAK)' \ | ||
54 | -ex 'c' \ | ||
55 | -ex 'set pagination on' | ||
56 | |||
57 | .PHONY: all flash debug debug-tui | ||
diff --git a/lib/chibios-contrib/os/various/bswap.h b/lib/chibios-contrib/os/various/bswap.h new file mode 100644 index 000000000..64484984d --- /dev/null +++ b/lib/chibios-contrib/os/various/bswap.h | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | Copyright (C) 2016 Stephane D'Alu | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef BSWAP_H | ||
18 | #define BSWAP_H | ||
19 | |||
20 | #if defined(__cplusplus) | ||
21 | extern "C" { | ||
22 | #endif | ||
23 | |||
24 | #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN)) | ||
25 | #error "Need to define one: ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN" | ||
26 | #endif | ||
27 | |||
28 | #if defined(ARCH_BIG_ENDIAN) && defined(ARCH_LITTLE_ENDIAN) | ||
29 | #error "ARCH_BIG_ENDIAN and ARCH_LITTLE_ENDIAN are both set" | ||
30 | #endif | ||
31 | |||
32 | |||
33 | #define BSWAP_16(x) \ | ||
34 | (uint16_t)((((x) & 0xFF00) >> 8) | \ | ||
35 | (((x) & 0x00FF) << 8)) | ||
36 | #define BSWAP_32(x) \ | ||
37 | (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | \ | ||
38 | (((x) & 0x00FF0000UL) >> 8UL) | \ | ||
39 | (((x) & 0x0000FF00UL) << 8UL) | \ | ||
40 | (((x) & 0x000000FFUL) << 24UL)) | ||
41 | #define BSWAP_64(x) \ | ||
42 | (uint64_t)((((x) & 0xFF00000000000000UL) >> 56UL) | \ | ||
43 | (((x) & 0x00FF000000000000UL) >> 40UL) | \ | ||
44 | (((x) & 0x0000FF0000000000UL) >> 24UL) | \ | ||
45 | (((x) & 0x000000FF00000000UL) >> 8UL) | \ | ||
46 | (((x) & 0x00000000FF000000UL) << 8UL) | \ | ||
47 | (((x) & 0x0000000000FF0000UL) << 24UL) | \ | ||
48 | (((x) & 0x000000000000FF00UL) << 40UL) | \ | ||
49 | (((x) & 0x00000000000000FFUL) << 56UL)) | ||
50 | |||
51 | |||
52 | #if defined(ARCH_BIG_ENDIAN) | ||
53 | #define le16_to_cpu(x) bswap_16(x) | ||
54 | #define le32_to_cpu(x) bswap_32(x) | ||
55 | #define le64_to_cpu(x) bswap_64(x) | ||
56 | #define be16_to_cpu(x) (x) | ||
57 | #define be32_to_cpu(x) (x) | ||
58 | #define be64_to_cpu(x) (x) | ||
59 | #define cpu_to_le16(x) bswap_16(x) | ||
60 | #define cpu_to_le32(x) bswap_32(x) | ||
61 | #define cpu_to_le64(x) bswap_64(x) | ||
62 | #define cpu_to_be16(x) (x) | ||
63 | #define cpu_to_be32(x) (x) | ||
64 | #define cpu_to_be64(x) (x) | ||
65 | #define LE16_TO_CPU(x) BSWAP_16(x) | ||
66 | #define LE32_TO_CPU(x) BSWAP_32(x) | ||
67 | #define LE64_TO_CPU(x) BSWAP_64(x) | ||
68 | #define BE16_TO_CPU(x) (x) | ||
69 | #define BE32_TO_CPU(x) (x) | ||
70 | #define BE64_TO_CPU(x) (x) | ||
71 | #define CPU_TO_LE16(x) BSWAP_16(x) | ||
72 | #define CPU_TO_LE32(x) BSWAP_32(x) | ||
73 | #define CPU_TO_LE64(x) BSWAP_64(x) | ||
74 | #define CPU_TO_BE16(x) (x) | ||
75 | #define CPU_TO_BE32(x) (x) | ||
76 | #define CPU_TO_BE64(x) (x) | ||
77 | #endif | ||
78 | |||
79 | |||
80 | #if defined(ARCH_LITTLE_ENDIAN) | ||
81 | #define le16_to_cpu(x) (x) | ||
82 | #define le32_to_cpu(x) (x) | ||
83 | #define le64_to_cpu(x) (x) | ||
84 | #define be16_to_cpu(x) bswap_16(x) | ||
85 | #define be32_to_cpu(x) bswap_32(x) | ||
86 | #define be64_to_cpu(x) bswap_64(x) | ||
87 | #define cpu_to_le16(x) (x) | ||
88 | #define cpu_to_le32(x) (x) | ||
89 | #define cpu_to_le64(x) (x) | ||
90 | #define cpu_to_be16(x) bswap_16(x) | ||
91 | #define cpu_to_be32(x) bswap_32(x) | ||
92 | #define cpu_to_be64(x) bswap_64(x) | ||
93 | #define LE16_TO_CPU(x) (x) | ||
94 | #define LE32_TO_CPU(x) (x) | ||
95 | #define LE64_TO_CPU(x) (x) | ||
96 | #define BE16_TO_CPU(x) BSWAP_16(x) | ||
97 | #define BE32_TO_CPU(x) BSWAP_32(x) | ||
98 | #define BE64_TO_CPU(x) BSWAP_64(x) | ||
99 | #define CPU_TO_LE16(x) (x) | ||
100 | #define CPU_TO_LE32(x) (x) | ||
101 | #define CPU_TO_LE64(x) (x) | ||
102 | #define CPU_TO_BE16(x) BSWAP_16(x) | ||
103 | #define CPU_TO_BE32(x) BSWAP_32(x) | ||
104 | #define CPU_TO_BE64(x) BSWAP_64(x) | ||
105 | #endif | ||
106 | |||
107 | |||
108 | static inline uint16_t bswap_16(const uint16_t x) | ||
109 | __attribute__ ((warn_unused_result)) | ||
110 | __attribute__ ((const)) | ||
111 | __attribute__ ((always_inline)); | ||
112 | |||
113 | static inline uint16_t bswap_16(const uint16_t x) { | ||
114 | if (__builtin_constant_p(x)) | ||
115 | return BSWAP_16(x); | ||
116 | |||
117 | uint8_t tmp; | ||
118 | union { uint16_t x; uint8_t b[2]; } data; | ||
119 | |||
120 | data.x = x; | ||
121 | tmp = data.b[0]; | ||
122 | data.b[0] = data.b[1]; | ||
123 | data.b[1] = tmp; | ||
124 | |||
125 | return data.x; | ||
126 | } | ||
127 | |||
128 | static inline uint32_t bswap_32(const uint32_t x) | ||
129 | __attribute__ ((warn_unused_result)) | ||
130 | __attribute__ ((const)) | ||
131 | __attribute__ ((always_inline)); | ||
132 | |||
133 | |||
134 | static inline uint32_t bswap_32(const uint32_t x) { | ||
135 | if (__builtin_constant_p(x)) | ||
136 | return BSWAP_32(x); | ||
137 | |||
138 | uint8_t tmp; | ||
139 | union { uint32_t x; uint8_t b[4]; } data; | ||
140 | |||
141 | data.x = x; | ||
142 | tmp = data.b[0]; | ||
143 | data.b[0] = data.b[3]; | ||
144 | data.b[3] = tmp; | ||
145 | tmp = data.b[1]; | ||
146 | data.b[1] = data.b[2]; | ||
147 | data.b[2] = tmp; | ||
148 | |||
149 | return data.x; | ||
150 | } | ||
151 | |||
152 | static inline uint64_t bswap_64(const uint64_t x) | ||
153 | __attribute__ ((warn_unused_result)) | ||
154 | __attribute__ ((const)) | ||
155 | __attribute__ ((always_inline)); | ||
156 | |||
157 | |||
158 | static inline uint64_t bswap_64(const uint64_t x) { | ||
159 | if (__builtin_constant_p(x)) | ||
160 | return BSWAP_64(x); | ||
161 | |||
162 | uint8_t tmp; | ||
163 | union { uint64_t x; uint8_t b[8]; } data; | ||
164 | |||
165 | data.x = x; | ||
166 | tmp = data.b[0]; | ||
167 | data.b[0] = data.b[7]; | ||
168 | data.b[7] = tmp; | ||
169 | tmp = data.b[1]; | ||
170 | data.b[1] = data.b[6]; | ||
171 | data.b[6] = tmp; | ||
172 | tmp = data.b[2]; | ||
173 | data.b[2] = data.b[5]; | ||
174 | data.b[5] = tmp; | ||
175 | tmp = data.b[3]; | ||
176 | data.b[3] = data.b[4]; | ||
177 | data.b[4] = tmp; | ||
178 | |||
179 | return data.x; | ||
180 | } | ||
181 | |||
182 | static inline void bswap_n(void* const data, uint8_t len) | ||
183 | __attribute__ ((nonnull (1))); | ||
184 | |||
185 | static inline void bswap_n(void* const data, uint8_t len) { | ||
186 | uint8_t* ptr = (uint8_t*)data; | ||
187 | |||
188 | for ( ; len > 1 ; ptr++, len -= 2 ) { | ||
189 | uint8_t tmp = *ptr; | ||
190 | *ptr = *(ptr + len - 1); | ||
191 | *(ptr + len - 1) = tmp; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | #if defined(__cplusplus) | ||
196 | } | ||
197 | #endif | ||
198 | |||
199 | #endif | ||
200 | |||
201 | |||
diff --git a/lib/chibios-contrib/os/various/crcsw.c b/lib/chibios-contrib/os/various/crcsw.c new file mode 100644 index 000000000..02a64f3ef --- /dev/null +++ b/lib/chibios-contrib/os/various/crcsw.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2015 Michael D. Spradling | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file crcsw.c | ||
19 | * @brief CRC software driver. | ||
20 | @note SW implementation was based from: | ||
21 | * @note http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code | ||
22 | * | ||
23 | * @addtogroup CRC | ||
24 | * @{ | ||
25 | */ | ||
26 | |||
27 | #include "hal.h" | ||
28 | |||
29 | #if HAL_USE_CRC || defined(__DOXYGEN__) | ||
30 | |||
31 | #if CRCSW_USE_CRC1 || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Driver local definitions. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /** | ||
38 | * @brief CRC default configuration. | ||
39 | */ | ||
40 | |||
41 | #if CRCSW_CRC32_TABLE == TRUE || defined(__DOXYGEN__) | ||
42 | static const uint32_t crc32_table[256] = { | ||
43 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, | ||
44 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | ||
45 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | ||
46 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | ||
47 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, | ||
48 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | ||
49 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, | ||
50 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | ||
51 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | ||
52 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | ||
53 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, | ||
54 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | ||
55 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, | ||
56 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | ||
57 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | ||
58 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | ||
59 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, | ||
60 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | ||
61 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, | ||
62 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | ||
63 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | ||
64 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | ||
65 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, | ||
66 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | ||
67 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, | ||
68 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | ||
69 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | ||
70 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | ||
71 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, | ||
72 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | ||
73 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, | ||
74 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | ||
75 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | ||
76 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | ||
77 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, | ||
78 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | ||
79 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, | ||
80 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | ||
81 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | ||
82 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | ||
83 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, | ||
84 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | ||
85 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, | ||
86 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | ||
87 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | ||
88 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | ||
89 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, | ||
90 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | ||
91 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, | ||
92 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | ||
93 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | ||
94 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | ||
95 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, | ||
96 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | ||
97 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, | ||
98 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | ||
99 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | ||
100 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | ||
101 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, | ||
102 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | ||
103 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, | ||
104 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | ||
105 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | ||
106 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d | ||
107 | }; | ||
108 | #endif | ||
109 | |||
110 | #if CRCSW_CRC16_TABLE || defined(__DOXYGEN__) | ||
111 | static const uint32_t crc16_table[256] = { | ||
112 | 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, | ||
113 | 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, | ||
114 | 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, | ||
115 | 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, | ||
116 | 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, | ||
117 | 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, | ||
118 | 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, | ||
119 | 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, | ||
120 | 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, | ||
121 | 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, | ||
122 | 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, | ||
123 | 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, | ||
124 | 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, | ||
125 | 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, | ||
126 | 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, | ||
127 | 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, | ||
128 | 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, | ||
129 | 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, | ||
130 | 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, | ||
131 | 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, | ||
132 | 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, | ||
133 | 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, | ||
134 | 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, | ||
135 | 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, | ||
136 | 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, | ||
137 | 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, | ||
138 | 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, | ||
139 | 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, | ||
140 | 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, | ||
141 | 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, | ||
142 | 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, | ||
143 | 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 | ||
144 | }; | ||
145 | #endif | ||
146 | |||
147 | /*===========================================================================*/ | ||
148 | /* Driver exported variables. */ | ||
149 | /*===========================================================================*/ | ||
150 | |||
151 | /** @brief CRC1 driver identifier.*/ | ||
152 | #if CRCSW_USE_CRC1 || defined(__DOXYGEN__) | ||
153 | CRCDriver CRCD1; | ||
154 | #endif | ||
155 | |||
156 | #if CRCSW_CRC32_TABLE || defined(__DOXYGEN__) | ||
157 | const CRCConfig crcsw_crc32_config = { | ||
158 | .poly_size = 32, | ||
159 | .poly = 0x04C11DB7, | ||
160 | .initial_val = 0xFFFFFFFF, | ||
161 | .final_val = 0xFFFFFFFF, | ||
162 | .reflect_data = 1, | ||
163 | .reflect_remainder = 1, | ||
164 | .table = crc32_table | ||
165 | }; | ||
166 | #endif | ||
167 | |||
168 | #if CRCSW_CRC16_TABLE || defined(__DOXYGEN__) | ||
169 | const CRCConfig crcsw_crc16_config = { | ||
170 | .poly_size = 16, | ||
171 | .poly = 0x8005, | ||
172 | .initial_val = 0x0, | ||
173 | .final_val = 0x0, | ||
174 | .reflect_data = 1, | ||
175 | .reflect_remainder = 1, | ||
176 | .table = crc16_table | ||
177 | }; | ||
178 | #endif | ||
179 | |||
180 | /*===========================================================================*/ | ||
181 | /* Driver local variables and types. */ | ||
182 | /*===========================================================================*/ | ||
183 | |||
184 | /*===========================================================================*/ | ||
185 | /* Driver local functions. */ | ||
186 | /*===========================================================================*/ | ||
187 | |||
188 | #if (CRCSW_PROGRAMMABLE == TRUE) | ||
189 | static uint32_t reflect(uint32_t data, uint8_t nBits) { | ||
190 | uint32_t reflection = 0x00000000; | ||
191 | uint8_t bit; | ||
192 | |||
193 | /* Reflect the data about the center bit. */ | ||
194 | for (bit = 0; bit < nBits; ++bit) { | ||
195 | /* If the LSB bit is set, set the reflection of it. */ | ||
196 | if (data & 0x01) { | ||
197 | reflection |= (1 << ((nBits - 1) - bit)); | ||
198 | } | ||
199 | |||
200 | data = (data >> 1); | ||
201 | } | ||
202 | |||
203 | return reflection; | ||
204 | } | ||
205 | #endif | ||
206 | |||
207 | /*===========================================================================*/ | ||
208 | /* Driver interrupt handlers. */ | ||
209 | /*===========================================================================*/ | ||
210 | |||
211 | /*===========================================================================*/ | ||
212 | /* Driver exported functions. */ | ||
213 | /*===========================================================================*/ | ||
214 | |||
215 | /** | ||
216 | * @brief Low level CRC software initialization. | ||
217 | * | ||
218 | * @notapi | ||
219 | */ | ||
220 | void crc_lld_init(void) { | ||
221 | crcObjectInit(&CRCD1); | ||
222 | CRCD1.crc = CRCD1.config->initial_val; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * @brief Configures and activates the CRC peripheral. | ||
227 | * | ||
228 | * @param[in] crcp pointer to the @p CRCDriver object | ||
229 | * | ||
230 | * @notapi | ||
231 | */ | ||
232 | void crc_lld_start(CRCDriver *crcp) { | ||
233 | osalDbgAssert(crcp->config != NULL, "config must not be NULL"); | ||
234 | |||
235 | #if CRCSW_PROGRAMMABLE == FALSE | ||
236 | #if CRCSW_CRC32_TABLE == TRUE && CRCSW_CRC16_TABLE == TRUE | ||
237 | osalDbgAssert((crcp->config == CRCSW_CRC32_TABLE_CONFIG) || | ||
238 | (crcp->config == CRCSW_CRC16_TABLE_CONFIG), "config must be CRCSW_CRC32_TABLE_CONFIG or CRCSW_CRC16_TABLE_CONFIG"); | ||
239 | #elif CRCSW_CRC32_TABLE == TRUE && CRCSW_CRC16_TABLE == FALSE | ||
240 | osalDbgAssert(crcp->config == CRCSW_CRC32_TABLE_CONFIG, | ||
241 | "config must be CRCSW_CRC32_TABLE_CONFIG"); | ||
242 | #else | ||
243 | osalDbgAssert(crcp->config == CRCSW_CRC16_TABLE_CONFIG, | ||
244 | "config must be CRCSW_CRC16_TABLE_CONFIG"); | ||
245 | #endif | ||
246 | #endif | ||
247 | crc_lld_reset(crcp); | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * @brief Deactivates the CRC peripheral. | ||
253 | * | ||
254 | * @param[in] crcp pointer to the @p CRCDriver object | ||
255 | * | ||
256 | * @notapi | ||
257 | */ | ||
258 | void crc_lld_stop(CRCDriver *crcp) { | ||
259 | (void)crcp; | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * @brief Resets current CRC calculation. | ||
264 | * | ||
265 | * @param[in] crcp pointer to the @p CRCDriver object | ||
266 | * | ||
267 | * @notapi | ||
268 | */ | ||
269 | void crc_lld_reset(CRCDriver *crcp) { | ||
270 | crcp->crc = crcp->config->initial_val; | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * @brief Returns calculated CRC from last reset | ||
275 | * | ||
276 | * @param[in] crcp pointer to the @p CRCDriver object | ||
277 | * @param[in] n size of buf in bytes | ||
278 | * @param[in] buf @p buffer location | ||
279 | * | ||
280 | * @notapi | ||
281 | */ | ||
282 | uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf) { | ||
283 | uint32_t i; | ||
284 | uint32_t crc; | ||
285 | #if (CRCSW_CRC32_TABLE == TRUE) || (CRCSW_CRC16_TABLE == TRUE) | ||
286 | if (crcp->config->table != NULL) { | ||
287 | for (i = 0; i < n; i++) { | ||
288 | uint8_t data = *((uint8_t*)buf + i); | ||
289 | uint8_t idx = (crcp->crc ^ data); | ||
290 | crcp->crc = (crcp->config->table[idx] ^ (crcp->crc >> 8)); | ||
291 | } | ||
292 | crc = crcp->crc; | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | #if (CRCSW_PROGRAMMABLE == TRUE) | ||
297 | // Mask off bits to poly size | ||
298 | uint32_t mask = 1 << (crcp->config->poly_size - 1); | ||
299 | mask |= (mask - 1); | ||
300 | |||
301 | crc = crcp->crc; | ||
302 | if (crcp->config->table == NULL) { | ||
303 | for (i = 0; i < n; i++) { | ||
304 | uint8_t data = *((uint8_t*)buf + i); | ||
305 | uint8_t bit; | ||
306 | |||
307 | if (crcp->config->reflect_data) { | ||
308 | data = reflect(data, 8); | ||
309 | } | ||
310 | |||
311 | /* Bring the next byte into the remainder. */ | ||
312 | crc ^= (data << (crcp->config->poly_size - 8)); | ||
313 | |||
314 | /* Perform modulo-2 division, a bit at a time. */ | ||
315 | for (bit = 8; bit > 0; --bit) { | ||
316 | /* Try to divide the current data bit. */ | ||
317 | if (crc & (1 << (crcp->config->poly_size - 1))) { | ||
318 | crc = (crc << 1) ^ crcp->config->poly; | ||
319 | } else { | ||
320 | crc <<= 1; | ||
321 | } | ||
322 | } | ||
323 | } | ||
324 | |||
325 | crcp->crc = crc; | ||
326 | |||
327 | if (crcp->config->reflect_remainder) { | ||
328 | crc = reflect(crc, crcp->config->poly_size); | ||
329 | } | ||
330 | } | ||
331 | #endif | ||
332 | |||
333 | return (crc ^ crcp->config->final_val) & mask; | ||
334 | } | ||
335 | |||
336 | #endif /* CRCSW_USE_CRC1 */ | ||
337 | |||
338 | #endif /* HAL_USE_CRC */ | ||
diff --git a/lib/chibios-contrib/os/various/crcsw.h b/lib/chibios-contrib/os/various/crcsw.h new file mode 100644 index 000000000..4483a3456 --- /dev/null +++ b/lib/chibios-contrib/os/various/crcsw.h | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2015 Michael D. Spradling | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file crcsw.h | ||
19 | * @brief CRC software driver. | ||
20 | * | ||
21 | * @addtogroup CRC | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #include "hal.h" | ||
26 | |||
27 | #if HAL_USE_CRC || defined(__DOXYGEN__) | ||
28 | |||
29 | #if CRCSW_USE_CRC1 || defined(__DOXYGEN__) | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Driver pre-compile time settings. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @name Configuration options | ||
37 | * @{ | ||
38 | */ | ||
39 | /** | ||
40 | * @brief CRC1 software driver enable switch. | ||
41 | * @details If set to @p TRUE the support for CRC1 is included. | ||
42 | * @note The default is @p FALSE | ||
43 | */ | ||
44 | #if !defined(CRCSW_USE_CRC1) || defined(__DOXYGEN__) | ||
45 | #define CRCSW_USE_CRC1 FALSE | ||
46 | #endif | ||
47 | |||
48 | /** | ||
49 | * @brief Enables software CRC32 | ||
50 | */ | ||
51 | #if !defined(CRCSW_CRC32_TABLE) || defined(__DOXYGEN__) | ||
52 | #define CRCSW_CRC32_TABLE FALSE | ||
53 | #endif | ||
54 | |||
55 | /** | ||
56 | * @brief Enables software CRC16 | ||
57 | */ | ||
58 | #if !defined(CRCSW_CRC16_TABLE) || defined(__DOXYGEN__) | ||
59 | #define CRCSW_CRC16_TABLE FALSE | ||
60 | #endif | ||
61 | |||
62 | /*===========================================================================*/ | ||
63 | /* Derived constants and error checks. */ | ||
64 | /*===========================================================================*/ | ||
65 | |||
66 | #if CRCSW_USE_CRC1 && CRC_USE_DMA | ||
67 | #error "Software CRC does not support DMA(CRC_USE_DMA)" | ||
68 | #endif | ||
69 | |||
70 | #if CRCSW_CRC32_TABLE == FALSE && CRCSW_CRC16_TABLE == FALSE && \ | ||
71 | CRCSW_PROGRAMMABLE == FALSE | ||
72 | #error "At least one of CRCSW_PROGRAMMABLE, CRCSW_CRC32_TABLE, or CRCSW_CRC16_TABLE must be defined" | ||
73 | #endif | ||
74 | |||
75 | /*===========================================================================*/ | ||
76 | /* Driver data structures and types. */ | ||
77 | /*===========================================================================*/ | ||
78 | /** | ||
79 | * @brief Type of a structure representing an CRC driver. | ||
80 | */ | ||
81 | typedef struct CRCDriver CRCDriver; | ||
82 | |||
83 | /** | ||
84 | * @brief Driver configuration structure. | ||
85 | */ | ||
86 | typedef struct { | ||
87 | /** | ||
88 | * @brief The size of polynomial to be used for CRC. | ||
89 | */ | ||
90 | uint32_t poly_size; | ||
91 | /** | ||
92 | * @brief The coefficients of the polynomial to be used for CRC. | ||
93 | */ | ||
94 | uint32_t poly; | ||
95 | /** | ||
96 | * @brief The inital value | ||
97 | */ | ||
98 | uint32_t initial_val; | ||
99 | /** | ||
100 | * @brief The final XOR value | ||
101 | */ | ||
102 | uint32_t final_val; | ||
103 | /** | ||
104 | * @brief Reflect bit order data going into CRC | ||
105 | */ | ||
106 | bool reflect_data; | ||
107 | /** | ||
108 | * @brief Reflect bit order of final remainder | ||
109 | */ | ||
110 | bool reflect_remainder; | ||
111 | /* End of the mandatory fields.*/ | ||
112 | /** | ||
113 | * @brief The crc lookup table to use when calculating CRC. | ||
114 | */ | ||
115 | const uint32_t *table; | ||
116 | } CRCConfig; | ||
117 | |||
118 | |||
119 | /** | ||
120 | * @brief Structure representing an CRC driver. | ||
121 | */ | ||
122 | struct CRCDriver { | ||
123 | /** | ||
124 | * @brief Driver state. | ||
125 | */ | ||
126 | crcstate_t state; | ||
127 | /** | ||
128 | * @brief Current configuration data. | ||
129 | */ | ||
130 | const CRCConfig *config; | ||
131 | #if CRC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) | ||
132 | /** | ||
133 | * @brief Mutex protecting the peripheral. | ||
134 | */ | ||
135 | mutex_t mutex; | ||
136 | #endif /* CRC_USE_MUTUAL_EXCLUSION */ | ||
137 | /* End of the mandatory fields.*/ | ||
138 | /** | ||
139 | * @brief Current value of calculated CRC. | ||
140 | */ | ||
141 | uint32_t crc; | ||
142 | }; | ||
143 | |||
144 | /*===========================================================================*/ | ||
145 | /* Driver macros. */ | ||
146 | /*===========================================================================*/ | ||
147 | #if CRCSW_CRC32_TABLE || defined(__DOXYGEN__) | ||
148 | /** | ||
149 | * @brief Configuration that represents CRC32 | ||
150 | */ | ||
151 | #define CRCSW_CRC32_TABLE_CONFIG (&crcsw_crc32_config) | ||
152 | #endif | ||
153 | |||
154 | #if CRCSW_CRC16_TABLE || defined(__DOXYGEN__) | ||
155 | /** | ||
156 | * @brief Configuration that represents CRC16 | ||
157 | */ | ||
158 | #define CRCSW_CRC16_TABLE_CONFIG (&crcsw_crc16_config) | ||
159 | #endif | ||
160 | |||
161 | /*===========================================================================*/ | ||
162 | /* Driver local definitions. */ | ||
163 | /*===========================================================================*/ | ||
164 | |||
165 | /*===========================================================================*/ | ||
166 | /* Driver exported variables. */ | ||
167 | /*===========================================================================*/ | ||
168 | |||
169 | /*===========================================================================*/ | ||
170 | /* Driver local variables and types. */ | ||
171 | /*===========================================================================*/ | ||
172 | |||
173 | /*===========================================================================*/ | ||
174 | /* Driver local functions. */ | ||
175 | /*===========================================================================*/ | ||
176 | |||
177 | /*===========================================================================*/ | ||
178 | /* Driver interrupt handlers. */ | ||
179 | /*===========================================================================*/ | ||
180 | |||
181 | /*===========================================================================*/ | ||
182 | /* Driver exported functions. */ | ||
183 | /*===========================================================================*/ | ||
184 | |||
185 | /*===========================================================================*/ | ||
186 | /* External declarations. */ | ||
187 | /*===========================================================================*/ | ||
188 | |||
189 | extern CRCDriver CRCD1; | ||
190 | |||
191 | #if CRCSW_CRC32_TABLE | ||
192 | extern const CRCConfig crcsw_crc32_config; | ||
193 | #endif | ||
194 | |||
195 | #if CRCSW_CRC16_TABLE | ||
196 | extern const CRCConfig crcsw_crc16_config; | ||
197 | #endif | ||
198 | |||
199 | #ifdef __cplusplus | ||
200 | extern "C" { | ||
201 | #endif | ||
202 | void crc_lld_init(void); | ||
203 | void crc_lld_start(CRCDriver *crcp); | ||
204 | void crc_lld_stop(CRCDriver *crcp); | ||
205 | void crc_lld_reset(CRCDriver *crcp); | ||
206 | uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf); | ||
207 | #ifdef __cplusplus | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | #endif /* CRCSW_USE_CRC1 */ | ||
212 | |||
213 | #endif /* HAL_USE_CRC */ | ||
214 | |||
215 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/dbgtrace.h b/lib/chibios-contrib/os/various/dbgtrace.h new file mode 100644 index 000000000..b1fc2979e --- /dev/null +++ b/lib/chibios-contrib/os/various/dbgtrace.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef DBGTRACE_H_ | ||
2 | #define DBGTRACE_H_ | ||
3 | |||
4 | #include "chprintf.h" | ||
5 | |||
6 | #if !defined(DEBUG_TRACE_PRINT) | ||
7 | #define DEBUG_TRACE_PRINT FALSE | ||
8 | #endif | ||
9 | |||
10 | #if !defined(DEBUG_TRACE_WARNING) | ||
11 | #define DEBUG_TRACE_WARNING FALSE | ||
12 | #endif | ||
13 | |||
14 | #if !defined(DEBUG_TRACE_ERROR) | ||
15 | #define DEBUG_TRACE_ERROR FALSE | ||
16 | #endif | ||
17 | |||
18 | /* user must provide correctly initialized pointer to print channel */ | ||
19 | #if DEBUG_TRACE_PRINT || DEBUG_TRACE_WARNING || DEBUG_TRACE_ERROR | ||
20 | extern BaseSequentialStream *GlobalDebugChannel; | ||
21 | #endif | ||
22 | |||
23 | #if DEBUG_TRACE_PRINT | ||
24 | #define dbgprintf(fmt, ...) chprintf(GlobalDebugChannel, fmt, ##__VA_ARGS__) | ||
25 | #else | ||
26 | #define dbgprintf(fmt, ...) do {} while(0) | ||
27 | #endif | ||
28 | |||
29 | #if DEBUG_TRACE_WARNING | ||
30 | #define warnprintf(fmt, ...) chprintf(GlobalDebugChannel, fmt, ##__VA_ARGS__) | ||
31 | #else | ||
32 | #define warnprintf(fmt, ...) do {} while(0) | ||
33 | #endif | ||
34 | |||
35 | #if DEBUG_TRACE_ERROR | ||
36 | #define errprintf(fmt, ...) chprintf(GlobalDebugChannel, fmt, ##__VA_ARGS__) | ||
37 | #else | ||
38 | #define errprintf(fmt, ...) do {} while(0) | ||
39 | #endif | ||
40 | |||
41 | #endif /* DBGTRACE_H_ */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.c b/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.c new file mode 100644 index 000000000..979e502cc --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | Copyright (C) 2013-2015 Andrea Zoppi | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file ili9341.c | ||
19 | * @brief ILI9341 TFT LCD diaplay controller driver. | ||
20 | * @note Does not support multiple calling threads natively. | ||
21 | */ | ||
22 | |||
23 | #include "ch.h" | ||
24 | #include "hal.h" | ||
25 | #include "ili9341.h" | ||
26 | |||
27 | /** | ||
28 | * @addtogroup ili9341 | ||
29 | * @{ | ||
30 | */ | ||
31 | |||
32 | /*===========================================================================*/ | ||
33 | /* Driver local definitions. */ | ||
34 | /*===========================================================================*/ | ||
35 | |||
36 | #if !ILI9341_USE_CHECKS && !defined(__DOXYGEN__) | ||
37 | /* Disable checks as needed.*/ | ||
38 | |||
39 | #ifdef osalDbgCheck | ||
40 | #undef osalDbgCheck | ||
41 | #endif | ||
42 | #define osalDbgCheck(c, func) { \ | ||
43 | (void)(c), (void)__QUOTE_THIS(func)"()"; \ | ||
44 | } | ||
45 | |||
46 | #ifdef osalDbgAssert | ||
47 | #undef osalDbgAssert | ||
48 | #endif | ||
49 | #define osalDbgAssert(c, m, r) { \ | ||
50 | (void)(c); \ | ||
51 | } | ||
52 | |||
53 | #ifdef osalDbgCheckClassS | ||
54 | #undef osalDbgCheckClassS | ||
55 | #endif | ||
56 | #define osalDbgCheckClassS() {} | ||
57 | |||
58 | #ifdef osalDbgCheckClassS | ||
59 | #undef osalDbgCheckClassS | ||
60 | #endif | ||
61 | #define osalDbgCheckClassI() {} | ||
62 | |||
63 | #endif /* ILI9341_USE_CHECKS */ | ||
64 | |||
65 | /*===========================================================================*/ | ||
66 | /* Driver exported variables. */ | ||
67 | /*===========================================================================*/ | ||
68 | |||
69 | /** @brief ILI9341D1 driver identifier.*/ | ||
70 | ILI9341Driver ILI9341D1; | ||
71 | |||
72 | /*===========================================================================*/ | ||
73 | /* Driver local variables and types. */ | ||
74 | /*===========================================================================*/ | ||
75 | |||
76 | /*===========================================================================*/ | ||
77 | /* Driver local functions. */ | ||
78 | /*===========================================================================*/ | ||
79 | |||
80 | /*===========================================================================*/ | ||
81 | /* Driver exported functions. */ | ||
82 | /*===========================================================================*/ | ||
83 | |||
84 | /** | ||
85 | * @brief Initializes the standard part of a @p ILI9341Driver structure. | ||
86 | * | ||
87 | * @param[out] driverp pointer to the @p ILI9341Driver object | ||
88 | * | ||
89 | * @init | ||
90 | */ | ||
91 | void ili9341ObjectInit(ILI9341Driver *driverp) { | ||
92 | |||
93 | osalDbgCheck(driverp != NULL); | ||
94 | |||
95 | driverp->state = ILI9341_STOP; | ||
96 | driverp->config = NULL; | ||
97 | #if (TRUE == ILI9341_USE_MUTUAL_EXCLUSION) | ||
98 | #if (TRUE == CH_CFG_USE_MUTEXES) | ||
99 | chMtxObjectInit(&driverp->lock); | ||
100 | #else | ||
101 | chSemObjectInit(&driverp->lock, 1); | ||
102 | #endif | ||
103 | #endif /* (TRUE == ILI9341_USE_MUTUAL_EXCLUSION) */ | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * @brief Configures and activates the ILI9341 peripheral. | ||
108 | * @pre ILI9341 is stopped. | ||
109 | * | ||
110 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
111 | * @param[in] configp pointer to the @p ILI9341Config object | ||
112 | * | ||
113 | * @api | ||
114 | */ | ||
115 | void ili9341Start(ILI9341Driver *driverp, const ILI9341Config *configp) { | ||
116 | |||
117 | chSysLock(); | ||
118 | osalDbgCheck(driverp != NULL); | ||
119 | osalDbgCheck(configp != NULL); | ||
120 | osalDbgCheck(configp->spi != NULL); | ||
121 | osalDbgAssert(driverp->state == ILI9341_STOP, "invalid state"); | ||
122 | |||
123 | spiSelectI(configp->spi); | ||
124 | spiUnselectI(configp->spi); | ||
125 | driverp->config = configp; | ||
126 | driverp->state = ILI9341_READY; | ||
127 | chSysUnlock(); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * @brief Deactivates the ILI9341 peripheral. | ||
132 | * @pre ILI9341 is ready. | ||
133 | * | ||
134 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
135 | * | ||
136 | * @api | ||
137 | */ | ||
138 | void ili9341Stop(ILI9341Driver *driverp) { | ||
139 | |||
140 | chSysLock(); | ||
141 | osalDbgCheck(driverp != NULL); | ||
142 | osalDbgAssert(driverp->state == ILI9341_READY, "invalid state"); | ||
143 | |||
144 | driverp->state = ILI9341_STOP; | ||
145 | chSysUnlock(); | ||
146 | } | ||
147 | |||
148 | #if ILI9341_USE_MUTUAL_EXCLUSION | ||
149 | |||
150 | /** | ||
151 | * @brief Gains exclusive access to the ILI9341 module. | ||
152 | * @details This function tries to gain ownership to the ILI9341 module, if the | ||
153 | * module is already being used then the invoking thread is queued. | ||
154 | * @pre In order to use this function the option | ||
155 | * @p ILI9341_USE_MUTUAL_EXCLUSION must be enabled. | ||
156 | * @pre ILI9341 is ready. | ||
157 | * | ||
158 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
159 | * | ||
160 | * @sclass | ||
161 | */ | ||
162 | void ili9341AcquireBusS(ILI9341Driver *driverp) { | ||
163 | |||
164 | osalDbgCheckClassS(); | ||
165 | osalDbgCheck(driverp == &ILI9341D1); | ||
166 | osalDbgAssert(driverp->state == ILI9341_READY, "not ready"); | ||
167 | |||
168 | #if (TRUE == CH_CFG_USE_MUTEXES) | ||
169 | chMtxLockS(&driverp->lock); | ||
170 | #else | ||
171 | chSemWaitS(&driverp->lock); | ||
172 | #endif | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * @brief Gains exclusive access to the ILI9341 module. | ||
177 | * @details This function tries to gain ownership to the ILI9341 module, if the | ||
178 | * module is already being used then the invoking thread is queued. | ||
179 | * @pre In order to use this function the option | ||
180 | * @p ILI9341_USE_MUTUAL_EXCLUSION must be enabled. | ||
181 | * @pre ILI9341 is ready. | ||
182 | * | ||
183 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
184 | * | ||
185 | * @api | ||
186 | */ | ||
187 | void ili9341AcquireBus(ILI9341Driver *driverp) { | ||
188 | |||
189 | chSysLock(); | ||
190 | ili9341AcquireBusS(driverp); | ||
191 | chSysUnlock(); | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * @brief Releases exclusive access to the ILI9341 module. | ||
196 | * @pre In order to use this function the option | ||
197 | * @p ILI9341_USE_MUTUAL_EXCLUSION must be enabled. | ||
198 | * @pre ILI9341 is ready. | ||
199 | * | ||
200 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
201 | * | ||
202 | * @sclass | ||
203 | */ | ||
204 | void ili9341ReleaseBusS(ILI9341Driver *driverp) { | ||
205 | |||
206 | osalDbgCheckClassS(); | ||
207 | osalDbgCheck(driverp == &ILI9341D1); | ||
208 | osalDbgAssert(driverp->state == ILI9341_READY, "not ready"); | ||
209 | |||
210 | #if (TRUE == CH_CFG_USE_MUTEXES) | ||
211 | chMtxUnlockS(&driverp->lock); | ||
212 | #else | ||
213 | chSemSignalI(&driverp->lock); | ||
214 | #endif | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * @brief Releases exclusive access to the ILI9341 module. | ||
219 | * @pre In order to use this function the option | ||
220 | * @p ILI9341_USE_MUTUAL_EXCLUSION must be enabled. | ||
221 | * @pre ILI9341 is ready. | ||
222 | * | ||
223 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
224 | * | ||
225 | * @api | ||
226 | */ | ||
227 | void ili9341ReleaseBus(ILI9341Driver *driverp) { | ||
228 | |||
229 | chSysLock(); | ||
230 | ili9341ReleaseBusS(driverp); | ||
231 | chSysUnlock(); | ||
232 | } | ||
233 | |||
234 | #endif /* ILI9341_USE_MUTUAL_EXCLUSION */ | ||
235 | |||
236 | #if ILI9341_IM == ILI9341_IM_4LSI_1 /* 4-wire, half-duplex */ | ||
237 | |||
238 | /** | ||
239 | * @brief Asserts the slave select signal and prepares for transfers. | ||
240 | * @pre ILI9341 is ready. | ||
241 | * | ||
242 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
243 | * | ||
244 | * @iclass | ||
245 | */ | ||
246 | void ili9341SelectI(ILI9341Driver *driverp) { | ||
247 | |||
248 | osalDbgCheckClassI(); | ||
249 | osalDbgCheck(driverp != NULL); | ||
250 | osalDbgAssert(driverp->state == ILI9341_READY, "invalid state"); | ||
251 | |||
252 | driverp->state = ILI9341_ACTIVE; | ||
253 | spiSelectI(driverp->config->spi); | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * @brief Asserts the slave select signal and prepares for transfers. | ||
258 | * @pre ILI9341 is ready. | ||
259 | * | ||
260 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
261 | * | ||
262 | * @api | ||
263 | */ | ||
264 | void ili9341Select(ILI9341Driver *driverp) { | ||
265 | |||
266 | chSysLock(); | ||
267 | ili9341SelectI(driverp); | ||
268 | chSysUnlock(); | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * @brief Deasserts the slave select signal. | ||
273 | * @details The previously selected peripheral is unselected. | ||
274 | * @pre ILI9341 is active. | ||
275 | * | ||
276 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
277 | * | ||
278 | * @iclass | ||
279 | */ | ||
280 | void ili9341UnselectI(ILI9341Driver *driverp) { | ||
281 | |||
282 | osalDbgCheckClassI(); | ||
283 | osalDbgCheck(driverp != NULL); | ||
284 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
285 | |||
286 | spiUnselectI(driverp->config->spi); | ||
287 | driverp->state = ILI9341_READY; | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * @brief Deasserts the slave select signal. | ||
292 | * @details The previously selected peripheral is unselected. | ||
293 | * @pre ILI9341 is active. | ||
294 | * | ||
295 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
296 | * | ||
297 | * @iclass | ||
298 | */ | ||
299 | void ili9341Unselect(ILI9341Driver *driverp) { | ||
300 | |||
301 | chSysLock(); | ||
302 | ili9341UnselectI(driverp); | ||
303 | chSysUnlock(); | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * @brief Write command byte. | ||
308 | * @details Sends a command byte via SPI. | ||
309 | * | ||
310 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
311 | * @param[in] cmd command byte | ||
312 | * | ||
313 | * @api | ||
314 | */ | ||
315 | void ili9341WriteCommand(ILI9341Driver *driverp, uint8_t cmd) { | ||
316 | |||
317 | osalDbgCheck(driverp != NULL); | ||
318 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
319 | |||
320 | driverp->value = cmd; | ||
321 | palClearPad(driverp->config->dcx_port, driverp->config->dcx_pad); /* !Cmd */ | ||
322 | spiSend(driverp->config->spi, 1, &driverp->value); | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * @brief Write data byte. | ||
327 | * @details Sends a data byte via SPI. | ||
328 | * | ||
329 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
330 | * @param[in] value data byte | ||
331 | * | ||
332 | * @api | ||
333 | */ | ||
334 | void ili9341WriteByte(ILI9341Driver *driverp, uint8_t value) { | ||
335 | |||
336 | osalDbgCheck(driverp != NULL); | ||
337 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
338 | |||
339 | driverp->value = value; | ||
340 | palSetPad(driverp->config->dcx_port, driverp->config->dcx_pad); /* Data */ | ||
341 | spiSend(driverp->config->spi, 1, &driverp->value); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * @brief Read data byte. | ||
346 | * @details Receives a data byte via SPI. | ||
347 | * | ||
348 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
349 | * | ||
350 | * @return data byte | ||
351 | * | ||
352 | * @api | ||
353 | */ | ||
354 | uint8_t ili9341ReadByte(ILI9341Driver *driverp) { | ||
355 | |||
356 | osalDbgAssert(FALSE, "should not be used"); | ||
357 | |||
358 | osalDbgCheck(driverp != NULL); | ||
359 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
360 | |||
361 | palSetPad(driverp->config->dcx_port, driverp->config->dcx_pad); /* Data */ | ||
362 | spiReceive(driverp->config->spi, 1, &driverp->value); | ||
363 | return driverp->value; | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * @brief Write data chunk. | ||
368 | * @details Sends a data chunk via SPI. | ||
369 | * @pre The chunk must be accessed by DMA. | ||
370 | * | ||
371 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
372 | * @param[in] chunk chunk bytes | ||
373 | * @param[in] length chunk length | ||
374 | * | ||
375 | * @api | ||
376 | */ | ||
377 | void ili9341WriteChunk(ILI9341Driver *driverp, const uint8_t chunk[], | ||
378 | size_t length) { | ||
379 | |||
380 | osalDbgCheck(driverp != NULL); | ||
381 | osalDbgCheck(chunk != NULL); | ||
382 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
383 | |||
384 | if (length != 0) { | ||
385 | palSetPad(driverp->config->dcx_port, driverp->config->dcx_pad); /* Data */ | ||
386 | spiSend(driverp->config->spi, length, chunk); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * @brief Read data chunk. | ||
392 | * @details Receives a data chunk via SPI. | ||
393 | * @pre The chunk must be accessed by DMA. | ||
394 | * | ||
395 | * @param[in] driverp pointer to the @p ILI9341Driver object | ||
396 | * @param[out] chunk chunk bytes | ||
397 | * @param[in] length chunk length | ||
398 | * | ||
399 | * @api | ||
400 | */ | ||
401 | void ili9341ReadChunk(ILI9341Driver *driverp, uint8_t chunk[], | ||
402 | size_t length) { | ||
403 | |||
404 | osalDbgCheck(driverp != NULL); | ||
405 | osalDbgCheck(chunk != NULL); | ||
406 | osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); | ||
407 | |||
408 | if (length != 0) { | ||
409 | palSetPad(driverp->config->dcx_port, driverp->config->dcx_pad); /* Data */ | ||
410 | spiReceive(driverp->config->spi, length, chunk); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | #else /* ILI9341_IM == * */ | ||
415 | #error "Only the ILI9341_IM_4LSI_1 interface mode is currently supported" | ||
416 | #endif /* ILI9341_IM == * */ | ||
417 | |||
418 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.h b/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.h new file mode 100644 index 000000000..007c4fd67 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.h | |||
@@ -0,0 +1,593 @@ | |||
1 | /* | ||
2 | Copyright (C) 2013-2015 Andrea Zoppi | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file ili9341.h | ||
19 | * @brief ILI9341 TFT LCD diaplay controller driver. | ||
20 | */ | ||
21 | |||
22 | #ifndef _ILI9341_H_ | ||
23 | #define _ILI9341_H_ | ||
24 | |||
25 | /** | ||
26 | * @addtogroup ili9341 | ||
27 | * @{ | ||
28 | */ | ||
29 | |||
30 | /*===========================================================================*/ | ||
31 | /* Driver constants. */ | ||
32 | /*===========================================================================*/ | ||
33 | |||
34 | /** | ||
35 | * @name ILI9341 regulative commands | ||
36 | * @{ | ||
37 | */ | ||
38 | #define ILI9341_CMD_NOP (0x00) /**< No operation.*/ | ||
39 | #define ILI9341_CMD_RESET (0x01) /**< Software reset.*/ | ||
40 | #define ILI9341_GET_ID_INFO (0x04) /**< Get ID information.*/ | ||
41 | #define ILI9341_GET_STATUS (0x09) /**< Get status.*/ | ||
42 | #define ILI9341_GET_PWR_MODE (0x0A) /**< Get power mode.*/ | ||
43 | #define ILI9341_GET_MADCTL (0x0B) /**< Get MADCTL.*/ | ||
44 | #define ILI9341_GET_PIX_FMT (0x0C) /**< Get pixel format.*/ | ||
45 | #define ILI9341_GET_IMG_FMT (0x0D) /**< Get image format.*/ | ||
46 | #define ILI9341_GET_SIG_MODE (0x0E) /**< Get signal mode.*/ | ||
47 | #define ILI9341_GET_SELF_DIAG (0x0F) /**< Get self-diagnostics.*/ | ||
48 | #define ILI9341_CMD_SLEEP_ON (0x10) /**< Enter sleep mode.*/ | ||
49 | #define ILI9341_CMD_SLEEP_OFF (0x11) /**< Exist sleep mode.*/ | ||
50 | #define ILI9341_CMD_PARTIAL_ON (0x12) /**< Enter partial mode.*/ | ||
51 | #define ILI9341_CMD_PARTIAL_OFF (0x13) /**< Exit partial mode.*/ | ||
52 | #define ILI9341_CMD_INVERT_ON (0x20) /**< Enter inverted mode.*/ | ||
53 | #define ILI9341_CMD_INVERT_OFF (0x21) /**< Exit inverted mode.*/ | ||
54 | #define ILI9341_SET_GAMMA (0x26) /**< Set gamma params.*/ | ||
55 | #define ILI9341_CMD_DISPLAY_OFF (0x28) /**< Disable display.*/ | ||
56 | #define ILI9341_CMD_DISPLAY_ON (0x29) /**< Enable display.*/ | ||
57 | #define ILI9341_SET_COL_ADDR (0x2A) /**< Set column address.*/ | ||
58 | #define ILI9341_SET_PAGE_ADDR (0x2B) /**< Set page address.*/ | ||
59 | #define ILI9341_SET_MEM (0x2C) /**< Set memory.*/ | ||
60 | #define ILI9341_SET_COLOR (0x2D) /**< Set color.*/ | ||
61 | #define ILI9341_GET_MEM (0x2E) /**< Get memory.*/ | ||
62 | #define ILI9341_SET_PARTIAL_AREA (0x30) /**< Set partial area.*/ | ||
63 | #define ILI9341_SET_VSCROLL (0x33) /**< Set vertical scroll def.*/ | ||
64 | #define ILI9341_CMD_TEARING_ON (0x34) /**< Tearing line enabled.*/ | ||
65 | #define ILI9341_CMD_TEARING_OFF (0x35) /**< Tearing line disabled.*/ | ||
66 | #define ILI9341_SET_MEM_ACS_CTL (0x36) /**< Set mem access ctl.*/ | ||
67 | #define ILI9341_SET_VSCROLL_ADDR (0x37) /**< Set vscroll start addr.*/ | ||
68 | #define ILI9341_CMD_IDLE_OFF (0x38) /**< Exit idle mode.*/ | ||
69 | #define ILI9341_CMD_IDLE_ON (0x39) /**< Enter idle mode.*/ | ||
70 | #define ILI9341_SET_PIX_FMT (0x3A) /**< Set pixel format.*/ | ||
71 | #define ILI9341_SET_MEM_CONT (0x3C) /**< Set memory continue.*/ | ||
72 | #define ILI9341_GET_MEM_CONT (0x3E) /**< Get memory continue.*/ | ||
73 | #define ILI9341_SET_TEAR_SCANLINE (0x44) /**< Set tearing scanline.*/ | ||
74 | #define ILI9341_GET_TEAR_SCANLINE (0x45) /**< Get tearing scanline.*/ | ||
75 | #define ILI9341_SET_BRIGHTNESS (0x51) /**< Set brightness.*/ | ||
76 | #define ILI9341_GET_BRIGHTNESS (0x52) /**< Get brightness.*/ | ||
77 | #define ILI9341_SET_DISPLAY_CTL (0x53) /**< Set display ctl.*/ | ||
78 | #define ILI9341_GET_DISPLAY_CTL (0x54) /**< Get display ctl.*/ | ||
79 | #define ILI9341_SET_CABC (0x55) /**< Set CABC.*/ | ||
80 | #define ILI9341_GET_CABC (0x56) /**< Get CABC.*/ | ||
81 | #define ILI9341_SET_CABC_MIN (0x5E) /**< Set CABC min.*/ | ||
82 | #define ILI9341_GET_CABC_MIN (0x5F) /**< Set CABC max.*/ | ||
83 | #define ILI9341_GET_ID1 (0xDA) /**< Get ID1.*/ | ||
84 | #define ILI9341_GET_ID2 (0xDB) /**< Get ID2.*/ | ||
85 | #define ILI9341_GET_ID3 (0xDC) /**< Get ID3.*/ | ||
86 | /** @} */ | ||
87 | |||
88 | /** | ||
89 | * @name ILI9341 extended commands | ||
90 | * @{ | ||
91 | */ | ||
92 | #define ILI9341_SET_RGB_IF_SIG_CTL (0xB0) /**< RGB IF signal ctl.*/ | ||
93 | #define ILI9341_SET_FRAME_CTL_NORMAL (0xB1) /**< Set frame ctl (normal).*/ | ||
94 | #define ILI9341_SET_FRAME_CTL_IDLE (0xB2) /**< Set frame ctl (idle).*/ | ||
95 | #define ILI9341_SET_FRAME_CTL_PARTIAL (0xB3) /**< Set frame ctl (partial).*/ | ||
96 | #define ILI9341_SET_INVERSION_CTL (0xB4) /**< Set inversion ctl.*/ | ||
97 | #define ILI9341_SET_BLANKING_PORCH_CTL (0xB5) /**< Set blanking porch ctl.*/ | ||
98 | #define ILI9341_SET_FUNCTION_CTL (0xB6) /**< Set function ctl.*/ | ||
99 | #define ILI9341_SET_ENTRY_MODE (0xB7) /**< Set entry mode.*/ | ||
100 | #define ILI9341_SET_LIGHT_CTL_1 (0xB8) /**< Set backlight ctl 1.*/ | ||
101 | #define ILI9341_SET_LIGHT_CTL_2 (0xB9) /**< Set backlight ctl 2.*/ | ||
102 | #define ILI9341_SET_LIGHT_CTL_3 (0xBA) /**< Set backlight ctl 3.*/ | ||
103 | #define ILI9341_SET_LIGHT_CTL_4 (0xBB) /**< Set backlight ctl 4.*/ | ||
104 | #define ILI9341_SET_LIGHT_CTL_5 (0xBC) /**< Set backlight ctl 5.*/ | ||
105 | #define ILI9341_SET_LIGHT_CTL_7 (0xBE) /**< Set backlight ctl 7.*/ | ||
106 | #define ILI9341_SET_LIGHT_CTL_8 (0xBF) /**< Set backlight ctl 8.*/ | ||
107 | #define ILI9341_SET_POWER_CTL_1 (0xC0) /**< Set power ctl 1.*/ | ||
108 | #define ILI9341_SET_POWER_CTL_2 (0xC1) /**< Set power ctl 2.*/ | ||
109 | #define ILI9341_SET_VCOM_CTL_1 (0xC5) /**< Set VCOM ctl 1.*/ | ||
110 | #define ILI9341_SET_VCOM_CTL_2 (0xC6) /**< Set VCOM ctl 2.*/ | ||
111 | #define ILI9341_SET_NVMEM (0xD0) /**< Set NVMEM data.*/ | ||
112 | #define ILI9341_GET_NVMEM_KEY (0xD1) /**< Get NVMEM protect key.*/ | ||
113 | #define ILI9341_GET_NVMEM_STATUS (0xD2) /**< Get NVMEM status.*/ | ||
114 | #define ILI9341_GET_ID4 (0xD3) /**< Get ID4.*/ | ||
115 | #define ILI9341_SET_PGAMMA (0xE0) /**< Set positive gamma.*/ | ||
116 | #define ILI9341_SET_NGAMMA (0xE1) /**< Set negative gamma.*/ | ||
117 | #define ILI9341_SET_DGAMMA_CTL_1 (0xE2) /**< Set digital gamma ctl 1.*/ | ||
118 | #define ILI9341_SET_DGAMMA_CTL_2 (0xE3) /**< Set digital gamma ctl 2.*/ | ||
119 | #define ILI9341_SET_IF_CTL (0xF6) /**< Set interface control.*/ | ||
120 | /** @} */ | ||
121 | |||
122 | /** | ||
123 | * @name ILI9341 interface modes | ||
124 | * @{ | ||
125 | */ | ||
126 | #define ILI9341_IM_3LSI_1 (0x5) /**< 3-line serial, mode 1.*/ | ||
127 | #define ILI9341_IM_3LSI_2 (0xD) /**< 3-line serial, mode 2.*/ | ||
128 | #define ILI9341_IM_4LSI_1 (0x6) /**< 4-line serial, mode 1.*/ | ||
129 | #define ILI9341_IM_4LSI_2 (0xE) /**< 4-line serial, mode 2.*/ | ||
130 | /** @} */ | ||
131 | |||
132 | /*===========================================================================*/ | ||
133 | /* Driver pre-compile time settings. */ | ||
134 | /*===========================================================================*/ | ||
135 | |||
136 | /** | ||
137 | * @name ILI9341 configuration options | ||
138 | * @{ | ||
139 | */ | ||
140 | |||
141 | /** | ||
142 | * @brief Enables the @p ili9341AcquireBus() and @p ili9341ReleaseBus() APIs. | ||
143 | * @note Disabling this option saves both code and data space. | ||
144 | */ | ||
145 | #if !defined(ILI9341_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) | ||
146 | #define ILI9341_USE_MUTUAL_EXCLUSION TRUE | ||
147 | #endif | ||
148 | |||
149 | /** | ||
150 | * @brief ILI9341 Interface Mode. | ||
151 | */ | ||
152 | #if !defined(ILI9341_IM) || defined(__DOXYGEN__) | ||
153 | #define ILI9341_IM (ILI9341_IM_4LSI_1) | ||
154 | #endif | ||
155 | |||
156 | /** | ||
157 | * @brief Enables checks for ILI9341 functions. | ||
158 | * @note Disabling this option saves both code and data space. | ||
159 | * @note Disabling checks by ChibiOS will automatically disable ILI9341 | ||
160 | * checks. | ||
161 | */ | ||
162 | #if !defined(ILI9341_USE_CHECKS) || defined(__DOXYGEN__) | ||
163 | #define ILI9341_USE_CHECKS TRUE | ||
164 | #endif | ||
165 | |||
166 | /** @} */ | ||
167 | |||
168 | /*===========================================================================*/ | ||
169 | /* Derived constants and error checks. */ | ||
170 | /*===========================================================================*/ | ||
171 | |||
172 | #if ((TRUE == ILI9341_USE_MUTUAL_EXCLUSION) && \ | ||
173 | (TRUE != CH_CFG_USE_MUTEXES) && \ | ||
174 | (TRUE != CH_CFG_USE_SEMAPHORES)) | ||
175 | #error "ILI9341_USE_MUTUAL_EXCLUSION requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" | ||
176 | #endif | ||
177 | |||
178 | /* TODO: Add the remaining modes.*/ | ||
179 | #if (ILI9341_IM != ILI9341_IM_4LSI_1) | ||
180 | #error "Only ILI9341_IM_4LSI_1 interface mode is supported currently" | ||
181 | #endif | ||
182 | |||
183 | /*===========================================================================*/ | ||
184 | /* Driver data structures and types. */ | ||
185 | /*===========================================================================*/ | ||
186 | |||
187 | /* Complex types forwarding.*/ | ||
188 | typedef struct ILI9341Config ILI9341Config; | ||
189 | typedef enum ili9341state_t ili9341state_t; | ||
190 | typedef struct ILI9341Driver ILI9341Driver; | ||
191 | |||
192 | /** | ||
193 | * @brief ILI9341 driver configuration. | ||
194 | */ | ||
195 | typedef struct ILI9341Config { | ||
196 | SPIDriver *spi; /**< SPI driver used by ILI9341.*/ | ||
197 | #if (ILI9341_IM == ILI9341_IM_4LSI_1) | ||
198 | ioportid_t dcx_port; /**< <tt>D/!C</tt> signal port.*/ | ||
199 | uint16_t dcx_pad; /**< <tt>D/!C</tt> signal pad.*/ | ||
200 | #endif /* ILI9341_IM == * */ /* TODO: Add all modes.*/ | ||
201 | } ILI9341Config; | ||
202 | |||
203 | /** | ||
204 | * @brief ILI9341 driver state. | ||
205 | */ | ||
206 | typedef enum ili9341state_t { | ||
207 | ILI9341_UNINIT = (0), /**< Not initialized.*/ | ||
208 | ILI9341_STOP = (1), /**< Stopped.*/ | ||
209 | ILI9341_READY = (2), /**< Ready.*/ | ||
210 | ILI9341_ACTIVE = (3), /**< Exchanging data.*/ | ||
211 | } ili9341state_t; | ||
212 | |||
213 | /** | ||
214 | * @brief ILI9341 driver. | ||
215 | */ | ||
216 | typedef struct ILI9341Driver { | ||
217 | ili9341state_t state; /**< Driver state.*/ | ||
218 | const ILI9341Config *config; /**< Driver configuration.*/ | ||
219 | |||
220 | /* Multithreading stuff.*/ | ||
221 | #if (TRUE == ILI9341_USE_MUTUAL_EXCLUSION) | ||
222 | #if (TRUE == CH_CFG_USE_MUTEXES) | ||
223 | mutex_t lock; /**< Multithreading lock.*/ | ||
224 | #elif (TRUE == CH_CFG_USE_SEMAPHORES) | ||
225 | semaphore_t lock; /**< Multithreading lock.*/ | ||
226 | #endif | ||
227 | #endif /* (TRUE == ILI9341_USE_MUTUAL_EXCLUSION) */ | ||
228 | |||
229 | /* Temporary variables.*/ | ||
230 | uint8_t value; /**< Non-stacked value, for SPI with CCM.*/ | ||
231 | } ILI9341Driver; | ||
232 | |||
233 | /** | ||
234 | * @name ILI9341 command params (little endian) | ||
235 | * @{ | ||
236 | */ | ||
237 | #pragma pack(push, 1) | ||
238 | |||
239 | typedef union { | ||
240 | struct ILI9341ParamBits_GET_ID_INFO { | ||
241 | uint8_t reserved_; | ||
242 | uint8_t ID1; | ||
243 | uint8_t ID2; | ||
244 | uint8_t ID3; | ||
245 | } bits; | ||
246 | uint8_t bytes[4]; | ||
247 | } ILI9341Params_GET_ID_INFO; | ||
248 | |||
249 | typedef union { | ||
250 | struct ILI9341ParamBits_GET_STATUS { | ||
251 | unsigned _reserved_1 : 5; /* D[ 4: 0] */ | ||
252 | unsigned tearing_mode : 1; /* D[ 5] */ | ||
253 | unsigned gamma_curve : 3; /* D[ 8: 6] */ | ||
254 | unsigned tearing : 1; /* D[ 9] */ | ||
255 | unsigned display : 1; /* D[10] */ | ||
256 | unsigned all_on : 1; /* D[11] */ | ||
257 | unsigned all_off : 1; /* D[12] */ | ||
258 | unsigned invert : 1; /* D[13] */ | ||
259 | unsigned _reserved_2 : 1; /* D[14] */ | ||
260 | unsigned vscroll : 1; /* D[15] */ | ||
261 | unsigned normal : 1; /* D[16] */ | ||
262 | unsigned sleep : 1; /* D[17] */ | ||
263 | unsigned partial : 1; /* D[18] */ | ||
264 | unsigned idle : 1; /* D[19] */ | ||
265 | unsigned pixel_format : 3; /* D[22:20] */ | ||
266 | unsigned _reserved_3 : 2; /* D[24:23] */ | ||
267 | unsigned hrefr_rtl_nltr : 1; /* D[25] */ | ||
268 | unsigned bgr_nrgb : 1; /* D[26] */ | ||
269 | unsigned vrefr_btt_nttb : 1; /* D[27] */ | ||
270 | unsigned transpose : 1; /* D[28] */ | ||
271 | unsigned coladr_rtl_nltr : 1; /* D[29] */ | ||
272 | unsigned rowadr_btt_nttb : 1; /* D[30] */ | ||
273 | unsigned booster : 1; /* D[31] */ | ||
274 | } bits; | ||
275 | uint8_t bytes[4]; | ||
276 | } ILI9341Params_GET_STATUS; | ||
277 | |||
278 | typedef union { | ||
279 | struct ILI9341ParamBits_GET_PWR_MODE { | ||
280 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
281 | unsigned display : 1; /* D[2] */ | ||
282 | unsigned normal : 1; /* D[3] */ | ||
283 | unsigned sleep : 1; /* D[4] */ | ||
284 | unsigned partial : 1; /* D[5] */ | ||
285 | unsigned idle : 1; /* D[6] */ | ||
286 | unsigned booster : 1; /* D[7] */ | ||
287 | } bits; | ||
288 | uint8_t bytes[1]; | ||
289 | } ILI9341Params_GET_PWR_MODE; | ||
290 | |||
291 | typedef union { | ||
292 | struct ILI9341ParamBits_GET_MADCTL { | ||
293 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
294 | unsigned refr_rtl_nltr : 1; /* D[2] */ | ||
295 | unsigned bgr_nrgb : 1; /* D[3] */ | ||
296 | unsigned refr_btt_nttb : 1; /* D[4] */ | ||
297 | unsigned invert : 1; /* D[5] */ | ||
298 | unsigned rtl_nltr : 1; /* D[6] */ | ||
299 | unsigned btt_nttb : 1; /* D[7] */ | ||
300 | } bits; | ||
301 | uint8_t bytes[1]; | ||
302 | } ILI9341Params_GET_MADCTL; | ||
303 | |||
304 | typedef union { | ||
305 | struct ILI9341ParamBits_GET_PIX_FMT { | ||
306 | unsigned DBI : 3; /* D[2:0] */ | ||
307 | unsigned _reserved_1 : 1; /* D[3] */ | ||
308 | unsigned DPI : 3; /* D[6:4] */ | ||
309 | unsigned RIM : 1; /* D[7] */ | ||
310 | } bits; | ||
311 | uint8_t bytes[1]; | ||
312 | } ILI9341Params_GET_PIX_FMT; | ||
313 | |||
314 | typedef union { | ||
315 | struct ILI9341ParamBits_GET_IMG_FMT { | ||
316 | unsigned gamma_curve : 3; /* D[2:0] */ | ||
317 | unsigned _reserved_1 : 5; /* D[7:3] */ | ||
318 | } bits; | ||
319 | uint8_t bytes[1]; | ||
320 | } ILI9341Params_GET_IMG_FMT; | ||
321 | |||
322 | typedef union { | ||
323 | struct ILI9341ParamBits_GET_SIG_MODE { | ||
324 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
325 | unsigned data_enable : 1; /* D[2] */ | ||
326 | unsigned pixel_clock : 1; /* D[3] */ | ||
327 | unsigned vsync : 1; /* D[4] */ | ||
328 | unsigned hsync : 1; /* D[5] */ | ||
329 | unsigned tearing_mode : 1; /* D[6] */ | ||
330 | unsigned tearing : 1; /* D[7] */ | ||
331 | } bits; | ||
332 | uint8_t bytes[1]; | ||
333 | } ILI9341Params_GET_SIG_MODE; | ||
334 | |||
335 | typedef union { | ||
336 | struct ILI9341ParamBits_GET_SELF_DIAG { | ||
337 | unsigned _reserved_1 : 6; /* D[5:0] */ | ||
338 | unsigned func_err : 1; /* D[6] */ | ||
339 | unsigned reg_err : 1; /* D[7] */ | ||
340 | } bits; | ||
341 | uint8_t bytes[1]; | ||
342 | } ILI9341Params_GET_SELF_DIAG; | ||
343 | |||
344 | typedef union { | ||
345 | struct ILI9341ParamBits_SET_GAMMA { | ||
346 | uint8_t gamma_curve; /* D[7:0] */ | ||
347 | } bits; | ||
348 | uint8_t bytes[1]; | ||
349 | } ILI9341Params_SET_GAMMA; | ||
350 | |||
351 | typedef union { | ||
352 | struct ILI9341ParamBits_SET_COL_ADDR { | ||
353 | uint8_t SC_15_8; /* D[ 7: 0] */ | ||
354 | uint8_t SC_7_0; /* D[15: 8] */ | ||
355 | uint8_t EC_15_8; /* D[23:16] */ | ||
356 | uint8_t EC_7_0; /* D[31:24] */ | ||
357 | } bits; | ||
358 | uint8_t bytes[4]; | ||
359 | } ILI9341Params_SET_COL_ADDR; | ||
360 | |||
361 | typedef union { | ||
362 | struct ILI9341ParamBits_SET_PAGE_ADDR { | ||
363 | uint8_t SP_15_8; /* D[ 7: 0] */ | ||
364 | uint8_t SP_7_0; /* D[15: 8] */ | ||
365 | uint8_t EP_15_8; /* D[23:16] */ | ||
366 | uint8_t EP_7_0; /* D[31:24] */ | ||
367 | } bits; | ||
368 | uint8_t bytes[4]; | ||
369 | } ILI9341Params_SET_PAGE_ADDR; | ||
370 | |||
371 | typedef union { | ||
372 | struct ILI9341ParamBits_SET_PARTIAL_AREA { | ||
373 | uint8_t SR_15_8; /* D[ 7: 0] */ | ||
374 | uint8_t SR_7_0; /* D[15: 8] */ | ||
375 | uint8_t ER_15_8; /* D[23:16] */ | ||
376 | uint8_t ER_7_0; /* D[31:24] */ | ||
377 | } bits; | ||
378 | uint8_t bytes[4]; | ||
379 | } ILI9341Params_SET_PARTIAL_AREA; | ||
380 | |||
381 | typedef union { | ||
382 | struct ILI9341ParamBits_SET_VSCROLL { | ||
383 | uint8_t TFA_15_8; /* D[ 7: 0] */ | ||
384 | uint8_t TFA_7_0; /* D[15: 8] */ | ||
385 | uint8_t VSA_15_8; /* D[23:16] */ | ||
386 | uint8_t VSA_7_0; /* D[31:24] */ | ||
387 | uint8_t BFA_15_8; /* D[39:32] */ | ||
388 | uint8_t BFA_7_0; /* D[47:40] */ | ||
389 | } bits; | ||
390 | uint8_t bytes[6]; | ||
391 | } ILI9341Params_SET_VSCROLL; | ||
392 | |||
393 | typedef union { | ||
394 | struct ILI9341ParamBits_CMD_TEARING_ON { | ||
395 | unsigned M : 1; /* D[0] */ | ||
396 | unsigned _reserved_1 : 7; /* D[7:1] */ | ||
397 | } bits; | ||
398 | uint8_t bytes[1]; | ||
399 | } ILI9341Params_CMD_TEARING_ON; | ||
400 | |||
401 | typedef union { | ||
402 | struct ILI9341ParamBits_SET_MEM_ACS_CTL { | ||
403 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
404 | unsigned MH : 1; /* D[2] */ | ||
405 | unsigned BGR : 1; /* D[3] */ | ||
406 | unsigned ML : 1; /* D[4] */ | ||
407 | unsigned MV : 1; /* D[5] */ | ||
408 | unsigned MX : 1; /* D[6] */ | ||
409 | unsigned MY : 1; /* D[7] */ | ||
410 | } bits; | ||
411 | uint8_t bytes[1]; | ||
412 | } ILI9341Params_SET_MEM_ACS_CTL; | ||
413 | |||
414 | typedef union { | ||
415 | struct ILI9341ParamBits_SET_VSCROLL_ADDR { | ||
416 | uint8_t VSP_15_8; /* D[ 7: 0] */ | ||
417 | uint8_t VSP_7_0; /* D[15: 8] */ | ||
418 | } bits; | ||
419 | uint8_t bytes[2]; | ||
420 | } ILI9341Params_SET_VSCROLL_ADDR; | ||
421 | |||
422 | typedef union { | ||
423 | struct ILI9341ParamBits_SET_PIX_FMT { | ||
424 | unsigned DBI : 3; /* D[2:0] */ | ||
425 | unsigned _reserved_1 : 1; /* D[3] */ | ||
426 | unsigned DPI : 3; /* D[4:6] */ | ||
427 | unsigned _reserved_2 : 1; /* D[7] */ | ||
428 | } bits; | ||
429 | uint8_t bytes[1]; | ||
430 | } ILI9341Params_SET_PIX_FMT; | ||
431 | |||
432 | typedef union { | ||
433 | struct ILI9341ParamBits_SET_TEAR_SCANLINE { | ||
434 | uint8_t STS_8; /* D[ 7: 0] */ | ||
435 | uint8_t STS_7_0; /* D[15: 8] */ | ||
436 | } bits; | ||
437 | uint8_t bytes[4]; | ||
438 | } ILI9341Params_SET_TEAR_SCANLINE; | ||
439 | |||
440 | typedef union { | ||
441 | struct ILI9341ParamBits_GET_TEAR_SCANLINE { | ||
442 | uint8_t GTS_9_8; /* D[ 7: 0] */ | ||
443 | uint8_t GTS_7_0; /* D[15: 8] */ | ||
444 | } bits; | ||
445 | uint8_t bytes[2]; | ||
446 | } ILI9341Params_GET_TEAR_SCANLINE; | ||
447 | |||
448 | typedef union { | ||
449 | struct ILI9341ParamBits_SET_BRIGHTNESS { | ||
450 | uint8_t DBV; /* D[7:0] */ | ||
451 | } bits; | ||
452 | uint8_t bytes[1]; | ||
453 | } ILI9341Params_SET_BRIGHTNESS; | ||
454 | |||
455 | typedef union { | ||
456 | struct ILI9341ParamBits_GET_BRIGHTNESS { | ||
457 | uint8_t DBV; /* D[7:0] */ | ||
458 | } bits; | ||
459 | uint8_t bytes[1]; | ||
460 | } ILI9341Params_GET_BRIGHTNESS; | ||
461 | |||
462 | typedef union { | ||
463 | struct ILI9341ParamBits_SET_DISPLAY_CTL { | ||
464 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
465 | unsigned BL : 1; /* D[2] */ | ||
466 | unsigned DD : 1; /* D[3] */ | ||
467 | unsigned _reserved_2 : 1; /* D[4] */ | ||
468 | unsigned BCTRL : 1; /* D[5] */ | ||
469 | unsigned _reserved_3 : 1; /* D[7:6] */ | ||
470 | } bits; | ||
471 | uint8_t bytes[1]; | ||
472 | } ILI9341Params_SET_DISPLAY_CTL; | ||
473 | |||
474 | typedef union { | ||
475 | struct ILI9341ParamBits_GET_DISPLAY_CTL { | ||
476 | unsigned _reserved_1 : 2; /* D[1:0] */ | ||
477 | unsigned BL : 1; /* D[2] */ | ||
478 | unsigned DD : 1; /* D[3] */ | ||
479 | unsigned _reserved_2 : 1; /* D[4] */ | ||
480 | unsigned BCTRL : 1; /* D[5] */ | ||
481 | unsigned _reserved_3 : 1; /* D[7:6] */ | ||
482 | } bits; | ||
483 | uint8_t bytes[1]; | ||
484 | } ILI9341Params_GET_DISPLAY_CTL; | ||
485 | |||
486 | typedef union { | ||
487 | struct ILI9341ParamBits_SET_CABC { | ||
488 | unsigned C : 2; /* D[1:0] */ | ||
489 | unsigned _reserved_1 : 6; /* D[7:2] */ | ||
490 | } bits; | ||
491 | uint8_t bytes[1]; | ||
492 | } ILI9341Params_SET_CABC; | ||
493 | |||
494 | typedef union { | ||
495 | struct ILI9341ParamBits_GET_CABC { | ||
496 | unsigned C : 2; /* D[1:0] */ | ||
497 | unsigned _reserved_1 : 6; /* D[7:2] */ | ||
498 | } bits; | ||
499 | uint8_t bytes[1]; | ||
500 | } ILI9341Params_GET_CABC; | ||
501 | |||
502 | typedef union { | ||
503 | struct ILI9341ParamBits_SET_CABC_MIN { | ||
504 | uint8_t CMB; /* D[7:0] */ | ||
505 | } bits; | ||
506 | uint8_t bytes[1]; | ||
507 | } ILI9341Params_SET_CABC_MIN; | ||
508 | |||
509 | typedef union { | ||
510 | struct ILI9341ParamBits_GET_CABC_MIN { | ||
511 | uint8_t CMB; /* D[7:0] */ | ||
512 | } bits; | ||
513 | uint8_t bytes[1]; | ||
514 | } ILI9341Params_GET_CABC_MIN; | ||
515 | |||
516 | #if 0 /* TODO: Extended command structs.*/ | ||
517 | |||
518 | typedef union { | ||
519 | struct ILI9341ParamBits { | ||
520 | unsigned : 1; /* D[] */ | ||
521 | unsigned : 1; /* D[] */ | ||
522 | unsigned : 1; /* D[] */ | ||
523 | unsigned : 1; /* D[] */ | ||
524 | unsigned : 1; /* D[] */ | ||
525 | unsigned : 1; /* D[] */ | ||
526 | unsigned : 1; /* D[] */ | ||
527 | unsigned : 1; /* D[] */ | ||
528 | } bits; | ||
529 | uint8_t bytes[1]; | ||
530 | } ILI9341Params_; | ||
531 | |||
532 | typedef union { | ||
533 | struct ILI9341ParamBits { | ||
534 | unsigned : 1; /* D[] */ | ||
535 | unsigned : 1; /* D[] */ | ||
536 | unsigned : 1; /* D[] */ | ||
537 | unsigned : 1; /* D[] */ | ||
538 | unsigned : 1; /* D[] */ | ||
539 | unsigned : 1; /* D[] */ | ||
540 | unsigned : 1; /* D[] */ | ||
541 | unsigned : 1; /* D[] */ | ||
542 | } bits; | ||
543 | uint8_t bytes[1]; | ||
544 | } ILI9341Params_; | ||
545 | |||
546 | #endif /*0*/ | ||
547 | |||
548 | #pragma pack(pop) | ||
549 | |||
550 | /** @} */ | ||
551 | |||
552 | /*===========================================================================*/ | ||
553 | /* Driver macros. */ | ||
554 | /*===========================================================================*/ | ||
555 | |||
556 | /*===========================================================================*/ | ||
557 | /* External declarations. */ | ||
558 | /*===========================================================================*/ | ||
559 | |||
560 | extern ILI9341Driver ILI9341D1; | ||
561 | |||
562 | #ifdef __cplusplus | ||
563 | extern "C" { | ||
564 | #endif | ||
565 | |||
566 | void ili9341ObjectInit(ILI9341Driver *driverp); | ||
567 | void ili9341Start(ILI9341Driver *driverp, const ILI9341Config *configp); | ||
568 | void ili9341Stop(ILI9341Driver *driverp); | ||
569 | #if (ILI9341_USE_MUTUAL_EXCLUSION == TRUE) | ||
570 | void ili9341AcquireBusS(ILI9341Driver *driverp); | ||
571 | void ili9341AcquireBus(ILI9341Driver *driverp); | ||
572 | void ili9341ReleaseBusS(ILI9341Driver *driverp); | ||
573 | void ili9341ReleaseBus(ILI9341Driver *driverp); | ||
574 | #endif /* (ILI9341_USE_MUTUAL_EXCLUSION == TRUE) */ | ||
575 | void ili9341SelectI(ILI9341Driver *driverp); | ||
576 | void ili9341Select(ILI9341Driver *driverp); | ||
577 | void ili9341UnselectI(ILI9341Driver *driverp); | ||
578 | void ili9341Unselect(ILI9341Driver *driverp); | ||
579 | void ili9341WriteCommand(ILI9341Driver *driverp, uint8_t cmd); | ||
580 | void ili9341WriteByte(ILI9341Driver *driverp, uint8_t value); | ||
581 | uint8_t ili9341ReadByte(ILI9341Driver *driverp); | ||
582 | void ili9341WriteChunk(ILI9341Driver *driverp, const uint8_t chunk[], | ||
583 | size_t length); | ||
584 | void ili9341ReadChunk(ILI9341Driver *driverp, uint8_t chunk[], | ||
585 | size_t length); | ||
586 | |||
587 | #ifdef __cplusplus | ||
588 | } | ||
589 | #endif | ||
590 | |||
591 | /** @} */ | ||
592 | |||
593 | #endif /* _ILI9341_H_ */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.c b/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.c new file mode 100644 index 000000000..1cc52c931 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file l3gd20.c | ||
31 | * @brief L3GD20 MEMS interface module code. | ||
32 | * | ||
33 | * @addtogroup l3gd20 | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "l3gd20.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Driver exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Driver local variables and types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Driver local functions. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Driver exported functions. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /** | ||
63 | * @brief Reads a generic register value. | ||
64 | * @pre The SPI interface must be initialized and the driver started. | ||
65 | * | ||
66 | * @param[in] spip pointer to the SPI interface | ||
67 | * @param[in] reg register number | ||
68 | * @return register value. | ||
69 | */ | ||
70 | uint8_t l3gd20ReadRegister(SPIDriver *spip, uint8_t reg) { | ||
71 | uint8_t txbuf[2] = {L3GD20_RW | reg, 0xFF}; | ||
72 | uint8_t rxbuf[2] = {0x00, 0x00}; | ||
73 | spiSelect(spip); | ||
74 | spiExchange(spip, 2, txbuf, rxbuf); | ||
75 | spiUnselect(spip); | ||
76 | return rxbuf[1]; | ||
77 | } | ||
78 | |||
79 | |||
80 | void l3gd20WriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value) { | ||
81 | |||
82 | switch (reg) { | ||
83 | |||
84 | default: | ||
85 | /* Reserved register must not be written, according to the datasheet | ||
86 | * this could permanently damage the device. | ||
87 | */ | ||
88 | chDbgAssert(FALSE, "lg3d20WriteRegister(), reserved register"); | ||
89 | case L3GD20_AD_WHO_AM_I: | ||
90 | case L3GD20_AD_OUT_TEMP : | ||
91 | case L3GD20_AD_STATUS_REG: | ||
92 | case L3GD20_AD_OUT_X_L: | ||
93 | case L3GD20_AD_OUT_X_H: | ||
94 | case L3GD20_AD_OUT_Y_L: | ||
95 | case L3GD20_AD_OUT_Y_H: | ||
96 | case L3GD20_AD_OUT_Z_L: | ||
97 | case L3GD20_AD_OUT_Z_H: | ||
98 | case L3GD20_AD_FIFO_SRC_REG: | ||
99 | case L3GD20_AD_INT1_SRC: | ||
100 | /* Read only registers cannot be written, the command is ignored.*/ | ||
101 | return; | ||
102 | case L3GD20_AD_CTRL_REG1: | ||
103 | case L3GD20_AD_CTRL_REG2: | ||
104 | case L3GD20_AD_CTRL_REG3: | ||
105 | case L3GD20_AD_CTRL_REG4: | ||
106 | case L3GD20_AD_CTRL_REG5: | ||
107 | case L3GD20_AD_REFERENCE: | ||
108 | case L3GD20_AD_FIFO_CTRL_REG: | ||
109 | case L3GD20_AD_INT1_CFG: | ||
110 | case L3GD20_AD_INT1_TSH_XH: | ||
111 | case L3GD20_AD_INT1_TSH_XL: | ||
112 | case L3GD20_AD_INT1_TSH_YH: | ||
113 | case L3GD20_AD_INT1_TSH_YL: | ||
114 | case L3GD20_AD_INT1_TSH_ZH: | ||
115 | case L3GD20_AD_INT1_TSH_ZL: | ||
116 | case L3GD20_AD_INT1_DURATION: | ||
117 | spiSelect(spip); | ||
118 | uint8_t txbuf[2] = {reg, value}; | ||
119 | spiSend(spip, 2, txbuf); | ||
120 | spiUnselect(spip); | ||
121 | } | ||
122 | } | ||
123 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.h b/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.h new file mode 100644 index 000000000..08d90927e --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.h | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file l3gd20.h | ||
31 | * @brief L3GD20 MEMS interface module header. | ||
32 | * | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef _L3GD20_H_ | ||
37 | #define _L3GD20_H_ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Driver constants. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | #define L3GD20_SENS_250DPS ((float)131.072f) /*!< gyroscope sensitivity with 250 dps full scale [LSB/dps] */ | ||
44 | #define L3GD20_SENS_500DPS ((float)65.536f) /*!< gyroscope sensitivity with 500 dps full scale [LSB/dps] */ | ||
45 | #define L3GD20_SENS_2000DPS ((float)16.384f) /*!< gyroscope sensitivity with 2000 dps full scale [LSB/dps] */ | ||
46 | /** | ||
47 | * @name L3GD20 register names | ||
48 | * @{ | ||
49 | */ | ||
50 | /******************************************************************************/ | ||
51 | /* */ | ||
52 | /* L3GD20 on board MEMS */ | ||
53 | /* */ | ||
54 | /******************************************************************************/ | ||
55 | /******************* Bit definition for SPI communication *******************/ | ||
56 | #define L3GD20_DI ((uint8_t)0xFF) /*!< DI[7:0] Data input */ | ||
57 | #define L3GD20_DI_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
58 | #define L3GD20_DI_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
59 | #define L3GD20_DI_2 ((uint8_t)0x04) /*!< bit 2 */ | ||
60 | #define L3GD20_DI_3 ((uint8_t)0x08) /*!< bit 3 */ | ||
61 | #define L3GD20_DI_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
62 | #define L3GD20_DI_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
63 | #define L3GD20_DI_6 ((uint8_t)0x40) /*!< bit 6 */ | ||
64 | #define L3GD20_DI_7 ((uint8_t)0x80) /*!< bit 7 */ | ||
65 | |||
66 | #define L3GD20_AD ((uint8_t)0x3F) /*!< AD[5:0] Address Data */ | ||
67 | #define L3GD20_AD_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
68 | #define L3GD20_AD_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
69 | #define L3GD20_AD_2 ((uint8_t)0x04) /*!< bit 2 */ | ||
70 | #define L3GD20_AD_3 ((uint8_t)0x08) /*!< bit 3 */ | ||
71 | #define L3GD20_AD_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
72 | #define L3GD20_AD_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
73 | |||
74 | #define L3GD20_MS ((uint8_t)0x40) /*!< Multiple read write */ | ||
75 | #define L3GD20_RW ((uint8_t)0x80) /*!< Read Write, 1 0 */ | ||
76 | |||
77 | /****************** Bit definition for Registers Addresses *******************/ | ||
78 | #define L3GD20_AD_WHO_AM_I ((uint8_t)0x0F) /*!< WHO I AM */ | ||
79 | #define L3GD20_AD_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 */ | ||
80 | #define L3GD20_AD_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 */ | ||
81 | #define L3GD20_AD_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 */ | ||
82 | #define L3GD20_AD_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 */ | ||
83 | #define L3GD20_AD_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 */ | ||
84 | #define L3GD20_AD_REFERENCE ((uint8_t)0x25) /*!< REFERENCE/DATACAPTURE */ | ||
85 | #define L3GD20_AD_OUT_TEMP ((uint8_t)0x26) /*!< MEMS ONBOARD TEMP SENSOR */ | ||
86 | #define L3GD20_AD_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER */ | ||
87 | #define L3GD20_AD_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW */ | ||
88 | #define L3GD20_AD_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH */ | ||
89 | #define L3GD20_AD_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW */ | ||
90 | #define L3GD20_AD_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH */ | ||
91 | #define L3GD20_AD_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW */ | ||
92 | #define L3GD20_AD_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH */ | ||
93 | #define L3GD20_AD_FIFO_CTRL_REG ((uint8_t)0x2E) /*!< FIFO CONTROL REGISTER */ | ||
94 | #define L3GD20_AD_FIFO_SRC_REG ((uint8_t)0x2F) /*!< FIFO SOURCE REGISTER */ | ||
95 | #define L3GD20_AD_INT1_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG REGISTER */ | ||
96 | #define L3GD20_AD_INT1_SRC ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE REGISTER */ | ||
97 | #define L3GD20_AD_INT1_TSH_XH ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD X-AXIS HIGH */ | ||
98 | #define L3GD20_AD_INT1_TSH_XL ((uint8_t)0x33) /*!< INTERRUPT1 THRESHOLD X-AXIS LOW */ | ||
99 | #define L3GD20_AD_INT1_TSH_YH ((uint8_t)0x34) /*!< INTERRUPT1 THRESHOLD Y-AXIS HIGH */ | ||
100 | #define L3GD20_AD_INT1_TSH_YL ((uint8_t)0x35) /*!< INTERRUPT1 THRESHOLD Y-AXIS LOW */ | ||
101 | #define L3GD20_AD_INT1_TSH_ZH ((uint8_t)0x36) /*!< INTERRUPT1 THRESHOLD Z-AXIS HIGH */ | ||
102 | #define L3GD20_AD_INT1_TSH_ZL ((uint8_t)0x37) /*!< INTERRUPT1 THRESHOLD Z-AXIS LOW */ | ||
103 | #define L3GD20_AD_INT1_DURATION ((uint8_t)0x38) /*!< INTERRUPT1 DURATION */ | ||
104 | |||
105 | /** @} */ | ||
106 | |||
107 | /*===========================================================================*/ | ||
108 | /* Driver pre-compile time settings. */ | ||
109 | /*===========================================================================*/ | ||
110 | |||
111 | /*===========================================================================*/ | ||
112 | /* Derived constants and error checks. */ | ||
113 | /*===========================================================================*/ | ||
114 | |||
115 | /*===========================================================================*/ | ||
116 | /* Driver data structures and types. */ | ||
117 | /*===========================================================================*/ | ||
118 | |||
119 | /** | ||
120 | * @name Gyroscope data structures and types | ||
121 | * @{ | ||
122 | */ | ||
123 | |||
124 | /** | ||
125 | * @brief Gyroscope Output Data Rate | ||
126 | */ | ||
127 | typedef enum { | ||
128 | L3GD20_ODR_95Hz_Fc_12_5 = 0x00, /*!< Output Data Rate = 95 Hz - LPF Cut-Off = 12.5 Hz */ | ||
129 | L3GD20_ODR_95Hz_Fc_25 = 0x10, /*!< Output Data Rate = 95 Hz - LPF Cut-Off = 25 Hz */ | ||
130 | L3GD20_ODR_190Hz_Fc_12_5 = 0x40, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 12.5 Hz */ | ||
131 | L3GD20_ODR_190Hz_Fc_25 = 0x50, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 25 Hz */ | ||
132 | L3GD20_ODR_190Hz_Fc_50 = 0x60, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 50 Hz */ | ||
133 | L3GD20_ODR_190Hz_Fc_70 = 0x70, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 70 Hz */ | ||
134 | L3GD20_ODR_380Hz_Fc_20 = 0x80, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 20 Hz */ | ||
135 | L3GD20_ODR_380Hz_Fc_25 = 0x90, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 25 Hz */ | ||
136 | L3GD20_ODR_380Hz_Fc_50 = 0xA0, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 50 Hz */ | ||
137 | L3GD20_ODR_380Hz_Fc_100 = 0xB0, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 100 Hz */ | ||
138 | L3GD20_ODR_760Hz_Fc_30 = 0xC0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 30 Hz */ | ||
139 | L3GD20_ODR_760Hz_Fc_35 = 0xD0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 35 Hz */ | ||
140 | L3GD20_ODR_760Hz_Fc_50 = 0xE0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 50 Hz */ | ||
141 | L3GD20_ODR_760Hz_Fc_100 = 0xF0 /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 100 Hz */ | ||
142 | }L3GD20_ODR_t; | ||
143 | |||
144 | /** | ||
145 | * @brief Gyroscope Power Mode | ||
146 | */ | ||
147 | typedef enum { | ||
148 | L3GD20_PM_POWER_DOWN = 0x00, /*!< Normal mode enabled */ | ||
149 | L3GD20_PM_SLEEP_NORMAL = 0x08 /*!< Low Power mode enabled */ | ||
150 | }L3GD20_PM_t; | ||
151 | |||
152 | /** | ||
153 | * @brief Gyroscope Full Scale | ||
154 | */ | ||
155 | typedef enum { | ||
156 | L3GD20_FS_250DPS = 0x00, /*!< �250 dps */ | ||
157 | L3GD20_FS_500DPS = 0x10, /*!< �500 dps */ | ||
158 | L3GD20_FS_2000DPS = 0x20 /*!< �200 dps */ | ||
159 | }L3GD20_FS_t; | ||
160 | |||
161 | /** | ||
162 | * @brief Gyroscope Axes Enabling | ||
163 | */ | ||
164 | typedef enum { | ||
165 | L3GD20_AE_DISABLED = 0x00, /*!< All disabled */ | ||
166 | L3GD20_AE_X = 0x01, /*!< Only X */ | ||
167 | L3GD20_AE_Y = 0x02, /*!< Only Y */ | ||
168 | L3GD20_AE_XY = 0x03, /*!< X & Y */ | ||
169 | L3GD20_AE_Z = 0x04, /*!< Only Z */ | ||
170 | L3GD20_AE_XZ = 0x05, /*!< X & Z */ | ||
171 | L3GD20_AE_YZ = 0x06, /*!< Y & Z */ | ||
172 | L3GD20_AE_XYZ = 0x07 /*!< All enabled */ | ||
173 | }L3GD20_AE_t; | ||
174 | |||
175 | /** | ||
176 | * @brief Gyroscope Block Data Update | ||
177 | */ | ||
178 | typedef enum { | ||
179 | L3GD20_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ | ||
180 | L3GD20_BDU_BLOCKED = 0x80 /*!< Single Update: output registers not updated until MSB and LSB reading */ | ||
181 | }L3GD20_BDU_t; | ||
182 | |||
183 | /** | ||
184 | * @brief Gyroscope Endianness | ||
185 | */ | ||
186 | typedef enum { | ||
187 | L3GD20_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ | ||
188 | L3GD20_End_BIG = 0x40 /*!< Big Endian: data MSB @ lower address */ | ||
189 | }L3GD20_End_t; | ||
190 | |||
191 | |||
192 | /** | ||
193 | * @brief Gyroscope configuration structure. | ||
194 | */ | ||
195 | typedef struct { | ||
196 | /** | ||
197 | * @brief Gyroscope fullscale value. | ||
198 | */ | ||
199 | L3GD20_FS_t fullscale; | ||
200 | /** | ||
201 | * @brief Gyroscope power mode selection. | ||
202 | */ | ||
203 | L3GD20_PM_t powermode; | ||
204 | /** | ||
205 | * @brief Gyroscope output data rate selection. | ||
206 | */ | ||
207 | L3GD20_ODR_t outputdatarate; | ||
208 | /** | ||
209 | * @brief Gyroscope axes enabling. | ||
210 | */ | ||
211 | L3GD20_AE_t axesenabling; | ||
212 | /** | ||
213 | * @brief Gyroscope endianess. | ||
214 | */ | ||
215 | L3GD20_End_t endianess; | ||
216 | /** | ||
217 | * @brief Gyroscope block data update. | ||
218 | */ | ||
219 | L3GD20_BDU_t blockdataupdate; | ||
220 | } L3GD20_Config; | ||
221 | /** @} */ | ||
222 | /*===========================================================================*/ | ||
223 | /* Driver macros. */ | ||
224 | /*===========================================================================*/ | ||
225 | |||
226 | /*===========================================================================*/ | ||
227 | /* External declarations. */ | ||
228 | /*===========================================================================*/ | ||
229 | |||
230 | #ifdef __cplusplus | ||
231 | extern "C" { | ||
232 | #endif | ||
233 | |||
234 | uint8_t l3gd20ReadRegister(SPIDriver *spip, uint8_t reg); | ||
235 | void l3gd20WriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value); | ||
236 | #ifdef __cplusplus | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | #endif /* _L3GD20_H_ */ | ||
241 | |||
242 | /** @} */ | ||
243 | |||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.c b/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.c new file mode 100644 index 000000000..99b71e45e --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lis3mdl.c | ||
31 | * @brief LIS3MDL MEMS interface module through I2C code. | ||
32 | * | ||
33 | * @addtogroup lis3mdl | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "lis3mdl.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Driver exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Driver local variables and types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Driver local functions. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Driver exported functions. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /** | ||
63 | * @brief Reads a generic sub-register value. | ||
64 | * @pre The I2C interface must be initialized and the driver started. | ||
65 | * | ||
66 | * @param[in] i2cp pointer to the I2C interface | ||
67 | * @param[in] sad slave address without R bit | ||
68 | * @param[in] sub sub-register address | ||
69 | * @param[in] message pointer to message | ||
70 | * @return register value. | ||
71 | */ | ||
72 | uint8_t lis3mdlReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
73 | msg_t* message) { | ||
74 | |||
75 | uint8_t txbuf, rxbuf[2]; | ||
76 | #if defined(STM32F103_MCUCONF) | ||
77 | txbuf = LSM303DLHC_SUB_MSB | sub; | ||
78 | if(message != NULL){ | ||
79 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, | ||
80 | TIME_INFINITE); | ||
81 | } | ||
82 | else{ | ||
83 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); | ||
84 | } | ||
85 | return rxbuf[0]; | ||
86 | #else | ||
87 | txbuf = sub; | ||
88 | if(message != NULL){ | ||
89 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, | ||
90 | TIME_INFINITE); | ||
91 | } | ||
92 | else{ | ||
93 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); | ||
94 | } | ||
95 | return rxbuf[0]; | ||
96 | #endif | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * @brief Writes a value into a register. | ||
101 | * @pre The I2C interface must be initialized and the driver started. | ||
102 | * | ||
103 | * @param[in] i2cp pointer to the I2C interface | ||
104 | * @param[in] sad slave address without R bit | ||
105 | * @param[in] sub sub-register address | ||
106 | * @param[in] value the value to be written | ||
107 | * @param[out] message pointer to message | ||
108 | */ | ||
109 | void lis3mdlWriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
110 | uint8_t value, msg_t* message) { | ||
111 | |||
112 | uint8_t txbuf[2]; | ||
113 | uint8_t rxbuf; | ||
114 | switch (sub) { | ||
115 | default: | ||
116 | /* Reserved register must not be written, according to the datasheet | ||
117 | * this could permanently damage the device. | ||
118 | */ | ||
119 | chDbgAssert(FALSE, "lis3mdlWriteRegister(), reserved register"); | ||
120 | case LIS3MDL_SUB_WHO_AM_I: | ||
121 | case LIS3MDL_SUB_STATUS_REG: | ||
122 | case LIS3MDL_SUB_OUT_X_L: | ||
123 | case LIS3MDL_SUB_OUT_X_H: | ||
124 | case LIS3MDL_SUB_OUT_Y_L: | ||
125 | case LIS3MDL_SUB_OUT_Y_H: | ||
126 | case LIS3MDL_SUB_OUT_Z_L: | ||
127 | case LIS3MDL_SUB_OUT_Z_H: | ||
128 | case LIS3MDL_SUB_INT_SOURCE: | ||
129 | case LIS3MDL_SUB_INT_THS_L: | ||
130 | case LIS3MDL_SUB_INT_THS_H: | ||
131 | /* Read only registers cannot be written, the command is ignored.*/ | ||
132 | return; | ||
133 | case LIS3MDL_SUB_CTRL_REG1: | ||
134 | case LIS3MDL_SUB_CTRL_REG2: | ||
135 | case LIS3MDL_SUB_CTRL_REG3: | ||
136 | case LIS3MDL_SUB_CTRL_REG4: | ||
137 | case LIS3MDL_SUB_CTRL_REG5: | ||
138 | case LIS3MDL_SUB_INT_CFG: | ||
139 | txbuf[0] = sub; | ||
140 | txbuf[1] = value; | ||
141 | if(message != NULL){ | ||
142 | *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, | ||
143 | TIME_INFINITE); | ||
144 | } | ||
145 | else{ | ||
146 | i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); | ||
147 | } | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.h b/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.h new file mode 100644 index 000000000..e55978e9b --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.h | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lis3mdl.h | ||
31 | * @brief LIS3MDL MEMS interface module header. | ||
32 | * | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef _LIS3MDL_H_ | ||
37 | #define _LIS3MDL_H_ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Driver constants. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | #define LIS3MDL_COMP_SENS_4GA ((float)6842.0f) /*!< compass sensitivity with 4 GA full scale [LSB / Ga] */ | ||
44 | #define LIS3MDL_COMP_SENS_8GA ((float)3421.0f) /*!< compass sensitivity with 8 GA full scale [LSB / Ga] */ | ||
45 | #define LIS3MDL_COMP_SENS_12GA ((float)2281.0f) /*!< compass sensitivity with 12 GA full scale [LSB / Ga] */ | ||
46 | #define LIS3MDL_COMP_SENS_16GA ((float)1711.0f) /*!< compass sensitivity with 16 GA full scale [LSB / Ga] */ | ||
47 | /** | ||
48 | * @name LIS3MDL register names | ||
49 | * @{ | ||
50 | */ | ||
51 | /******************************************************************************/ | ||
52 | /* */ | ||
53 | /* LIS3MDL on board MEMS */ | ||
54 | /* */ | ||
55 | /******************************************************************************/ | ||
56 | /***************** Bit definition for I2C/SPI communication *****************/ | ||
57 | #define LIS3MDL_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ | ||
58 | #define LIS3MDL_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
59 | #define LIS3MDL_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
60 | #define LIS3MDL_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ | ||
61 | #define LIS3MDL_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
62 | #define LIS3MDL_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
63 | #define LIS3MDL_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ | ||
64 | |||
65 | #define LIS3MDL_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ | ||
66 | |||
67 | /**************** Bit definition SUB-Registers Addresses ********************/ | ||
68 | #define LIS3MDL_SUB_WHO_AM_I ((uint8_t)0x0F) /*!< CONTROL REGISTER 1 */ | ||
69 | #define LIS3MDL_SUB_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 */ | ||
70 | #define LIS3MDL_SUB_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 */ | ||
71 | #define LIS3MDL_SUB_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 */ | ||
72 | #define LIS3MDL_SUB_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 */ | ||
73 | #define LIS3MDL_SUB_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 */ | ||
74 | #define LIS3MDL_SUB_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER */ | ||
75 | #define LIS3MDL_SUB_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW */ | ||
76 | #define LIS3MDL_SUB_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH */ | ||
77 | #define LIS3MDL_SUB_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW */ | ||
78 | #define LIS3MDL_SUB_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH */ | ||
79 | #define LIS3MDL_SUB_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW */ | ||
80 | #define LIS3MDL_SUB_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH */ | ||
81 | #define LIS3MDL_SUB_INT_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG */ | ||
82 | #define LIS3MDL_SUB_INT_SOURCE ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE */ | ||
83 | #define LIS3MDL_SUB_INT_THS_L ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD */ | ||
84 | #define LIS3MDL_SUB_INT_THS_H ((uint8_t)0x33) /*!< INTERRUPT1 DURATION */ | ||
85 | |||
86 | /** @} */ | ||
87 | |||
88 | /*===========================================================================*/ | ||
89 | /* Driver pre-compile time settings. */ | ||
90 | /*===========================================================================*/ | ||
91 | |||
92 | /*===========================================================================*/ | ||
93 | /* Derived constants and error checks. */ | ||
94 | /*===========================================================================*/ | ||
95 | |||
96 | /*===========================================================================*/ | ||
97 | /* Driver data structures and types. */ | ||
98 | /*===========================================================================*/ | ||
99 | |||
100 | /** | ||
101 | * @name Compass data structures and types | ||
102 | * @{ | ||
103 | */ | ||
104 | |||
105 | /** | ||
106 | * @brief Compass Slave Address | ||
107 | */ | ||
108 | typedef enum { | ||
109 | LIS3MDL_SAD_GND = 0x1C, /*!< COMPASS Slave Address when SA1 is to GND */ | ||
110 | LIS3MDL_SAD_VCC = 0x1E /*!< COMPASS Slave Address when SA1 is to VCC */ | ||
111 | }LIS3MDL_SAD_t; | ||
112 | |||
113 | /** | ||
114 | * @brief Compass Operation Mode for X and Y axes | ||
115 | */ | ||
116 | typedef enum { | ||
117 | LIS3MDL_OMXY_LOW_POWER = 0x00, /*!< Operation Mode XY low power */ | ||
118 | LIS3MDL_OMXY_MEDIUM_PERFORMANCE = 0x20, /*!< Operation Mode XY medium performance */ | ||
119 | LIS3MDL_OMXY_HIGH_PERFORMANCE = 0x40, /*!< Operation Mode XY high performance */ | ||
120 | LIS3MDL_OMXY_ULTRA_PERFORMANCE = 0x60 /*!< Operation Mode XY ultra performance */ | ||
121 | }LIS3MDL_OMXY_t; | ||
122 | |||
123 | /** | ||
124 | * @brief Compass Output Data Rate | ||
125 | */ | ||
126 | typedef enum { | ||
127 | LIS3MDL_ODR_0_625Hz = 0x00, /*!< Output Data Rate = 0.625 Hz */ | ||
128 | LIS3MDL_ODR_1_25Hz = 0x04, /*!< Output Data Rate = 1.25 Hz */ | ||
129 | LIS3MDL_ODR_2_5Hz = 0x08, /*!< Output Data Rate = 2.5 Hz */ | ||
130 | LIS3MDL_ODR_5Hz = 0x0C, /*!< Output Data Rate = 5 Hz */ | ||
131 | LIS3MDL_ODR_10Hz = 0x10, /*!< Output Data Rate = 10 Hz */ | ||
132 | LIS3MDL_ODR_20Hz = 0x14, /*!< Output Data Rate = 20 Hz */ | ||
133 | LIS3MDL_ODR_40Hz = 0x18, /*!< Output Data Rate = 40 Hz */ | ||
134 | LIS3MDL_ODR_80Hz = 0x1C /*!< Output Data Rate = 80 Hz */ | ||
135 | }LIS3MDL_ODR_t; | ||
136 | |||
137 | /** | ||
138 | * @brief Compass Full Scale | ||
139 | */ | ||
140 | typedef enum { | ||
141 | LIS3MDL_FS_4GA = 0x00, /*!< �4 Gauss */ | ||
142 | LIS3MDL_FS_8GA = 0x02, /*!< �8 Gauss */ | ||
143 | LIS3MDL_FS_12GA = 0x04, /*!< �12 Gauss */ | ||
144 | LIS3MDL_FS_16GA = 0x0C /*!< �16 Gauss */ | ||
145 | }LIS3MDL_FS_t; | ||
146 | |||
147 | /** | ||
148 | * @brief Compass Low Mode configuration | ||
149 | */ | ||
150 | typedef enum { | ||
151 | LIS3MDL_LOW_POWER_DISABLED = 0x00, /*!< Low Power mode disabled */ | ||
152 | LIS3MDL_LOW_POWER_ENABLED = 0x20 /*!< Low Power mode enabled */ | ||
153 | }LIS3MDL_PM_t; | ||
154 | |||
155 | /** | ||
156 | * @brief Compass Mode | ||
157 | */ | ||
158 | typedef enum { | ||
159 | LIS3MDL_MD_CONTINOUS_CONVERSION = 0x00, /*!< Continous conversion mode */ | ||
160 | LIS3MDL_MD_SINGLE_CONVERSION = 0x01, /*!< Single conversion mode */ | ||
161 | LIS3MDL_MD_POWER_DOWN = 0x02 /*!< Power down mode */ | ||
162 | }LIS3MDL_MD_t; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * @brief Compass Operation Mode for Z axis | ||
167 | */ | ||
168 | typedef enum { | ||
169 | LIS3MDL_OMZ_LOW_POWER = 0x00, /*!< Operation Mode Z low power */ | ||
170 | LIS3MDL_OMZ_MEDIUM_PERFORMANCE = 0x04, /*!< Operation Mode Z medium performance */ | ||
171 | LIS3MDL_OMZ_HIGH_PERFORMANCE = 0x08, /*!< Operation Mode Z high performance */ | ||
172 | LIS3MDL_OMZ_ULTRA_PERFORMANCE = 0x0C /*!< Operation Mode Z ultra performance */ | ||
173 | }LIS3MDL_OMZ_t; | ||
174 | |||
175 | /** | ||
176 | * @brief Compass Endianness | ||
177 | */ | ||
178 | typedef enum { | ||
179 | LIS3MDL_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ | ||
180 | LIS3MDL_End_BIG = 0x02 /*!< Big Endian: data MSB @ lower address */ | ||
181 | }LIS3MDL_End_t; | ||
182 | |||
183 | /** | ||
184 | * @brief Compass Block Data Update | ||
185 | */ | ||
186 | typedef enum { | ||
187 | LIS3MDL_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ | ||
188 | LIS3MDL_BDU_BLOCKED = 0x40 /*!< Single Update: output registers not updated until MSB and LSB reading */ | ||
189 | }LIS3MDL_BDU_t; | ||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /** | ||
195 | * @brief Gyroscope configuration structure. | ||
196 | */ | ||
197 | typedef struct { | ||
198 | /** | ||
199 | * @brief Compass Slave Address | ||
200 | */ | ||
201 | LIS3MDL_SAD_t slaveaddress; | ||
202 | /** | ||
203 | * @brief Compass Operation Mode for X and Y axes | ||
204 | */ | ||
205 | LIS3MDL_OMXY_t opmodexy; | ||
206 | /** | ||
207 | * @brief Compass Output Data Rate | ||
208 | */ | ||
209 | LIS3MDL_ODR_t outputdatarate; | ||
210 | /** | ||
211 | * @brief Compass Full Scale | ||
212 | */ | ||
213 | LIS3MDL_FS_t fullscale; | ||
214 | /** | ||
215 | * @brief Compass Low Mode configuration | ||
216 | */ | ||
217 | LIS3MDL_PM_t lowpowermode; | ||
218 | /** | ||
219 | * @brief Compass Mode | ||
220 | */ | ||
221 | LIS3MDL_MD_t mode; | ||
222 | /** | ||
223 | * @brief Compass Operation Mode for Z axis | ||
224 | */ | ||
225 | LIS3MDL_OMZ_t opmodez; | ||
226 | /** | ||
227 | * @brief Compass Endianness | ||
228 | */ | ||
229 | LIS3MDL_End_t endianess; | ||
230 | /** | ||
231 | * @brief Compass Block Data Update | ||
232 | */ | ||
233 | LIS3MDL_BDU_t blockdataupdate; | ||
234 | } LIS3MDL_Config; | ||
235 | /** @} */ | ||
236 | /*===========================================================================*/ | ||
237 | /* Driver macros. */ | ||
238 | /*===========================================================================*/ | ||
239 | |||
240 | /*===========================================================================*/ | ||
241 | /* External declarations. */ | ||
242 | /*===========================================================================*/ | ||
243 | |||
244 | #ifdef __cplusplus | ||
245 | extern "C" { | ||
246 | #endif | ||
247 | |||
248 | uint8_t lis3mdlReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
249 | msg_t* message); | ||
250 | void lis3mdlWriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
251 | uint8_t value, msg_t* message); | ||
252 | #ifdef __cplusplus | ||
253 | } | ||
254 | #endif | ||
255 | |||
256 | #endif /* _LIS3MDL_H_ */ | ||
257 | |||
258 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.c b/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.c new file mode 100644 index 000000000..070c49cc8 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lsm303dlhc.c | ||
31 | * @brief LSM303DLHC MEMS interface module through I2C code. | ||
32 | * | ||
33 | * @addtogroup lsm303dlhc | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "lsm303dlhc.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Driver exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Driver local variables and types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | |||
55 | /*===========================================================================*/ | ||
56 | /* Driver local functions. */ | ||
57 | /*===========================================================================*/ | ||
58 | |||
59 | /*===========================================================================*/ | ||
60 | /* Driver exported functions. */ | ||
61 | /*===========================================================================*/ | ||
62 | |||
63 | /** | ||
64 | * @brief Reads a generic sub-register value. | ||
65 | * @pre The I2C interface must be initialized and the driver started. | ||
66 | * | ||
67 | * @param[in] i2cp pointer to the I2C interface | ||
68 | * @param[in] sad slave address without R bit | ||
69 | * @param[in] sub sub-register address | ||
70 | * @param[in] message pointer to message | ||
71 | * @return register value. | ||
72 | */ | ||
73 | uint8_t lsm303dlhcReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
74 | msg_t* message) { | ||
75 | |||
76 | uint8_t txbuf, rxbuf[2]; | ||
77 | #if defined(STM32F103_MCUCONF) | ||
78 | txbuf = LSM303DLHC_SUB_MSB | sub; | ||
79 | if(message != NULL){ | ||
80 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, | ||
81 | TIME_INFINITE); | ||
82 | } | ||
83 | else{ | ||
84 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); | ||
85 | } | ||
86 | return rxbuf[0]; | ||
87 | #else | ||
88 | txbuf = sub; | ||
89 | if(message != NULL){ | ||
90 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, | ||
91 | TIME_INFINITE); | ||
92 | } | ||
93 | else{ | ||
94 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); | ||
95 | } | ||
96 | return rxbuf[0]; | ||
97 | #endif | ||
98 | |||
99 | |||
100 | } | ||
101 | |||
102 | /** | ||
103 | * @brief Writes a value into a register. | ||
104 | * @pre The I2C interface must be initialized and the driver started. | ||
105 | * | ||
106 | * @param[in] i2cp pointer to the I2C interface | ||
107 | * @param[in] sad slave address without R bit | ||
108 | * @param[in] sub sub-register address | ||
109 | * @param[in] value the value to be written | ||
110 | * @param[out] message pointer to message | ||
111 | */ | ||
112 | void lsm303dlhcWriteRegister(I2CDriver *i2cp,uint8_t sad, uint8_t sub, | ||
113 | uint8_t value, msg_t* message) { | ||
114 | |||
115 | uint8_t txbuf[2]; | ||
116 | uint8_t rxbuf; | ||
117 | if(sad == LSM303DLHC_SAD_ACCEL){ | ||
118 | switch (sub) { | ||
119 | default: | ||
120 | /* Reserved register must not be written, according to the datasheet | ||
121 | * this could permanently damage the device. | ||
122 | */ | ||
123 | chDbgAssert(FALSE, "lsm303dlhcWriteRegister(), reserved register"); | ||
124 | case LSM303DLHC_SUB_ACC_STATUS_REG: | ||
125 | case LSM303DLHC_SUB_ACC_OUT_X_L: | ||
126 | case LSM303DLHC_SUB_ACC_OUT_X_H: | ||
127 | case LSM303DLHC_SUB_ACC_OUT_Y_L: | ||
128 | case LSM303DLHC_SUB_ACC_OUT_Y_H: | ||
129 | case LSM303DLHC_SUB_ACC_OUT_Z_L: | ||
130 | case LSM303DLHC_SUB_ACC_OUT_Z_H: | ||
131 | case LSM303DLHC_SUB_ACC_FIFO_SRC_REG: | ||
132 | case LSM303DLHC_SUB_ACC_INT1_SOURCE: | ||
133 | case LSM303DLHC_SUB_ACC_INT2_SOURCE: | ||
134 | case LSM303DLHC_SUB_ACC_CLICK_SRC: | ||
135 | /* Read only registers cannot be written, the command is ignored.*/ | ||
136 | return; | ||
137 | case LSM303DLHC_SUB_ACC_CTRL_REG1: | ||
138 | case LSM303DLHC_SUB_ACC_CTRL_REG2: | ||
139 | case LSM303DLHC_SUB_ACC_CTRL_REG3: | ||
140 | case LSM303DLHC_SUB_ACC_CTRL_REG4: | ||
141 | case LSM303DLHC_SUB_ACC_CTRL_REG5: | ||
142 | case LSM303DLHC_SUB_ACC_CTRL_REG6: | ||
143 | case LSM303DLHC_SUB_ACC_REFERENCE: | ||
144 | case LSM303DLHC_SUB_ACC_FIFO_CTRL_REG: | ||
145 | case LSM303DLHC_SUB_ACC_INT1_CFG: | ||
146 | case LSM303DLHC_SUB_ACC_INT1_THS: | ||
147 | case LSM303DLHC_SUB_ACC_INT1_DURATION: | ||
148 | case LSM303DLHC_SUB_ACC_INT2_CFG: | ||
149 | case LSM303DLHC_SUB_ACC_INT2_THS: | ||
150 | case LSM303DLHC_SUB_ACC_INT2_DURATION: | ||
151 | case LSM303DLHC_SUB_ACC_CLICK_CFG: | ||
152 | case LSM303DLHC_SUB_ACC_CLICK_THS: | ||
153 | case LSM303DLHC_SUB_ACC_TIME_LIMIT: | ||
154 | case LSM303DLHC_SUB_ACC_TIME_LATENCY: | ||
155 | case LSM303DLHC_SUB_ACC_TIME_WINDOW: | ||
156 | txbuf[0] = sub; | ||
157 | txbuf[1] = value; | ||
158 | if(message != NULL){ | ||
159 | *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, | ||
160 | TIME_INFINITE); | ||
161 | } | ||
162 | else{ | ||
163 | i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); | ||
164 | } | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | else if(sad == LSM303DLHC_SAD_COMPASS){ | ||
169 | switch (sub) { | ||
170 | default: | ||
171 | /* Reserved register must not be written, according to the datasheet | ||
172 | * this could permanently damage the device. | ||
173 | */ | ||
174 | chDbgAssert(FALSE, "lsm303dlhcWriteRegister(), reserved register"); | ||
175 | case LSM303DLHC_SUB_COMP_OUT_X_H: | ||
176 | case LSM303DLHC_SUB_COMP_OUT_X_L: | ||
177 | case LSM303DLHC_SUB_COMP_OUT_Z_H: | ||
178 | case LSM303DLHC_SUB_COMP_OUT_Z_L: | ||
179 | case LSM303DLHC_SUB_COMP_OUT_Y_H: | ||
180 | case LSM303DLHC_SUB_COMP_OUT_Y_L: | ||
181 | case LSM303DLHC_SUB_COMP_SR_REG: | ||
182 | case LSM303DLHC_SUB_COMP_IRA_REG: | ||
183 | case LSM303DLHC_SUB_COMP_IRB_REG: | ||
184 | case LSM303DLHC_SUB_COMP_IRC_REG: | ||
185 | case LSM303DLHC_SUB_COMP_TEMP_OUT_H: | ||
186 | case LSM303DLHC_SUB_COMP_TEMP_OUT_L: | ||
187 | /* Read only registers cannot be written, the command is ignored.*/ | ||
188 | return; | ||
189 | case LSM303DLHC_SUB_COMP_CRA_REG: | ||
190 | case LSM303DLHC_SUB_COMP_CRB_REG: | ||
191 | case LSM303DLHC_SUB_COMP_MR_REG: | ||
192 | txbuf[0] = sub; | ||
193 | txbuf[1] = value; | ||
194 | if(message != NULL){ | ||
195 | *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, | ||
196 | TIME_INFINITE); | ||
197 | } | ||
198 | else{ | ||
199 | i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); | ||
200 | } | ||
201 | break; | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.h b/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.h new file mode 100644 index 000000000..46b51bce8 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.h | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lsm303dlhc.h | ||
31 | * @brief LSM303DLHC MEMS interface module through I2C header. | ||
32 | * | ||
33 | * @addtogroup lsm303dlhc | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #ifndef _LSM303DLHC_H_ | ||
38 | #define _LSM303DLHC_H_ | ||
39 | |||
40 | /*===========================================================================*/ | ||
41 | /* Driver constants. */ | ||
42 | /*===========================================================================*/ | ||
43 | |||
44 | #define LSM303DLHC_ACC_SENS_2G ((float)1671.836f) /*!< Accelerometer sensitivity with 2 G full scale [LSB * s^2 / m] */ | ||
45 | #define LSM303DLHC_ACC_SENS_4G ((float)835.918f) /*!< Accelerometer sensitivity with 4 G full scale [LSB * s^2 / m] */ | ||
46 | #define LSM303DLHC_ACC_SENS_8G ((float)417.959f) /*!< Accelerometer sensitivity with 8 G full scale [LSB * s^2 / m] */ | ||
47 | #define LSM303DLHC_ACC_SENS_16G ((float)208.979f) /*!< Accelerometer sensitivity with 16 G full scale [LSB * s^2 / m] */ | ||
48 | |||
49 | #define LSM303DLHC_COMP_SENS_XY_1_3GA ((float)1100.0f) /*!< Compass sensitivity with 1.3 GA full scale [LSB / Ga] */ | ||
50 | #define LSM303DLHC_COMP_SENS_XY_1_9GA ((float)855.0f) /*!< Compass sensitivity with 1.9 GA full scale [LSB / Ga] */ | ||
51 | #define LSM303DLHC_COMP_SENS_XY_2_5GA ((float)670.0f) /*!< Compass sensitivity with 2.5 GA full scale [LSB / Ga] */ | ||
52 | #define LSM303DLHC_COMP_SENS_XY_4_0GA ((float)450.0f) /*!< Compass sensitivity with 4.0 GA full scale [LSB / Ga] */ | ||
53 | #define LSM303DLHC_COMP_SENS_XY_4_7GA ((float)400.0f) /*!< Compass sensitivity with 4.7 GA full scale [LSB / Ga] */ | ||
54 | #define LSM303DLHC_COMP_SENS_XY_5_6GA ((float)330.0f) /*!< Compass sensitivity with 5.6 GA full scale [LSB / Ga] */ | ||
55 | #define LSM303DLHC_COMP_SENS_XY_8_1GA ((float)230.0f) /*!< Compass sensitivity with 8.1 GA full scale [LSB / Ga] */ | ||
56 | |||
57 | #define LSM303DLHC_COMP_SENS_Z_1_3GA ((float)980.0f) /*!< Compass sensitivity with 1.3 GA full scale [LSB / Ga] */ | ||
58 | #define LSM303DLHC_COMP_SENS_Z_1_9GA ((float)765.0f) /*!< Compass sensitivity with 1.9 GA full scale [LSB / Ga] */ | ||
59 | #define LSM303DLHC_COMP_SENS_Z_2_5GA ((float)600.0f) /*!< Compass sensitivity with 2.5 GA full scale [LSB / Ga] */ | ||
60 | #define LSM303DLHC_COMP_SENS_Z_4_0GA ((float)400.0f) /*!< Compass sensitivity with 4.0 GA full scale [LSB / Ga] */ | ||
61 | #define LSM303DLHC_COMP_SENS_Z_4_7GA ((float)355.0f) /*!< Compass sensitivity with 4.7 GA full scale [LSB / Ga] */ | ||
62 | #define LSM303DLHC_COMP_SENS_Z_5_6GA ((float)295.0f) /*!< Compass sensitivity with 5.6 GA full scale [LSB / Ga] */ | ||
63 | #define LSM303DLHC_COMP_SENS_Z_8_1GA ((float)205.0f) /*!< Compass sensitivity with 8.1 GA full scale [LSB / Ga] */ | ||
64 | /** | ||
65 | * @name LSM303DLHC register names | ||
66 | * @{ | ||
67 | */ | ||
68 | /******************************************************************************/ | ||
69 | /* */ | ||
70 | /* LSM303DLHC on board MEMS */ | ||
71 | /* */ | ||
72 | /******************************************************************************/ | ||
73 | /******************* Bit definition for I2C communication *******************/ | ||
74 | #define LSM303DLHC_SAD ((uint8_t)0x7F) /*!< SAD[6:0] Slave Address Mask */ | ||
75 | #define LSM303DLHC_SAD_ACCEL ((uint8_t)0x19) /*!< ACCELEROMETER Slave Address */ | ||
76 | #define LSM303DLHC_SAD_COMPASS ((uint8_t)0x1E) /*!< MAGNETOMETER Slave Address */ | ||
77 | |||
78 | #define LSM303DLHC_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ | ||
79 | #define LSM303DLHC_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
80 | #define LSM303DLHC_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
81 | #define LSM303DLHC_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ | ||
82 | #define LSM303DLHC_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
83 | #define LSM303DLHC_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
84 | #define LSM303DLHC_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ | ||
85 | |||
86 | #define LSM303DLHC_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ | ||
87 | |||
88 | /******** Bit definition for Accelerometer SUB-Registers Addresses **********/ | ||
89 | #define LSM303DLHC_SUB_ACC_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 FOR ACCELEROMETER */ | ||
90 | #define LSM303DLHC_SUB_ACC_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 FOR ACCELEROMETER */ | ||
91 | #define LSM303DLHC_SUB_ACC_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 FOR ACCELEROMETER */ | ||
92 | #define LSM303DLHC_SUB_ACC_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 FOR ACCELEROMETER */ | ||
93 | #define LSM303DLHC_SUB_ACC_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 FOR ACCELEROMETER */ | ||
94 | #define LSM303DLHC_SUB_ACC_CTRL_REG6 ((uint8_t)0x25) /*!< CONTROL REGISTER 6 FOR ACCELEROMETER */ | ||
95 | #define LSM303DLHC_SUB_ACC_REFERENCE ((uint8_t)0x26) /*!< REFERENCE/DATACAPTURE FOR ACCELEROMETER */ | ||
96 | #define LSM303DLHC_SUB_ACC_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER FOR ACCELEROMETER */ | ||
97 | #define LSM303DLHC_SUB_ACC_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW FOR ACCELEROMETER */ | ||
98 | #define LSM303DLHC_SUB_ACC_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH FOR ACCELEROMETER */ | ||
99 | #define LSM303DLHC_SUB_ACC_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW FOR ACCELEROMETER */ | ||
100 | #define LSM303DLHC_SUB_ACC_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH FOR ACCELEROMETER */ | ||
101 | #define LSM303DLHC_SUB_ACC_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW FOR ACCELEROMETER */ | ||
102 | #define LSM303DLHC_SUB_ACC_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH FOR ACCELEROMETER */ | ||
103 | #define LSM303DLHC_SUB_ACC_FIFO_CTRL_REG ((uint8_t)0x2E) /*!< FIFO CONTROL REGISTER FOR ACCELEROMETER */ | ||
104 | #define LSM303DLHC_SUB_ACC_FIFO_SRC_REG ((uint8_t)0x2F) /*!< FIFO SOURCE REGISTER FOR ACCELEROMETER */ | ||
105 | #define LSM303DLHC_SUB_ACC_INT1_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG FOR ACCELEROMETER */ | ||
106 | #define LSM303DLHC_SUB_ACC_INT1_SOURCE ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE FOR ACCELEROMETER */ | ||
107 | #define LSM303DLHC_SUB_ACC_INT1_THS ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD FOR ACCELEROMETER */ | ||
108 | #define LSM303DLHC_SUB_ACC_INT1_DURATION ((uint8_t)0x33) /*!< INTERRUPT1 DURATION FOR ACCELEROMETER */ | ||
109 | #define LSM303DLHC_SUB_ACC_INT2_CFG ((uint8_t)0x34) /*!< INTERRUPT2 CONFIG FOR ACCELEROMETER */ | ||
110 | #define LSM303DLHC_SUB_ACC_INT2_SOURCE ((uint8_t)0x35) /*!< INTERRUPT2 SOURCE FOR ACCELEROMETER */ | ||
111 | #define LSM303DLHC_SUB_ACC_INT2_THS ((uint8_t)0x36) /*!< INTERRUPT2 THRESHOLD FOR ACCELEROMETER */ | ||
112 | #define LSM303DLHC_SUB_ACC_INT2_DURATION ((uint8_t)0x37) /*!< INTERRUPT2 DURATION FOR ACCELEROMETER */ | ||
113 | #define LSM303DLHC_SUB_ACC_CLICK_CFG ((uint8_t)0x38) /*!< CLICK CONFIG FOR ACCELEROMETER */ | ||
114 | #define LSM303DLHC_SUB_ACC_CLICK_SRC ((uint8_t)0x39) /*!< CLICK SOURCE FOR ACCELEROMETER */ | ||
115 | #define LSM303DLHC_SUB_ACC_CLICK_THS ((uint8_t)0x3A) /*!< CLICK THRESHOLD FOR ACCELEROMETER */ | ||
116 | #define LSM303DLHC_SUB_ACC_TIME_LIMIT ((uint8_t)0x3B) /*!< TIME LIMIT FOR ACCELEROMETER */ | ||
117 | #define LSM303DLHC_SUB_ACC_TIME_LATENCY ((uint8_t)0x3C) /*!< TIME LATENCY FOR ACCELEROMETER */ | ||
118 | #define LSM303DLHC_SUB_ACC_TIME_WINDOW ((uint8_t)0x3D) /*!< TIME WINDOW FOR ACCELEROMETER */ | ||
119 | |||
120 | /********* Bit definition for Compass SUB-Registers Addresses **********/ | ||
121 | #define LSM303DLHC_SUB_COMP_CRA_REG ((uint8_t)0x00) /*!< CONTROL REGISTER A FOR MAGNETOMETER */ | ||
122 | #define LSM303DLHC_SUB_COMP_CRB_REG ((uint8_t)0x01) /*!< CONTROL REGISTER B FOR MAGNETOMETER */ | ||
123 | #define LSM303DLHC_SUB_COMP_MR_REG ((uint8_t)0x02) /*!< STATUS REGISTER FOR MAGNETOMETER */ | ||
124 | #define LSM303DLHC_SUB_COMP_OUT_X_H ((uint8_t)0x03) /*!< OUTPUT X-AXIS HIGH FOR MAGNETOMETER */ | ||
125 | #define LSM303DLHC_SUB_COMP_OUT_X_L ((uint8_t)0x04) /*!< OUTPUT X-AXIS LOW FOR MAGNETOMETER */ | ||
126 | #define LSM303DLHC_SUB_COMP_OUT_Z_H ((uint8_t)0x05) /*!< OUTPUT Z-AXIS HIGH FOR MAGNETOMETER */ | ||
127 | #define LSM303DLHC_SUB_COMP_OUT_Z_L ((uint8_t)0x06) /*!< OUTPUT Z-AXIS LOW FOR MAGNETOMETER */ | ||
128 | #define LSM303DLHC_SUB_COMP_OUT_Y_H ((uint8_t)0x07) /*!< OUTPUT Y-AXIS HIGH FOR MAGNETOMETER */ | ||
129 | #define LSM303DLHC_SUB_COMP_OUT_Y_L ((uint8_t)0x08) /*!< OUTPUT Y-AXIS LOW FOR MAGNETOMETER */ | ||
130 | #define LSM303DLHC_SUB_COMP_SR_REG ((uint8_t)0x09) /*!< SR REGISTER FOR MAGNETOMETER */ | ||
131 | #define LSM303DLHC_SUB_COMP_IRA_REG ((uint8_t)0x0A) /*!< IR A REGISTER FOR MAGNETOMETER */ | ||
132 | #define LSM303DLHC_SUB_COMP_IRB_REG ((uint8_t)0x0B) /*!< IR B REGISTER FOR MAGNETOMETER */ | ||
133 | #define LSM303DLHC_SUB_COMP_IRC_REG ((uint8_t)0x0C) /*!< IR C REGISTER FOR MAGNETOMETER */ | ||
134 | #define LSM303DLHC_SUB_COMP_TEMP_OUT_H ((uint8_t)0x31) /*!< OUTPUT TEMP HIGH FOR MAGNETOMETER */ | ||
135 | #define LSM303DLHC_SUB_COMP_TEMP_OUT_L ((uint8_t)0x32) /*!< OUTPUT TEMP LOW FOR MAGNETOMETER */ | ||
136 | |||
137 | /** @} */ | ||
138 | |||
139 | /*===========================================================================*/ | ||
140 | /* Driver pre-compile time settings. */ | ||
141 | /*===========================================================================*/ | ||
142 | |||
143 | /*===========================================================================*/ | ||
144 | /* Derived constants and error checks. */ | ||
145 | /*===========================================================================*/ | ||
146 | |||
147 | /*===========================================================================*/ | ||
148 | /* Driver data structures and types. */ | ||
149 | /*===========================================================================*/ | ||
150 | |||
151 | /** | ||
152 | * @name Accelerometer data structures and types | ||
153 | * @{ | ||
154 | */ | ||
155 | |||
156 | /** | ||
157 | * @brief Accelerometer Output Data Rate | ||
158 | */ | ||
159 | typedef enum | ||
160 | { | ||
161 | LSM303DLHC_ACC_ODR_PD = 0x00, /*!< Power down */ | ||
162 | LSM303DLHC_ACC_ODR_1Hz = 0x10, /*!< Output Data Rate = 1 Hz */ | ||
163 | LSM303DLHC_ACC_ODR_10Hz = 0x20, /*!< Output Data Rate = 10 Hz */ | ||
164 | LSM303DLHC_ACC_ODR_25Hz = 0x30, /*!< Output Data Rate = 25 Hz */ | ||
165 | LSM303DLHC_ACC_ODR_50Hz = 0x40, /*!< Output Data Rate = 50 Hz */ | ||
166 | LSM303DLHC_ACC_ODR_100Hz = 0x50, /*!< Output Data Rate = 100 Hz */ | ||
167 | LSM303DLHC_ACC_ODR_200Hz = 0x60, /*!< Output Data Rate = 200 Hz */ | ||
168 | LSM303DLHC_ACC_ODR_400Hz = 0x70, /*!< Output Data Rate = 400 Hz */ | ||
169 | LSM303DLHC_ACC_ODR_1620Hz = 0x80, /*!< Output Data Rate = 1620 Hz Low Power mode only */ | ||
170 | LSM303DLHC_ACC_ODR_1344Hz = 0x90 /*!< Output Data Rate = 1344 Hz in Normal mode and 5376 Hz in Low Power Mode */ | ||
171 | }LSM303DLHC_ACC_ODR_t; | ||
172 | |||
173 | /** | ||
174 | * @brief Accelerometer Power Mode | ||
175 | */ | ||
176 | typedef enum | ||
177 | { | ||
178 | LSM303DLHC_ACC_PM_NORMAL = 0x00, /*!< Normal mode enabled */ | ||
179 | LSM303DLHC_ACC_PM_LOW_POWER = 0x08 /*!< Low Power mode enabled */ | ||
180 | }LSM303DLHC_ACC_PM_t; | ||
181 | |||
182 | /** | ||
183 | * @brief Accelerometer Full Scale | ||
184 | */ | ||
185 | typedef enum | ||
186 | { | ||
187 | LSM303DLHC_ACC_FS_2G = 0x00, /*!< �2 g m/s^2 */ | ||
188 | LSM303DLHC_ACC_FS_4G = 0x10, /*!< �4 g m/s^2 */ | ||
189 | LSM303DLHC_ACC_FS_8G = 0x20, /*!< �8 g m/s^2 */ | ||
190 | LSM303DLHC_ACC_FS_16G = 0x30 /*!< �16 g m/s^2 */ | ||
191 | }LSM303DLHC_ACC_FS_t; | ||
192 | |||
193 | /** | ||
194 | * @brief Accelerometer Axes Enabling | ||
195 | */ | ||
196 | typedef enum{ | ||
197 | LSM303DLHC_ACC_AE_DISABLED = 0x00, /*!< Axes all disabled */ | ||
198 | LSM303DLHC_ACC_AE_X = 0x01, /*!< Only X-axis enabled */ | ||
199 | LSM303DLHC_ACC_AE_Y = 0x02, /*!< Only Y-axis enabled */ | ||
200 | LSM303DLHC_ACC_AE_XY = 0x03, /*!< X & Y axes enabled */ | ||
201 | LSM303DLHC_ACC_AE_Z = 0x04, /*!< Only Z-axis enabled */ | ||
202 | LSM303DLHC_ACC_AE_XZ = 0x05, /*!< X & Z axes enabled */ | ||
203 | LSM303DLHC_ACC_AE_YZ = 0x06, /*!< Y & Z axes enabled */ | ||
204 | LSM303DLHC_ACC_AE_XYZ = 0x07 /*!< All axes enabled */ | ||
205 | }LSM303DLHC_ACC_AE_t; | ||
206 | |||
207 | /** | ||
208 | * @brief Accelerometer Block Data Update | ||
209 | */ | ||
210 | typedef enum | ||
211 | { | ||
212 | LSM303DLHC_ACC_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ | ||
213 | LSM303DLHC_ACC_BDU_BLOCKED = 0x80 /*!< Single Update: output registers not updated until MSB and LSB reading */ | ||
214 | }LSM303DLHC_ACC_BDU_t; | ||
215 | |||
216 | /** | ||
217 | * @brief Accelerometer Endianness | ||
218 | */ | ||
219 | typedef enum | ||
220 | { | ||
221 | LSM303DLHC_ACC_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ | ||
222 | LSM303DLHC_ACC_End_BIG = 0x40 /*!< Big Endian: data MSB @ lower address */ | ||
223 | }LSM303DLHC_ACC_End_t; | ||
224 | |||
225 | /** | ||
226 | * @brief Accelerometer High Resolution mode | ||
227 | */ | ||
228 | typedef enum | ||
229 | { | ||
230 | LSM303DLHC_ACC_HR_Enabled = 0x08, /*!< High resolution output mode enabled */ | ||
231 | LSM303DLHC_ACC_HR_Disabled = 0x00 /*!< High resolution output mode disabled */ | ||
232 | }LSM303DLHC_ACC_HR_t; | ||
233 | |||
234 | /** | ||
235 | * @brief Accelerometer configuration structure. | ||
236 | */ | ||
237 | typedef struct { | ||
238 | /** | ||
239 | * @brief Accelerometer fullscale value. | ||
240 | */ | ||
241 | LSM303DLHC_ACC_FS_t fullscale; | ||
242 | /** | ||
243 | * @brief Accelerometer power mode selection. | ||
244 | */ | ||
245 | LSM303DLHC_ACC_PM_t powermode; | ||
246 | /** | ||
247 | * @brief Accelerometer output data rate selection. | ||
248 | */ | ||
249 | LSM303DLHC_ACC_ODR_t outputdatarate; | ||
250 | /** | ||
251 | * @brief Accelerometer axes enabling. | ||
252 | */ | ||
253 | LSM303DLHC_ACC_AE_t axesenabling; | ||
254 | /** | ||
255 | * @brief Accelerometer block data update. | ||
256 | */ | ||
257 | LSM303DLHC_ACC_BDU_t blockdataupdate; | ||
258 | /** | ||
259 | * @brief Accelerometer block data update. | ||
260 | */ | ||
261 | LSM303DLHC_ACC_HR_t highresmode; | ||
262 | } LSM303DLHC_ACC_Config; | ||
263 | /** @} */ | ||
264 | |||
265 | |||
266 | /** | ||
267 | * @name Compass data types | ||
268 | * @{ | ||
269 | */ | ||
270 | |||
271 | /** | ||
272 | * @brief Compass Output Data Rate | ||
273 | */ | ||
274 | typedef enum | ||
275 | { | ||
276 | LSM303DLHC_COMP_ODR_0_75_Hz = 0x00, /*!< Output Data Rate = 0.75 Hz */ | ||
277 | LSM303DLHC_COMP_ODR_1_5_Hz = 0x04, /*!< Output Data Rate = 1.5 Hz */ | ||
278 | LSM303DLHC_COMP_ODR_3_0_Hz = 0x08, /*!< Output Data Rate = 3 Hz */ | ||
279 | LSM303DLHC_COMP_ODR_7_5_Hz = 0x0C, /*!< Output Data Rate = 7.5 Hz */ | ||
280 | LSM303DLHC_COMP_ODR_15_Hz = 0x10, /*!< Output Data Rate = 15 Hz */ | ||
281 | LSM303DLHC_COMP_ODR_30_Hz = 0x14, /*!< Output Data Rate = 30 Hz */ | ||
282 | LSM303DLHC_COMP_ODR_75_Hz = 0x18, /*!< Output Data Rate = 75 Hz */ | ||
283 | LSM303DLHC_COMP_ODR_220_Hz = 0x1C /*!< Output Data Rate = 220 Hz */ | ||
284 | }LSM303DLHC_COMP_ODR_t; | ||
285 | |||
286 | |||
287 | /** | ||
288 | * @brief Compass Full Scale | ||
289 | */ | ||
290 | typedef enum | ||
291 | { | ||
292 | LSM303DLHC_COMP_FS_1_3_GA = 0x20, /*!< Full scale = �1.3 Gauss */ | ||
293 | LSM303DLHC_COMP_FS_1_9_GA = 0x40, /*!< Full scale = �1.9 Gauss */ | ||
294 | LSM303DLHC_COMP_FS_2_5_GA = 0x60, /*!< Full scale = �2.5 Gauss */ | ||
295 | LSM303DLHC_COMP_FS_4_0_GA = 0x80, /*!< Full scale = �4.0 Gauss */ | ||
296 | LSM303DLHC_COMP_FS_4_7_GA = 0xA0, /*!< Full scale = �4.7 Gauss */ | ||
297 | LSM303DLHC_COMP_FS_5_6_GA = 0xC0, /*!< Full scale = �5.6 Gauss */ | ||
298 | LSM303DLHC_COMP_FS_8_1_GA = 0xE0 /*!< Full scale = �8.1 Gauss */ | ||
299 | }LSM303DLHC_COMP_FS_t; | ||
300 | |||
301 | |||
302 | /** | ||
303 | * @brief Compass Working Mode | ||
304 | */ | ||
305 | typedef enum | ||
306 | { | ||
307 | LSM303DLHC_COMP_WM_CONTINUOS = 0x00, /*!< Continuous-Conversion Mode */ | ||
308 | LSM303DLHC_COMP_WM_BLOCKED = 0x01, /*!< Single-Conversion Mode */ | ||
309 | LSM303DLHC_COMP_WM_SLEEP = 0x02 /*!< Sleep Mode */ | ||
310 | }LSM303DLHC_COMP_WM_t; | ||
311 | |||
312 | /** | ||
313 | * @brief Compass configuration structure. | ||
314 | */ | ||
315 | typedef struct { | ||
316 | /** | ||
317 | * @brief Compass fullscale value. | ||
318 | */ | ||
319 | LSM303DLHC_COMP_FS_t fullscale; | ||
320 | /** | ||
321 | * @brief Compass output data rate selection. | ||
322 | */ | ||
323 | LSM303DLHC_COMP_ODR_t outputdatarate; | ||
324 | /** | ||
325 | * @brief Compass working mode. | ||
326 | */ | ||
327 | LSM303DLHC_COMP_WM_t workingmode; | ||
328 | } LSM303DLHC_COMP_Config; | ||
329 | /** @} */ | ||
330 | /*===========================================================================*/ | ||
331 | /* Driver macros. */ | ||
332 | /*===========================================================================*/ | ||
333 | |||
334 | /*===========================================================================*/ | ||
335 | /* External declarations. */ | ||
336 | /*===========================================================================*/ | ||
337 | |||
338 | #ifdef __cplusplus | ||
339 | extern "C" { | ||
340 | #endif | ||
341 | |||
342 | uint8_t lsm303dlhcReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
343 | msg_t* message); | ||
344 | void lsm303dlhcWriteRegister(I2CDriver *i2cp,uint8_t sad, uint8_t sub, | ||
345 | uint8_t value, msg_t* message); | ||
346 | |||
347 | #ifdef __cplusplus | ||
348 | } | ||
349 | #endif | ||
350 | #endif /* _LSM303DLHC_H_ */ | ||
351 | /** @} */ | ||
352 | |||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.c b/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.c new file mode 100644 index 000000000..da67f126f --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lsm6ds0.c | ||
31 | * @brief LSM6DS0 MEMS interface module through I2C code. | ||
32 | * | ||
33 | * @addtogroup lsm6ds0 | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "lsm6ds0.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Driver exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Driver local variables and types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Driver local functions. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Driver exported functions. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /** | ||
63 | * @brief Reads a generic sub-register value. | ||
64 | * @pre The I2C interface must be initialized and the driver started. | ||
65 | * | ||
66 | * @param[in] i2cp pointer to the I2C interface | ||
67 | * @param[in] sad slave address without R bit | ||
68 | * @param[in] sub sub-register address | ||
69 | * @param[in] message pointer to message | ||
70 | * @return register value. | ||
71 | */ | ||
72 | uint8_t lsm6ds0ReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
73 | msg_t* message) { | ||
74 | |||
75 | uint8_t txbuf, rxbuf[2]; | ||
76 | #if defined(STM32F103_MCUCONF) | ||
77 | txbuf = LSM303DLHC_SUB_MSB | sub; | ||
78 | if(message != NULL){ | ||
79 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, | ||
80 | TIME_INFINITE); | ||
81 | } | ||
82 | else{ | ||
83 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); | ||
84 | } | ||
85 | return rxbuf[0]; | ||
86 | #else | ||
87 | txbuf = sub; | ||
88 | if(message != NULL){ | ||
89 | *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, | ||
90 | TIME_INFINITE); | ||
91 | } | ||
92 | else{ | ||
93 | i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); | ||
94 | } | ||
95 | return rxbuf[0]; | ||
96 | #endif | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * @brief Writes a value into a register. | ||
101 | * @pre The I2C interface must be initialized and the driver started. | ||
102 | * | ||
103 | * @param[in] i2cp pointer to the I2C interface | ||
104 | * @param[in] sad slave address without R bit | ||
105 | * @param[in] sub sub-register address | ||
106 | * @param[in] value the value to be written | ||
107 | * @param[out] message pointer to message | ||
108 | */ | ||
109 | void lsm6ds0WriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
110 | uint8_t value, msg_t* message) { | ||
111 | |||
112 | uint8_t txbuf[2]; | ||
113 | uint8_t rxbuf; | ||
114 | switch (sub) { | ||
115 | default: | ||
116 | /* Reserved register must not be written, according to the datasheet | ||
117 | * this could permanently damage the device. | ||
118 | */ | ||
119 | chDbgAssert(FALSE, "lsm6ds0WriteRegister(), reserved register"); | ||
120 | case LSM6DS0_SUB_WHO_AM_I: | ||
121 | case LSM6DS0_SUB_INT_GEN_SRC_G: | ||
122 | case LSM6DS0_SUB_OUT_TEMP_L: | ||
123 | case LSM6DS0_SUB_OUT_TEMP_H: | ||
124 | case LSM6DS0_SUB_STATUS_REG1: | ||
125 | case LSM6DS0_SUB_OUT_X_L_G: | ||
126 | case LSM6DS0_SUB_OUT_X_H_G: | ||
127 | case LSM6DS0_SUB_OUT_Y_L_G: | ||
128 | case LSM6DS0_SUB_OUT_Y_H_G: | ||
129 | case LSM6DS0_SUB_OUT_Z_L_G: | ||
130 | case LSM6DS0_SUB_OUT_Z_H_G: | ||
131 | case LSM6DS0_SUB_INT_GEN_SRC_XL: | ||
132 | case LSM6DS0_SUB_STATUS_REG2: | ||
133 | case LSM6DS0_SUB_OUT_X_L_XL: | ||
134 | case LSM6DS0_SUB_OUT_X_H_XL: | ||
135 | case LSM6DS0_SUB_OUT_Y_L_XL: | ||
136 | case LSM6DS0_SUB_OUT_Y_H_XL: | ||
137 | case LSM6DS0_SUB_OUT_Z_L_XL: | ||
138 | case LSM6DS0_SUB_OUT_Z_H_XL: | ||
139 | case LSM6DS0_SUB_FIFO_SRC: | ||
140 | /* Read only registers cannot be written, the command is ignored.*/ | ||
141 | return; | ||
142 | case LSM6DS0_SUB_ACT_THS: | ||
143 | case LSM6DS0_SUB_ACT_DUR: | ||
144 | case LSM6DS0_SUB_INT_GEN_CFG_XL: | ||
145 | case LSM6DS0_SUB_INT_GEN_THS_X_XL: | ||
146 | case LSM6DS0_SUB_INT_GEN_THS_Y_XL: | ||
147 | case LSM6DS0_SUB_INT_GEN_THS_Z_XL: | ||
148 | case LSM6DS0_SUB_INT_GEN_DUR_XL: | ||
149 | case LSM6DS0_SUB_REFERENCE_G: | ||
150 | case LSM6DS0_SUB_INT_CTRL: | ||
151 | case LSM6DS0_SUB_CTRL_REG1_G: | ||
152 | case LSM6DS0_SUB_CTRL_REG2_G: | ||
153 | case LSM6DS0_SUB_CTRL_REG3_G: | ||
154 | case LSM6DS0_SUB_ORIENT_CFG_G: | ||
155 | case LSM6DS0_SUB_CTRL_REG4: | ||
156 | case LSM6DS0_SUB_CTRL_REG5_XL: | ||
157 | case LSM6DS0_SUB_CTRL_REG6_XL: | ||
158 | case LSM6DS0_SUB_CTRL_REG7_XL: | ||
159 | case LSM6DS0_SUB_CTRL_REG8: | ||
160 | case LSM6DS0_SUB_CTRL_REG9: | ||
161 | case LSM6DS0_SUB_CTRL_REG10: | ||
162 | case LSM6DS0_SUB_FIFO_CTRL: | ||
163 | case LSM6DS0_SUB_INT_GEN_CFG_G: | ||
164 | case LSM6DS0_SUB_INT_GEN_THS_XH_G: | ||
165 | case LSM6DS0_SUB_INT_GEN_THS_XL_G: | ||
166 | case LSM6DS0_SUB_INT_GEN_THS_YH_G: | ||
167 | case LSM6DS0_SUB_INT_GEN_THS_YL_G: | ||
168 | case LSM6DS0_SUB_INT_GEN_THS_ZH_G: | ||
169 | case LSM6DS0_SUB_INT_GEN_THS_ZL_G: | ||
170 | case LSM6DS0_SUB_INT_GEN_DUR_G: | ||
171 | txbuf[0] = sub; | ||
172 | txbuf[1] = value; | ||
173 | if(message != NULL){ | ||
174 | *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, | ||
175 | TIME_INFINITE); | ||
176 | } | ||
177 | else{ | ||
178 | i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); | ||
179 | } | ||
180 | break; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.h b/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.h new file mode 100644 index 000000000..57e205779 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.h | |||
@@ -0,0 +1,482 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file lsm6ds0.h | ||
31 | * @brief LSM6DS0 MEMS interface module header. | ||
32 | * | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef _LSM6DS0_H_ | ||
37 | #define _LSM6DS0_H_ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Driver constants. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | #define LSM6DS0_ACC_SENS_2G ((float)1671.095f) /*!< Accelerometer sensitivity with 2 G full scale [LSB * s^2 / m] */ | ||
44 | #define LSM6DS0_ACC_SENS_4G ((float)835.547f) /*!< Accelerometer sensitivity with 4 G full scale [LSB * s^2 / m] */ | ||
45 | #define LSM6DS0_ACC_SENS_8G ((float)417.774) /*!< Accelerometer sensitivity with 8 G full scale [LSB * s^2 / m] */ | ||
46 | #define LSM6DS0_ACC_SENS_16G ((float)139.258f) /*!< Accelerometer sensitivity with 16 G full scale [LSB * s^2 / m] */ | ||
47 | |||
48 | #define LSM6DS0_GYRO_SENS_245DPS ((float)114.286f) /*!< Gyroscope sensitivity with 245 dps full scale [LSB * s / �] */ | ||
49 | #define LSM6DS0_GYRO_SENS_500DPS ((float)57.143f) /*!< Gyroscope sensitivity with 500 dps full scale [LSB * s / �] */ | ||
50 | #define LSM6DS0_GYRO_SENS_2000DPS ((float)14.286f) /*!< Gyroscope sensitivity with 2000 dps full scale [LSB * s / �] */ | ||
51 | /** | ||
52 | * @name LSM6DS0 register names | ||
53 | * @{ | ||
54 | */ | ||
55 | /******************************************************************************/ | ||
56 | /* */ | ||
57 | /* LSM6DS0 on board MEMS */ | ||
58 | /* */ | ||
59 | /******************************************************************************/ | ||
60 | /***************** Bit definition for I2C/SPI communication *****************/ | ||
61 | #define LSM6DS0_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ | ||
62 | #define LSM6DS0_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
63 | #define LSM6DS0_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
64 | #define LSM6DS0_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ | ||
65 | #define LSM6DS0_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
66 | #define LSM6DS0_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
67 | #define LSM6DS0_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ | ||
68 | |||
69 | #define LSM6DS0_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ | ||
70 | |||
71 | /***************** Bit definition for Registers Addresses *******************/ | ||
72 | #define LSM6DS0_SUB_ACT_THS ((uint8_t)0x04) /*!< Activity threshold register */ | ||
73 | #define LSM6DS0_SUB_ACT_DUR ((uint8_t)0x05) /*!< Inactivity duration register */ | ||
74 | #define LSM6DS0_SUB_INT_GEN_CFG_XL ((uint8_t)0x06) /*!< Accelerometer interrupt generator configuration register */ | ||
75 | #define LSM6DS0_SUB_INT_GEN_THS_X_XL ((uint8_t)0x07) /*!< Accelerometer X-axis interrupt threshold register */ | ||
76 | #define LSM6DS0_SUB_INT_GEN_THS_Y_XL ((uint8_t)0x08) /*!< Accelerometer Y-axis interrupt threshold register */ | ||
77 | #define LSM6DS0_SUB_INT_GEN_THS_Z_XL ((uint8_t)0x09) /*!< Accelerometer Z-axis interrupt threshold register */ | ||
78 | #define LSM6DS0_SUB_INT_GEN_DUR_XL ((uint8_t)0x0A) /*!< Accelerometer interrupt duration register */ | ||
79 | #define LSM6DS0_SUB_REFERENCE_G ((uint8_t)0x0B) /*!< Gyroscope reference value register for digital high-pass filter */ | ||
80 | #define LSM6DS0_SUB_INT_CTRL ((uint8_t)0x0C) /*!< INT pin control register */ | ||
81 | #define LSM6DS0_SUB_WHO_AM_I ((uint8_t)0x0F) /*!< Who_AM_I register */ | ||
82 | #define LSM6DS0_SUB_CTRL_REG1_G ((uint8_t)0x10) /*!< Gyroscope control register 1 */ | ||
83 | #define LSM6DS0_SUB_CTRL_REG2_G ((uint8_t)0x11) /*!< Gyroscope control register 2 */ | ||
84 | #define LSM6DS0_SUB_CTRL_REG3_G ((uint8_t)0x12) /*!< Gyroscope control register 3 */ | ||
85 | #define LSM6DS0_SUB_ORIENT_CFG_G ((uint8_t)0x13) /*!< Gyroscope sign and orientation register */ | ||
86 | #define LSM6DS0_SUB_INT_GEN_SRC_G ((uint8_t)0x14) /*!< Gyroscope interrupt source register */ | ||
87 | #define LSM6DS0_SUB_OUT_TEMP_L ((uint8_t)0x15) /*!< Temperature data output low register */ | ||
88 | #define LSM6DS0_SUB_OUT_TEMP_H ((uint8_t)0x16) /*!< Temperature data output high register */ | ||
89 | #define LSM6DS0_SUB_STATUS_REG1 ((uint8_t)0x17) /*!< Status register 1 */ | ||
90 | #define LSM6DS0_SUB_OUT_X_L_G ((uint8_t)0x18) /*!< Gyroscope X-axis low output register */ | ||
91 | #define LSM6DS0_SUB_OUT_X_H_G ((uint8_t)0x19) /*!< Gyroscope X-axis high output register */ | ||
92 | #define LSM6DS0_SUB_OUT_Y_L_G ((uint8_t)0x1A) /*!< Gyroscope Y-axis low output register */ | ||
93 | #define LSM6DS0_SUB_OUT_Y_H_G ((uint8_t)0x1B) /*!< Gyroscope Y-axis high output register */ | ||
94 | #define LSM6DS0_SUB_OUT_Z_L_G ((uint8_t)0x1C) /*!< Gyroscope Z-axis low output register */ | ||
95 | #define LSM6DS0_SUB_OUT_Z_H_G ((uint8_t)0x1D) /*!< Gyroscope Z-axis high output register */ | ||
96 | #define LSM6DS0_SUB_CTRL_REG4 ((uint8_t)0x1E) /*!< Control register 4 */ | ||
97 | #define LSM6DS0_SUB_CTRL_REG5_XL ((uint8_t)0x1F) /*!< Accelerometer Control Register 5 */ | ||
98 | #define LSM6DS0_SUB_CTRL_REG6_XL ((uint8_t)0x20) /*!< Accelerometer Control Register 6 */ | ||
99 | #define LSM6DS0_SUB_CTRL_REG7_XL ((uint8_t)0x21) /*!< Accelerometer Control Register 7 */ | ||
100 | #define LSM6DS0_SUB_CTRL_REG8 ((uint8_t)0x22) /*!< Control register 8 */ | ||
101 | #define LSM6DS0_SUB_CTRL_REG9 ((uint8_t)0x23) /*!< Control register 9 */ | ||
102 | #define LSM6DS0_SUB_CTRL_REG10 ((uint8_t)0x24) /*!< Control register 10 */ | ||
103 | #define LSM6DS0_SUB_INT_GEN_SRC_XL ((uint8_t)0x26) /*!< Accelerometer interrupt source register */ | ||
104 | #define LSM6DS0_SUB_STATUS_REG2 ((uint8_t)0x27) /*!< Status register */ | ||
105 | #define LSM6DS0_SUB_OUT_X_L_XL ((uint8_t)0x28) /*!< Accelerometer X-axis low output register */ | ||
106 | #define LSM6DS0_SUB_OUT_X_H_XL ((uint8_t)0x29) /*!< Accelerometer X-axis high output register */ | ||
107 | #define LSM6DS0_SUB_OUT_Y_L_XL ((uint8_t)0x2A) /*!< Accelerometer Y-axis low output register */ | ||
108 | #define LSM6DS0_SUB_OUT_Y_H_XL ((uint8_t)0x2B) /*!< Accelerometer Y-axis high output register */ | ||
109 | #define LSM6DS0_SUB_OUT_Z_L_XL ((uint8_t)0x2C) /*!< Accelerometer Z-axis low output register */ | ||
110 | #define LSM6DS0_SUB_OUT_Z_H_XL ((uint8_t)0x2D) /*!< Accelerometer Z-axis high output register */ | ||
111 | #define LSM6DS0_SUB_FIFO_CTRL ((uint8_t)0x2E) /*!< FIFO control register */ | ||
112 | #define LSM6DS0_SUB_FIFO_SRC ((uint8_t)0x2F) /*!< FIFO status control register */ | ||
113 | #define LSM6DS0_SUB_INT_GEN_CFG_G ((uint8_t)0x30) /*!< Gyroscope interrupt generator configuration register */ | ||
114 | #define LSM6DS0_SUB_INT_GEN_THS_XH_G ((uint8_t)0x31) /*!< Gyroscope X-axis low interrupt generator threshold registers */ | ||
115 | #define LSM6DS0_SUB_INT_GEN_THS_XL_G ((uint8_t)0x32) /*!< Gyroscope X-axis high interrupt generator threshold registers */ | ||
116 | #define LSM6DS0_SUB_INT_GEN_THS_YH_G ((uint8_t)0x33) /*!< Gyroscope Y-axis low interrupt generator threshold registers */ | ||
117 | #define LSM6DS0_SUB_INT_GEN_THS_YL_G ((uint8_t)0x34) /*!< Gyroscope Y-axis high interrupt generator threshold registers */ | ||
118 | #define LSM6DS0_SUB_INT_GEN_THS_ZH_G ((uint8_t)0x35) /*!< Gyroscope Z-axis low interrupt generator threshold registers */ | ||
119 | #define LSM6DS0_SUB_INT_GEN_THS_ZL_G ((uint8_t)0x36) /*!< Gyroscope Z-axis high interrupt generator threshold registers */ | ||
120 | #define LSM6DS0_SUB_INT_GEN_DUR_G ((uint8_t)0x37) /*!< Gyroscope interrupt generator duration register */ | ||
121 | |||
122 | /** @} */ | ||
123 | |||
124 | /*===========================================================================*/ | ||
125 | /* Driver pre-compile time settings. */ | ||
126 | /*===========================================================================*/ | ||
127 | |||
128 | /*===========================================================================*/ | ||
129 | /* Derived constants and error checks. */ | ||
130 | /*===========================================================================*/ | ||
131 | |||
132 | /*===========================================================================*/ | ||
133 | /* Driver data structures and types. */ | ||
134 | /*===========================================================================*/ | ||
135 | |||
136 | /** | ||
137 | * @name Generic LSM6DS0 data structures and types | ||
138 | * @{ | ||
139 | */ | ||
140 | |||
141 | /** | ||
142 | * @brief Accelerometer and Gyroscope Slave Address | ||
143 | */ | ||
144 | typedef enum { | ||
145 | LSM6DS0_SAD_GND = 0x6A, /*!< LSM6DS0 Slave Address when SA1 is to GND */ | ||
146 | LSM6DS0_SAD_VCC = 0x6B /*!< LSM6DS0 Slave Address when SA1 is to VCC */ | ||
147 | }LSM6DS0_SAD_t; | ||
148 | |||
149 | /** | ||
150 | * @brief Accelerometer and Gyroscope Block Data Update | ||
151 | */ | ||
152 | typedef enum | ||
153 | { | ||
154 | LSM6DS0_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ | ||
155 | LSM6DS0_BDU_BLOCKED = 0x40 /*!< Single Update: output registers not updated until MSB and LSB reading */ | ||
156 | }LSM6DS0_BDU_t; | ||
157 | |||
158 | /** | ||
159 | * @brief Accelerometer and Gyroscope Endianness | ||
160 | */ | ||
161 | typedef enum | ||
162 | { | ||
163 | LSM6DS0_END_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ | ||
164 | LSM6DS0_END_BIG = 0x20 /*!< Big Endian: data MSB @ lower address */ | ||
165 | }LSM6DS0_END_t; | ||
166 | /** @} */ | ||
167 | |||
168 | /** | ||
169 | * @name Accelerometer data structures and types | ||
170 | * @{ | ||
171 | */ | ||
172 | |||
173 | /** | ||
174 | * @brief Accelerometer Decimation Mode | ||
175 | */ | ||
176 | typedef enum { | ||
177 | LSM6DS0_ACC_DEC_DISABLED = 0x00, /*!< NO decimation */ | ||
178 | LSM6DS0_ACC_DEC_X2 = 0x40, /*!< Decimation update every 2 sample */ | ||
179 | LSM6DS0_ACC_DEC_X4 = 0x80, /*!< Decimation update every 4 sample */ | ||
180 | LSM6DS0_ACC_DEC_X8 = 0xC0 /*!< Decimation update every 8 sample */ | ||
181 | }LSM6DS0_ACC_DEC_t; | ||
182 | |||
183 | /** | ||
184 | * @brief Accelerometer Axes Enabling | ||
185 | */ | ||
186 | typedef enum{ | ||
187 | LSM6DS0_ACC_AE_DISABLED = 0x00, /*!< Axes all disabled */ | ||
188 | LSM6DS0_ACC_AE_X = 0x08, /*!< Only X-axis enabled */ | ||
189 | LSM6DS0_ACC_AE_Y = 0x10, /*!< Only Y-axis enabled */ | ||
190 | LSM6DS0_ACC_AE_XY = 0x18, /*!< X & Y axes enabled */ | ||
191 | LSM6DS0_ACC_AE_Z = 0x20, /*!< Only Z-axis enabled */ | ||
192 | LSM6DS0_ACC_AE_XZ = 0x28, /*!< X & Z axes enabled */ | ||
193 | LSM6DS0_ACC_AE_YZ = 0x30, /*!< Y & Z axes enabled */ | ||
194 | LSM6DS0_ACC_AE_XYZ = 0x38 /*!< All axes enabled */ | ||
195 | }LSM6DS0_ACC_AE_t; | ||
196 | |||
197 | /** | ||
198 | * @brief Accelerometer Output Data Rate | ||
199 | */ | ||
200 | typedef enum { | ||
201 | LSM6DS0_ACC_ODR_PD = 0x00, /*!< Power down */ | ||
202 | LSM6DS0_ACC_ODR_10Hz = 0x20, /*!< Output Data Rate = 10 Hz */ | ||
203 | LSM6DS0_ACC_ODR_50Hz = 0x40, /*!< Output Data Rate = 50 Hz */ | ||
204 | LSM6DS0_ACC_ODR_119Hz = 0x60, /*!< Output Data Rate = 119 Hz */ | ||
205 | LSM6DS0_ACC_ODR_238Hz = 0x80, /*!< Output Data Rate = 238 Hz */ | ||
206 | LSM6DS0_ACC_ODR_476Hz = 0xA0, /*!< Output Data Rate = 476 Hz */ | ||
207 | LSM6DS0_ACC_ODR_952Hz = 0xC0 /*!< Output Data Rate = 952 Hz */ | ||
208 | }LSM6DS0_ACC_ODR_t; | ||
209 | |||
210 | /** | ||
211 | * @brief Accelerometer Full Scale | ||
212 | */ | ||
213 | typedef enum { | ||
214 | LSM6DS0_ACC_FS_2G = 0x00, /*!< �2 g m/s^2 */ | ||
215 | LSM6DS0_ACC_FS_4G = 0x10, /*!< �4 g m/s^2 */ | ||
216 | LSM6DS0_ACC_FS_8G = 0x18, /*!< �8 g m/s^2 */ | ||
217 | LSM6DS0_ACC_FS_16G = 0x08 /*!< �16 g m/s^2 */ | ||
218 | }LSM6DS0_ACC_FS_t; | ||
219 | |||
220 | /** | ||
221 | * @brief Accelerometer Antialiasing filter Bandwidth Selection | ||
222 | */ | ||
223 | typedef enum { | ||
224 | LSM6DS0_ACC_BW_408Hz = 0x00, /*!< AA filter bandwidth = 408 Hz */ | ||
225 | LSM6DS0_ACC_BW_211Hz = 0x01, /*!< AA filter bandwidth = 211 Hz */ | ||
226 | LSM6DS0_ACC_BW_105Hz = 0x02, /*!< AA filter bandwidth = 105 Hz */ | ||
227 | LSM6DS0_ACC_BW_50Hz = 0x03, /*!< AA filter bandwidth = 50 Hz */ | ||
228 | LSM6DS0_ACC_BW_ACCORDED = 0x04, /*!< AA filter bandwidth chosen by ODR selection */ | ||
229 | }LSM6DS0_ACC_BW_t; | ||
230 | |||
231 | /** | ||
232 | * @brief Accelerometer High Resolution mode | ||
233 | */ | ||
234 | typedef enum | ||
235 | { | ||
236 | LSM6DS0_ACC_HR_Disabled = 0x00, /*!< High resolution output mode disabled, FDS bypassed */ | ||
237 | LSM6DS0_ACC_HR_EN_9 = 0xC4, /*!< High resolution output mode enabled, LP cutoff = ODR/9, FDS enabled */ | ||
238 | LSM6DS0_ACC_HR_EN_50 = 0x84, /*!< High resolution output mode enabled, LP cutoff = ODR/50, FDS enabled */ | ||
239 | LSM6DS0_ACC_HR_EN_100 = 0xA4, /*!< High resolution output mode enabled, LP cutoff = ODR/100, FDS enabled */ | ||
240 | LSM6DS0_ACC_HR_EN_400 = 0xE4, /*!< High resolution output mode enabled, LP cutoff = ODR/400, FDS enabled */ | ||
241 | }LSM6DS0_ACC_HR_t; | ||
242 | |||
243 | /** | ||
244 | * @brief HP filter for interrupt | ||
245 | */ | ||
246 | typedef enum | ||
247 | { | ||
248 | LSM6DS0_ACC_HPIS1_BYPASSED = 0x00, /*!< High-pass filter bypassed */ | ||
249 | LSM6DS0_ACC_HPIS1_ENABLED = 0x01 /*!< High-pass filter enabled for accelerometer interrupt function on interrupt */ | ||
250 | }LSM6DS0_ACC_HPIS1_t; | ||
251 | |||
252 | /** | ||
253 | * @brief Accelerometer configuration structure. | ||
254 | */ | ||
255 | typedef struct { | ||
256 | |||
257 | /** | ||
258 | * @brief LSM6DS0 Slave Address | ||
259 | */ | ||
260 | LSM6DS0_SAD_t slaveaddress; | ||
261 | /** | ||
262 | * @brief Accelerometer Decimation Mode | ||
263 | */ | ||
264 | LSM6DS0_ACC_DEC_t decimation; | ||
265 | /** | ||
266 | * @brief Accelerometer Output Data Rate | ||
267 | */ | ||
268 | LSM6DS0_ACC_ODR_t outputdatarate; | ||
269 | /** | ||
270 | * @brief Accelerometer Antialiasing filter Bandwidth Selection | ||
271 | */ | ||
272 | LSM6DS0_ACC_BW_t bandwidth; | ||
273 | /** | ||
274 | * @brief Accelerometer Full Scale | ||
275 | */ | ||
276 | LSM6DS0_ACC_FS_t fullscale; | ||
277 | /** | ||
278 | * @brief Accelerometer Axes Enabling | ||
279 | */ | ||
280 | LSM6DS0_ACC_AE_t axesenabling; | ||
281 | /** | ||
282 | * @brief Accelerometer High Resolution mode | ||
283 | */ | ||
284 | LSM6DS0_ACC_HR_t highresmode; | ||
285 | /** | ||
286 | * @brief HP filter for interrupt | ||
287 | */ | ||
288 | LSM6DS0_ACC_HPIS1_t hpfirq; | ||
289 | /** | ||
290 | * @brief LSM6DS0 Endianness | ||
291 | */ | ||
292 | LSM6DS0_END_t endianess; | ||
293 | /** | ||
294 | * @brief LSM6DS0 Block Data Update | ||
295 | */ | ||
296 | LSM6DS0_BDU_t blockdataupdate; | ||
297 | } LSM6DS0_ACC_Config; | ||
298 | /** @} */ | ||
299 | |||
300 | /** | ||
301 | * @name Gyroscope data structures and types | ||
302 | * @{ | ||
303 | */ | ||
304 | |||
305 | /** | ||
306 | * @brief Gyroscope Output Data Rate | ||
307 | */ | ||
308 | typedef enum { | ||
309 | LSM6DS0_GYRO_ODR_PD = 0x00, /*!< Power down */ | ||
310 | LSM6DS0_GYRO_ODR_14_9Hz_CO_5Hz = 0x20, /*!< Output Data Rate = 14.9 Hz, CutOff = 5Hz */ | ||
311 | LSM6DS0_GYRO_ODR_59_5Hz_CO_16Hz = 0x40, /*!< Output Data Rate = 59.5 Hz, CutOff = 16Hz */ | ||
312 | LSM6DS0_GYRO_ODR_119Hz_CO_14Hz = 0x60, /*!< Output Data Rate = 119 Hz, CutOff = 14Hz */ | ||
313 | LSM6DS0_GYRO_ODR_119Hz_CO_31Hz = 0x61, /*!< Output Data Rate = 119 Hz, CutOff = 31Hz */ | ||
314 | LSM6DS0_GYRO_ODR_238Hz_CO_14Hz = 0x80, /*!< Output Data Rate = 238 Hz, CutOff = 14Hz */ | ||
315 | LSM6DS0_GYRO_ODR_238Hz_CO_29Hz = 0x81, /*!< Output Data Rate = 328 Hz, CutOff = 29Hz */ | ||
316 | LSM6DS0_GYRO_ODR_238Hz_CO_63Hz = 0x82, /*!< Output Data Rate = 238 Hz, CutOff = 63Hz */ | ||
317 | LSM6DS0_GYRO_ODR_238Hz_CO_78Hz = 0x83, /*!< Output Data Rate = 476 Hz, CutOff = 78Hz */ | ||
318 | LSM6DS0_GYRO_ODR_476Hz_CO_21Hz = 0xA0, /*!< Output Data Rate = 476 Hz, CutOff = 21Hz */ | ||
319 | LSM6DS0_GYRO_ODR_476Hz_CO_28Hz = 0xA1, /*!< Output Data Rate = 238 Hz, CutOff = 28Hz */ | ||
320 | LSM6DS0_GYRO_ODR_476Hz_CO_57Hz = 0xA2, /*!< Output Data Rate = 476 Hz, CutOff = 57Hz */ | ||
321 | LSM6DS0_GYRO_ODR_476Hz_CO_100Hz = 0xA3, /*!< Output Data Rate = 476 Hz, CutOff = 100Hz */ | ||
322 | LSM6DS0_GYRO_ODR_952Hz_CO_33Hz = 0xC0, /*!< Output Data Rate = 952 Hz, CutOff = 33Hz */ | ||
323 | LSM6DS0_GYRO_ODR_952Hz_CO_40Hz = 0xC1, /*!< Output Data Rate = 952 Hz, CutOff = 40Hz */ | ||
324 | LSM6DS0_GYRO_ODR_952Hz_CO_58Hz = 0xC2, /*!< Output Data Rate = 952 Hz, CutOff = 58Hz */ | ||
325 | LSM6DS0_GYRO_ODR_952Hz_CO_100Hz = 0xC3 /*!< Output Data Rate = 952 Hz, CutOff = 100Hz */ | ||
326 | }LSM6DS0_GYRO_ODR_t; | ||
327 | |||
328 | /** | ||
329 | * @brief Gyroscope Full Scale | ||
330 | */ | ||
331 | typedef enum { | ||
332 | LSM6DS0_GYRO_FS_245DSP = 0x00, /*!< �245 degrees per second */ | ||
333 | LSM6DS0_GYRO_FS_500DSP = 0x08, /*!< �500 degrees per second */ | ||
334 | LSM6DS0_GYRO_FS_2000DSP = 0x18 /*!< �2000 degrees per second */ | ||
335 | }LSM6DS0_GYRO_FS_t; | ||
336 | |||
337 | /** | ||
338 | * @brief Gyroscope Output Selection | ||
339 | */ | ||
340 | typedef enum { | ||
341 | LSM6DS0_GYRO_OUT_SEL_BYPASS = 0x00, /*!< Output not filtered */ | ||
342 | LSM6DS0_GYRO_OUT_SEL_FILTERED = 0x01, /*!< Output filtered */ | ||
343 | }LSM6DS0_GYRO_OUT_SEL_t; | ||
344 | |||
345 | /** | ||
346 | * @brief Gyroscope Interrupt Selection | ||
347 | */ | ||
348 | typedef enum { | ||
349 | LSM6DS0_GYRO_INT_SEL_BYPASS = 0x00, /*!< Interrupt generator signal not filtered */ | ||
350 | LSM6DS0_GYRO_INT_SEL_FILTERED = 0x08, /*!< Interrupt generator signal filtered */ | ||
351 | }LSM6DS0_GYRO_INT_SEL_t; | ||
352 | |||
353 | /** | ||
354 | * @brief Gyroscope Low Power Mode | ||
355 | */ | ||
356 | typedef enum { | ||
357 | LSM6DS0_GYRO_LP_MODE_HIGH_PERFORMANCE = 0x00, /*!< High performance */ | ||
358 | LSM6DS0_GYRO_LP_MODE_LOW_POWER = 0x80, /*!< Low power */ | ||
359 | }LSM6DS0_GYRO_LP_MODE_t; | ||
360 | |||
361 | /** | ||
362 | * @brief Gyroscope High Pass Filter Cutoff Selection | ||
363 | */ | ||
364 | typedef enum { | ||
365 | LSM6DS0_GYRO_HPCF_DISABLED = 0x00, /*!< HP filter disabled */ | ||
366 | LSM6DS0_GYRO_HPCF_0 = 0x40, /*!< Config 0 refer to table 48 of DOcID025604 Rev 3 */ | ||
367 | LSM6DS0_GYRO_HPCF_1 = 0x41, /*!< Config 1 refer to table 48 of DOcID025604 Rev 3 */ | ||
368 | LSM6DS0_GYRO_HPCF_2 = 0x42, /*!< Config 2 refer to table 48 of DOcID025604 Rev 3 */ | ||
369 | LSM6DS0_GYRO_HPCF_3 = 0x43, /*!< Config 3 refer to table 48 of DOcID025604 Rev 3 */ | ||
370 | LSM6DS0_GYRO_HPCF_4 = 0x44, /*!< Config 4 refer to table 48 of DOcID025604 Rev 3 */ | ||
371 | LSM6DS0_GYRO_HPCF_5 = 0x45, /*!< Config 5 refer to table 48 of DOcID025604 Rev 3 */ | ||
372 | LSM6DS0_GYRO_HPCF_6 = 0x46, /*!< Config 6 refer to table 48 of DOcID025604 Rev 3 */ | ||
373 | LSM6DS0_GYRO_HPCF_7 = 0x47, /*!< Config 7 refer to table 48 of DOcID025604 Rev 3 */ | ||
374 | LSM6DS0_GYRO_HPCF_8 = 0x48, /*!< Config 8 refer to table 48 of DOcID025604 Rev 3 */ | ||
375 | LSM6DS0_GYRO_HPCF_9 = 0x49, /*!< Config 9 refer to table 48 of DOcID025604 Rev 3 */ | ||
376 | LSM6DS0_GYRO_HPCF_10 = 0x4A /*!< Config 10 refer to table 48 of DOcID025604 Rev 3 */ | ||
377 | }LSM6DS0_GYRO_HPCF_t; | ||
378 | |||
379 | /** | ||
380 | * @brief Gyroscope Axes Enabling | ||
381 | */ | ||
382 | typedef enum{ | ||
383 | LSM6DS0_GYRO_AE_DISABLED = 0x00, /*!< Axes all disabled */ | ||
384 | LSM6DS0_GYRO_AE_X = 0x08, /*!< Only X-axis enabled */ | ||
385 | LSM6DS0_GYRO_AE_Y = 0x10, /*!< Only Y-axis enabled */ | ||
386 | LSM6DS0_GYRO_AE_XY = 0x18, /*!< X & Y axes enabled */ | ||
387 | LSM6DS0_GYRO_AE_Z = 0x20, /*!< Only Z-axis enabled */ | ||
388 | LSM6DS0_GYRO_AE_XZ = 0x28, /*!< X & Z axes enabled */ | ||
389 | LSM6DS0_GYRO_AE_YZ = 0x30, /*!< Y & Z axes enabled */ | ||
390 | LSM6DS0_GYRO_AE_XYZ = 0x38 /*!< All axes enabled */ | ||
391 | }LSM6DS0_GYRO_AE_t; | ||
392 | |||
393 | /** | ||
394 | * @brief Gyroscope Decimation Mode | ||
395 | */ | ||
396 | typedef enum { | ||
397 | LSM6DS0_GYRO_DEC_DISABLED = 0x00, /*!< NO decimation */ | ||
398 | LSM6DS0_GYRO_DEC_X2 = 0x40, /*!< Decimation update every 2 sample */ | ||
399 | LSM6DS0_GYRO_DEC_X4 = 0x80, /*!< Decimation update every 4 sample */ | ||
400 | LSM6DS0_GYRO_DEC_X8 = 0xC0 /*!< Decimation update every 8 sample */ | ||
401 | }LSM6DS0_GYRO_DEC_t; | ||
402 | |||
403 | /** | ||
404 | * @brief Gyroscope Sleep Mode | ||
405 | */ | ||
406 | typedef enum { | ||
407 | LSM6DS0_GYRO_SLP_DISABLED = 0x00, /*!< Gyroscope sleep mode disabled */ | ||
408 | LSM6DS0_GYRO_SLP_ENABLED = 0x40 /*!< Gyroscope sleep mode enabled */ | ||
409 | }LSM6DS0_GYRO_SLP_t; | ||
410 | /** | ||
411 | * @brief Gyroscope configuration structure. | ||
412 | */ | ||
413 | typedef struct { | ||
414 | /** | ||
415 | * @brief LSM6DS0 Slave Address | ||
416 | */ | ||
417 | LSM6DS0_SAD_t slaveaddress; | ||
418 | /** | ||
419 | * @brief Gyroscope Output Data Rate | ||
420 | */ | ||
421 | LSM6DS0_GYRO_ODR_t outputdatarate; | ||
422 | /** | ||
423 | * @brief Gyroscope Full Scale | ||
424 | */ | ||
425 | LSM6DS0_GYRO_FS_t fullscale; | ||
426 | /** | ||
427 | * @brief Gyroscope Output Selection | ||
428 | */ | ||
429 | LSM6DS0_GYRO_OUT_SEL_t outputselect; | ||
430 | /** | ||
431 | * @brief Gyroscope Interrupt Selection | ||
432 | */ | ||
433 | LSM6DS0_GYRO_INT_SEL_t irqselect; | ||
434 | /** | ||
435 | * @brief Gyroscope Low Power Mode | ||
436 | */ | ||
437 | LSM6DS0_GYRO_LP_MODE_t lowpowermode; | ||
438 | /** | ||
439 | * @brief Gyroscope High Pass Filter Cutoff Selection | ||
440 | */ | ||
441 | LSM6DS0_GYRO_HPCF_t HPCfrequency; | ||
442 | /** | ||
443 | * @brief Gyroscope Axes Enabling | ||
444 | */ | ||
445 | LSM6DS0_GYRO_AE_t axesenabling; | ||
446 | /** | ||
447 | * @brief Gyroscope Decimation Mode | ||
448 | */ | ||
449 | LSM6DS0_GYRO_DEC_t decimation; | ||
450 | /** | ||
451 | * @brief LSM6DS0 Endianness | ||
452 | */ | ||
453 | LSM6DS0_END_t endianess; | ||
454 | /** | ||
455 | * @brief LSM6DS0 Block Data Update | ||
456 | */ | ||
457 | LSM6DS0_BDU_t blockdataupdate; | ||
458 | } LSM6DS0_GYRO_Config; | ||
459 | /** @} */ | ||
460 | /*===========================================================================*/ | ||
461 | /* Driver macros. */ | ||
462 | /*===========================================================================*/ | ||
463 | |||
464 | /*===========================================================================*/ | ||
465 | /* External declarations. */ | ||
466 | /*===========================================================================*/ | ||
467 | |||
468 | #ifdef __cplusplus | ||
469 | extern "C" { | ||
470 | #endif | ||
471 | |||
472 | uint8_t lsm6ds0ReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
473 | msg_t* message); | ||
474 | void lsm6ds0WriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, | ||
475 | uint8_t value, msg_t* message); | ||
476 | #ifdef __cplusplus | ||
477 | } | ||
478 | #endif | ||
479 | |||
480 | #endif /* _LSM6DS0_H_ */ | ||
481 | |||
482 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/others/max7219.c b/lib/chibios-contrib/os/various/devices_lib/others/max7219.c new file mode 100644 index 000000000..0e511671c --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/others/max7219.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file max7219.c | ||
31 | * @brief MAX7219 display driver module code. | ||
32 | * | ||
33 | * @addtogroup max7219 | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "max7219.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Driver exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Driver local variables and types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Driver local functions. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Driver exported functions. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /** | ||
63 | * @brief Reads a generic register value. | ||
64 | * @pre The SPI interface must be initialized and the driver started. | ||
65 | * | ||
66 | * @param[in] spip pointer to the SPI interface | ||
67 | * @param[in] adr address number | ||
68 | * @param[in] data data value. | ||
69 | */ | ||
70 | void max7219WriteRegister(SPIDriver *spip, uint16_t adr, uint8_t data) { | ||
71 | |||
72 | switch (adr) { | ||
73 | default: | ||
74 | return; | ||
75 | case MAX7219_AD_DIGIT_0: | ||
76 | case MAX7219_AD_DIGIT_1: | ||
77 | case MAX7219_AD_DIGIT_2: | ||
78 | case MAX7219_AD_DIGIT_3: | ||
79 | case MAX7219_AD_DIGIT_4: | ||
80 | case MAX7219_AD_DIGIT_5: | ||
81 | case MAX7219_AD_DIGIT_6: | ||
82 | case MAX7219_AD_DIGIT_7: | ||
83 | case MAX7219_AD_DECODE_MODE: | ||
84 | case MAX7219_AD_INTENSITY: | ||
85 | case MAX7219_AD_SCAN_LIMIT: | ||
86 | case MAX7219_AD_SHUTDOWN: | ||
87 | case MAX7219_AD_DISPLAY_TEST: | ||
88 | spiSelect(spip); | ||
89 | uint16_t txbuf = {adr | data}; | ||
90 | spiSend(spip, 1, &txbuf); | ||
91 | spiUnselect(spip); | ||
92 | } | ||
93 | } | ||
94 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/others/max7219.h b/lib/chibios-contrib/os/various/devices_lib/others/max7219.h new file mode 100644 index 000000000..e672be946 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/others/max7219.h | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file MAX7219.h | ||
31 | * @brief MAX7219 display driver module header. | ||
32 | * | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef _MAX7219_H_ | ||
37 | #define _MAX7219_H_ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Driver constants. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | /** | ||
44 | * @name MAX7219 register names | ||
45 | * @{ | ||
46 | */ | ||
47 | /******************************************************************************/ | ||
48 | /* */ | ||
49 | /* MAX7219 display driver */ | ||
50 | /* */ | ||
51 | /******************************************************************************/ | ||
52 | /******************* Bit definition for SPI communication *******************/ | ||
53 | #define MAX7219_DI ((uint16_t)0x00FF) /*!< DI[7:0] Data input */ | ||
54 | #define MAX7219_DI_0 ((uint16_t)0x0001) /*!< bit 0 */ | ||
55 | #define MAX7219_DI_1 ((uint16_t)0x0002) /*!< bit 1 */ | ||
56 | #define MAX7219_DI_2 ((uint16_t)0x0004) /*!< bit 2 */ | ||
57 | #define MAX7219_DI_3 ((uint16_t)0x0008) /*!< bit 3 */ | ||
58 | #define MAX7219_DI_4 ((uint16_t)0x0010) /*!< bit 4 */ | ||
59 | #define MAX7219_DI_5 ((uint16_t)0x0020) /*!< bit 5 */ | ||
60 | #define MAX7219_DI_6 ((uint16_t)0x0040) /*!< bit 6 */ | ||
61 | #define MAX7219_DI_7 ((uint16_t)0x0080) /*!< bit 7 */ | ||
62 | |||
63 | #define MAX7219_AD ((uint16_t)0x0F00) /*!< AD[11:8] Data input */ | ||
64 | #define MAX7219_AD_0 ((uint16_t)0x0100) /*!< bit 8 */ | ||
65 | #define MAX7219_AD_1 ((uint16_t)0x0200) /*!< bit 9 */ | ||
66 | #define MAX7219_AD_2 ((uint16_t)0x0400) /*!< bit 10 */ | ||
67 | #define MAX7219_AD_3 ((uint16_t)0x0800) /*!< bit 11 */ | ||
68 | |||
69 | /****************** Bit definition for Registers Addresses *******************/ | ||
70 | #define MAX7219_AD_NOP ((uint16_t)0x0000) /*!< No operation */ | ||
71 | #define MAX7219_AD_DIGIT_0 ((uint16_t)0x0100) /*!< Digit 0 */ | ||
72 | #define MAX7219_AD_DIGIT_1 ((uint16_t)0x0200) /*!< Digit 1 */ | ||
73 | #define MAX7219_AD_DIGIT_2 ((uint16_t)0x0300) /*!< Digit 2 */ | ||
74 | #define MAX7219_AD_DIGIT_3 ((uint16_t)0x0400) /*!< Digit 3 */ | ||
75 | #define MAX7219_AD_DIGIT_4 ((uint16_t)0x0500) /*!< Digit 4 */ | ||
76 | #define MAX7219_AD_DIGIT_5 ((uint16_t)0x0600) /*!< Digit 5 */ | ||
77 | #define MAX7219_AD_DIGIT_6 ((uint16_t)0x0700) /*!< Digit 6 */ | ||
78 | #define MAX7219_AD_DIGIT_7 ((uint16_t)0x0800) /*!< Digit 7 */ | ||
79 | #define MAX7219_AD_DECODE_MODE ((uint16_t)0x0900) /*!< Decode mode */ | ||
80 | #define MAX7219_AD_INTENSITY ((uint16_t)0x0A00) /*!< Intensity */ | ||
81 | #define MAX7219_AD_SCAN_LIMIT ((uint16_t)0x0B00) /*!< Scan limit */ | ||
82 | #define MAX7219_AD_SHUTDOWN ((uint16_t)0x0C00) /*!< Shutdown */ | ||
83 | #define MAX7219_AD_DISPLAY_TEST ((uint16_t)0x0F00) /*!< Display test */ | ||
84 | |||
85 | /*************** Bit definition for Registers Configuration *****************/ | ||
86 | /** @} */ | ||
87 | |||
88 | /*===========================================================================*/ | ||
89 | /* Driver pre-compile time settings. */ | ||
90 | /*===========================================================================*/ | ||
91 | |||
92 | /*===========================================================================*/ | ||
93 | /* Derived constants and error checks. */ | ||
94 | /*===========================================================================*/ | ||
95 | |||
96 | #if !HAL_USE_SPI | ||
97 | #error "MAX7219 requires HAL_USE_SPI" | ||
98 | #endif | ||
99 | /*===========================================================================*/ | ||
100 | /* Driver data structures and types. */ | ||
101 | /*===========================================================================*/ | ||
102 | |||
103 | /** | ||
104 | * @name MAX7219 data structures and types | ||
105 | * @{ | ||
106 | * | ||
107 | */ | ||
108 | |||
109 | /** | ||
110 | * @brief MAX7219 operation mode | ||
111 | */ | ||
112 | typedef enum { | ||
113 | MAX7219_OM_Shutdown = 0x00, /*!< Shutdown mode */ | ||
114 | MAX7219_OM_Normal = 0x01 /*!< Normal mode */ | ||
115 | } MAX7219_OM_t; | ||
116 | |||
117 | /** | ||
118 | * @brief MAX7219 decoder mode | ||
119 | */ | ||
120 | typedef enum { | ||
121 | MAX7219_DM_No_decode = 0x00, /*!< No decode */ | ||
122 | MAX7219_DM_CodeB_0 = 0x01, /*!< Code B on Digit 0 */ | ||
123 | MAX7219_DM_CodeB_1 = 0x03, /*!< Code B on Digits 0-1 */ | ||
124 | MAX7219_DM_CodeB_2 = 0x07, /*!< Code B on Digits from 0 to 2 */ | ||
125 | MAX7219_DM_CodeB_3 = 0x0F, /*!< Code B on Digits from 0 to 3 */ | ||
126 | MAX7219_DM_CodeB_4 = 0x1F, /*!< Code B on Digits from 0 to 4 */ | ||
127 | MAX7219_DM_CodeB_5 = 0x3F, /*!< Code B on Digits from 0 to 5 */ | ||
128 | MAX7219_DM_CodeB_6 = 0x7F, /*!< Code B on Digits from 0 to 6 */ | ||
129 | MAX7219_DM_CodeB_7 = 0xFF /*!< Code B on every digit */ | ||
130 | } MAX7219_DM_t; | ||
131 | |||
132 | /** | ||
133 | * @brief MAX7219 intensity mode | ||
134 | */ | ||
135 | typedef enum { | ||
136 | MAX7219_IM_1_32 = 0x00, /*!< 1/32 intensity */ | ||
137 | MAX7219_IM_3_32 = 0x01, /*!< 3/32 intensity */ | ||
138 | MAX7219_IM_5_32 = 0x02, /*!< 5/32 intensity */ | ||
139 | MAX7219_IM_7_32 = 0x03, /*!< 7/32 intensity */ | ||
140 | MAX7219_IM_9_32 = 0x04, /*!< 9/32 intensity */ | ||
141 | MAX7219_IM_11_32 = 0x05, /*!< 11/32 intensity */ | ||
142 | MAX7219_IM_13_32 = 0x06, /*!< 13/32 intensity */ | ||
143 | MAX7219_IM_15_32 = 0x07, /*!< 15/32 intensity */ | ||
144 | MAX7219_IM_17_32 = 0x08, /*!< 17/32 intensity */ | ||
145 | MAX7219_IM_19_32 = 0x09, /*!< 19/32 intensity */ | ||
146 | MAX7219_IM_21_32 = 0x0A, /*!< 21/32 intensity */ | ||
147 | MAX7219_IM_23_32 = 0x0B, /*!< 23/32 intensity */ | ||
148 | MAX7219_IM_25_32 = 0x0C, /*!< 25/32 intensity */ | ||
149 | MAX7219_IM_27_32 = 0x0D, /*!< 27/32 intensity */ | ||
150 | MAX7219_IM_29_32 = 0x0E, /*!< 29/32 intensity */ | ||
151 | MAX7219_IM_31_32 = 0x0F /*!< 31/32 intensity */ | ||
152 | } MAX7219_IM_t; | ||
153 | |||
154 | /** | ||
155 | * @brief MAX7219 scan line mode | ||
156 | */ | ||
157 | typedef enum { | ||
158 | MAX7219_SL_0 = 0x00, /*!< Scanned digit 0 only */ | ||
159 | MAX7219_SL_1 = 0x01, /*!< Scanned digit 0 & 1 */ | ||
160 | MAX7219_SL_2 = 0x02, /*!< Scanned digit 0 - 2 */ | ||
161 | MAX7219_SL_3 = 0x03, /*!< Scanned digit 0 - 3 */ | ||
162 | MAX7219_SL_4 = 0x04, /*!< Scanned digit 0 - 4 */ | ||
163 | MAX7219_SL_5 = 0x05, /*!< Scanned digit 0 - 5 */ | ||
164 | MAX7219_SL_6 = 0x06, /*!< Scanned digit 0 - 6 */ | ||
165 | MAX7219_SL_7 = 0x07 /*!< Scanned digit 0 - 7 */ | ||
166 | } MAX7219_SL_t; | ||
167 | /** @} */ | ||
168 | /*===========================================================================*/ | ||
169 | /* Driver macros. */ | ||
170 | /*===========================================================================*/ | ||
171 | |||
172 | /*===========================================================================*/ | ||
173 | /* External declarations. */ | ||
174 | /*===========================================================================*/ | ||
175 | |||
176 | #ifdef __cplusplus | ||
177 | extern "C" { | ||
178 | #endif | ||
179 | |||
180 | void max7219WriteRegister(SPIDriver *spip, uint16_t adr, uint8_t data); | ||
181 | #ifdef __cplusplus | ||
182 | } | ||
183 | #endif | ||
184 | #endif /* _MAX7219_H_ */ | ||
185 | |||
186 | /** @} */ | ||
187 | |||
diff --git a/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.c b/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.c new file mode 100644 index 000000000..f526fbeff --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.c | |||
@@ -0,0 +1,440 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file nrf24l01.c | ||
31 | * @brief NRF24L01 interface module code. | ||
32 | * | ||
33 | * @addtogroup nrf24l01 | ||
34 | * @{ | ||
35 | */ | ||
36 | |||
37 | #include "ch.h" | ||
38 | #include "hal.h" | ||
39 | |||
40 | #include "nrf24l01.h" | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Driver local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | #define ACTIVATE 0x73 | ||
47 | /*===========================================================================*/ | ||
48 | /* Driver exported variables. */ | ||
49 | /*===========================================================================*/ | ||
50 | |||
51 | /*===========================================================================*/ | ||
52 | /* Driver local variables and types. */ | ||
53 | /*===========================================================================*/ | ||
54 | |||
55 | /*===========================================================================*/ | ||
56 | /* Driver local functions. */ | ||
57 | /*===========================================================================*/ | ||
58 | |||
59 | /*===========================================================================*/ | ||
60 | /* Driver exported functions. */ | ||
61 | /*===========================================================================*/ | ||
62 | |||
63 | /** | ||
64 | * @brief Gets the status register value. | ||
65 | * @pre The SPI interface must be initialized and the driver started. | ||
66 | * | ||
67 | * @param[in] spip pointer to the SPI interface | ||
68 | * | ||
69 | * @return the status register value | ||
70 | */ | ||
71 | NRF24L01_status_t nrf24l01GetStatus(SPIDriver *spip) { | ||
72 | uint8_t txbuf = NRF24L01_CMD_NOP; | ||
73 | uint8_t status; | ||
74 | spiSelect(spip); | ||
75 | spiExchange(spip, 1, &txbuf, &status); | ||
76 | spiUnselect(spip); | ||
77 | return status; | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * @brief Reads a generic register value. | ||
82 | * | ||
83 | * @note Cannot be used to set addresses | ||
84 | * @pre The SPI interface must be initialized and the driver started. | ||
85 | * | ||
86 | * @param[in] spip pointer to the SPI interface | ||
87 | * @param[in] reg register number | ||
88 | * @param[out] pvalue pointer to a data buffer | ||
89 | * | ||
90 | * @return the status register value | ||
91 | */ | ||
92 | NRF24L01_status_t nrf24l01ReadRegister(SPIDriver *spip, uint8_t reg, | ||
93 | uint8_t* pvalue) { | ||
94 | uint8_t txbuf = (NRF24L01_CMD_READ | reg); | ||
95 | uint8_t status = 0xFF; | ||
96 | spiSelect(spip); | ||
97 | spiExchange(spip, 1, &txbuf, &status); | ||
98 | spiReceive(spip, 1, pvalue); | ||
99 | spiUnselect(spip); | ||
100 | return status; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * @brief Writes a generic register value. | ||
105 | * | ||
106 | * @note Cannot be used to set addresses | ||
107 | * @pre The SPI interface must be initialized and the driver started. | ||
108 | * | ||
109 | * @param[in] spip pointer to the SPI interface | ||
110 | * @param[in] reg register number | ||
111 | * @param[in] value data value | ||
112 | * | ||
113 | * @return the status register value | ||
114 | */ | ||
115 | NRF24L01_status_t nrf24l01WriteRegister(SPIDriver *spip, uint8_t reg, | ||
116 | uint8_t value) { | ||
117 | |||
118 | uint8_t txbuf[2] = {(NRF24L01_CMD_WRITE | reg), value}; | ||
119 | uint8_t rxbuf[2] = {0xFF, 0xFF}; | ||
120 | switch (reg) { | ||
121 | |||
122 | default: | ||
123 | /* Reserved register must not be written, according to the datasheet | ||
124 | * this could permanently damage the device. | ||
125 | */ | ||
126 | chDbgAssert(FALSE, "lg3d20WriteRegister(), reserved register"); | ||
127 | case NRF24L01_AD_OBSERVE_TX: | ||
128 | case NRF24L01_AD_CD: | ||
129 | case NRF24L01_AD_RX_ADDR_P0: | ||
130 | case NRF24L01_AD_RX_ADDR_P1: | ||
131 | case NRF24L01_AD_RX_ADDR_P2: | ||
132 | case NRF24L01_AD_RX_ADDR_P3: | ||
133 | case NRF24L01_AD_RX_ADDR_P4: | ||
134 | case NRF24L01_AD_RX_ADDR_P5: | ||
135 | case NRF24L01_AD_TX_ADDR: | ||
136 | /* Read only or addresses registers cannot be written, | ||
137 | * the command is ignored. | ||
138 | */ | ||
139 | return 0; | ||
140 | case NRF24L01_AD_CONFIG: | ||
141 | case NRF24L01_AD_EN_AA: | ||
142 | case NRF24L01_AD_EN_RXADDR: | ||
143 | case NRF24L01_AD_SETUP_AW: | ||
144 | case NRF24L01_AD_SETUP_RETR: | ||
145 | case NRF24L01_AD_RF_CH: | ||
146 | case NRF24L01_AD_RF_SETUP: | ||
147 | case NRF24L01_AD_STATUS: | ||
148 | case NRF24L01_AD_RX_PW_P0: | ||
149 | case NRF24L01_AD_RX_PW_P1: | ||
150 | case NRF24L01_AD_RX_PW_P2: | ||
151 | case NRF24L01_AD_RX_PW_P3: | ||
152 | case NRF24L01_AD_RX_PW_P4: | ||
153 | case NRF24L01_AD_RX_PW_P5: | ||
154 | case NRF24L01_AD_FIFO_STATUS: | ||
155 | case NRF24L01_AD_DYNPD: | ||
156 | case NRF24L01_AD_FEATURE: | ||
157 | spiSelect(spip); | ||
158 | spiExchange(spip, 2, txbuf, rxbuf); | ||
159 | spiUnselect(spip); | ||
160 | return rxbuf[0]; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * @brief Writes an address. | ||
167 | * | ||
168 | * @pre The SPI interface must be initialized and the driver started. | ||
169 | * | ||
170 | * @param[in] spip pointer to the SPI interface | ||
171 | * @param[in] reg register number | ||
172 | * @param[in] pvalue pointer to address value | ||
173 | * @param[in] addlen address len | ||
174 | * | ||
175 | * @return the status register value | ||
176 | */ | ||
177 | NRF24L01_status_t nrf24l01WriteAddress(SPIDriver *spip, uint8_t reg, | ||
178 | uint8_t *pvalue, uint8_t addlen) { | ||
179 | |||
180 | uint8_t txbuf[NRF24L01_MAX_ADD_LENGHT + 1]; | ||
181 | uint8_t rxbuf[NRF24L01_MAX_ADD_LENGHT + 1]; | ||
182 | unsigned i; | ||
183 | |||
184 | if(addlen > NRF24L01_MAX_ADD_LENGHT) { | ||
185 | chDbgAssert(FALSE, "nrf24l01WriteAddress(), wrong address length"); | ||
186 | return 0; | ||
187 | } | ||
188 | txbuf[0] = (NRF24L01_CMD_WRITE | reg); | ||
189 | rxbuf[0] = 0xFF; | ||
190 | for(i = 1; i <= addlen; i++) { | ||
191 | txbuf[i] = *(pvalue + (i - 1)); | ||
192 | rxbuf[i] = 0xFF; | ||
193 | } | ||
194 | switch (reg) { | ||
195 | |||
196 | default: | ||
197 | /* Reserved register must not be written, according to the datasheet | ||
198 | * this could permanently damage the device. | ||
199 | */ | ||
200 | chDbgAssert(FALSE, "nrf24l01WriteAddress(), reserved register"); | ||
201 | case NRF24L01_AD_OBSERVE_TX: | ||
202 | case NRF24L01_AD_CD: | ||
203 | case NRF24L01_AD_CONFIG: | ||
204 | case NRF24L01_AD_EN_AA: | ||
205 | case NRF24L01_AD_EN_RXADDR: | ||
206 | case NRF24L01_AD_SETUP_AW: | ||
207 | case NRF24L01_AD_SETUP_RETR: | ||
208 | case NRF24L01_AD_RF_CH: | ||
209 | case NRF24L01_AD_RF_SETUP: | ||
210 | case NRF24L01_AD_STATUS: | ||
211 | case NRF24L01_AD_RX_PW_P0: | ||
212 | case NRF24L01_AD_RX_PW_P1: | ||
213 | case NRF24L01_AD_RX_PW_P2: | ||
214 | case NRF24L01_AD_RX_PW_P3: | ||
215 | case NRF24L01_AD_RX_PW_P4: | ||
216 | case NRF24L01_AD_RX_PW_P5: | ||
217 | case NRF24L01_AD_FIFO_STATUS: | ||
218 | case NRF24L01_AD_DYNPD: | ||
219 | case NRF24L01_AD_FEATURE: | ||
220 | /* Not address registers cannot be written, the command is ignored.*/ | ||
221 | return 0; | ||
222 | case NRF24L01_AD_RX_ADDR_P0: | ||
223 | case NRF24L01_AD_RX_ADDR_P1: | ||
224 | case NRF24L01_AD_RX_ADDR_P2: | ||
225 | case NRF24L01_AD_RX_ADDR_P3: | ||
226 | case NRF24L01_AD_RX_ADDR_P4: | ||
227 | case NRF24L01_AD_RX_ADDR_P5: | ||
228 | case NRF24L01_AD_TX_ADDR: | ||
229 | spiSelect(spip); | ||
230 | spiExchange(spip, addlen + 1, txbuf, rxbuf); | ||
231 | spiUnselect(spip); | ||
232 | return rxbuf[0]; | ||
233 | } | ||
234 | } | ||
235 | /** | ||
236 | * @brief Reads RX payload from FIFO. | ||
237 | * | ||
238 | * @note Payload is deleted from FIFO after it is read. Used in RX mode. | ||
239 | * @pre The SPI interface must be initialized and the driver started. | ||
240 | * | ||
241 | * @param[in] spip pointer to the SPI interface | ||
242 | * @param[in] paylen payload length | ||
243 | * @param[in] rxbuf pointer to a buffer | ||
244 | * | ||
245 | * @return the status register value | ||
246 | */ | ||
247 | NRF24L01_status_t nrf24l01GetRxPl(SPIDriver *spip, uint8_t paylen, | ||
248 | uint8_t* rxbuf) { | ||
249 | |||
250 | uint8_t txbuf = NRF24L01_CMD_R_RX_PAYLOAD; | ||
251 | uint8_t status; | ||
252 | if(paylen > NRF24L01_MAX_PL_LENGHT) { | ||
253 | return 0; | ||
254 | } | ||
255 | spiSelect(spip); | ||
256 | spiExchange(spip, 1, &txbuf, &status); | ||
257 | spiReceive(spip, paylen, rxbuf); | ||
258 | spiUnselect(spip); | ||
259 | return status; | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * @brief Writes TX payload on FIFO. | ||
264 | * | ||
265 | * @note Used in TX mode. | ||
266 | * @pre The SPI interface must be initialized and the driver started. | ||
267 | * | ||
268 | * @param[in] spip pointer to the SPI interface | ||
269 | * @param[in] paylen payload length | ||
270 | * @param[in] rxbuf pointer to a buffer | ||
271 | * | ||
272 | * @return the status register value | ||
273 | */ | ||
274 | NRF24L01_status_t nrf24l01WriteTxPl(SPIDriver *spip, uint8_t paylen, | ||
275 | uint8_t* txbuf) { | ||
276 | |||
277 | uint8_t cmd = NRF24L01_CMD_W_TX_PAYLOAD; | ||
278 | uint8_t status; | ||
279 | if(paylen > NRF24L01_MAX_PL_LENGHT) { | ||
280 | return 0; | ||
281 | } | ||
282 | spiSelect(spip); | ||
283 | spiExchange(spip, 1, &cmd, &status); | ||
284 | spiSend(spip, paylen, txbuf); | ||
285 | spiUnselect(spip); | ||
286 | return status; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * @brief Flush TX FIFO. | ||
291 | * | ||
292 | * @note Used in TX mode. | ||
293 | * @pre The SPI interface must be initialized and the driver started. | ||
294 | * | ||
295 | * @param[in] spip pointer to the SPI interface | ||
296 | * | ||
297 | * @return the status register value | ||
298 | */ | ||
299 | NRF24L01_status_t nrf24l01FlushTx(SPIDriver *spip) { | ||
300 | |||
301 | uint8_t txbuf = NRF24L01_CMD_FLUSH_TX; | ||
302 | uint8_t status; | ||
303 | spiSelect(spip); | ||
304 | spiExchange(spip, 1, &txbuf, &status); | ||
305 | spiUnselect(spip); | ||
306 | return status; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * @brief Flush RX FIFO. | ||
311 | * | ||
312 | * @note Used in RX mode. Should not be executed during transmission of | ||
313 | acknowledge, that is, acknowledge package will not be completed. | ||
314 | * @pre The SPI interface must be initialized and the driver started. | ||
315 | * | ||
316 | * @param[in] spip pointer to the SPI interface | ||
317 | * | ||
318 | * @return the status register value | ||
319 | */ | ||
320 | NRF24L01_status_t nrf24l01FlushRx(SPIDriver *spip) { | ||
321 | |||
322 | uint8_t txbuf = NRF24L01_CMD_FLUSH_RX; | ||
323 | uint8_t status; | ||
324 | spiSelect(spip); | ||
325 | spiExchange(spip, 1, &txbuf, &status); | ||
326 | spiUnselect(spip); | ||
327 | return status; | ||
328 | } | ||
329 | |||
330 | #if NRF24L01_USE_FEATURE || defined(__DOXYGEN__) | ||
331 | /** | ||
332 | * @brief Activates the following features: | ||
333 | * R_RX_PL_WID -> (In order to enable DPL the EN_DPL bit in the | ||
334 | * FEATURE register must be set) | ||
335 | * W_ACK_PAYLOAD -> (In order to enable PL with ACK the EN_ACK_PAY | ||
336 | * bit in the FEATURE register must be set) | ||
337 | * W_TX_PAYLOAD_NOACK -> (In order to send a PL without ACK | ||
338 | * the EN_DYN_ACK it in the FEATURE register | ||
339 | * must be set) | ||
340 | * | ||
341 | * @note A new ACTIVATE command with the same data deactivates them again. | ||
342 | * This is executable in power down or stand by modes only. | ||
343 | * @pre The SPI interface must be initialized and the driver started. | ||
344 | * | ||
345 | * @param[in] spip pointer to the SPI interface | ||
346 | * | ||
347 | * @return the status register value | ||
348 | */ | ||
349 | NRF24L01_status_t nrf24l01Activate(SPIDriver *spip) { | ||
350 | |||
351 | uint8_t txbuf[2] = {NRF24L01_CMD_FLUSH_RX, ACTIVATE}; | ||
352 | uint8_t rxbuf[2]; | ||
353 | spiSelect(spip); | ||
354 | spiExchange(spip, 2, txbuf, rxbuf); | ||
355 | spiUnselect(spip); | ||
356 | return rxbuf[0]; | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * @brief Reads RX payload lenght for the top R_RX_PAYLOAD | ||
361 | * in the RX FIFO when Dynamic Payload Length is activated. | ||
362 | * | ||
363 | * @note R_RX_PL_WID must be set and activated. | ||
364 | * @pre The SPI interface must be initialized and the driver started. | ||
365 | * | ||
366 | * @param[in] spip pointer to the SPI interface | ||
367 | * @param[in] ppaylen pointer to the payload length variable | ||
368 | * | ||
369 | * @return the status register value | ||
370 | */ | ||
371 | NRF24L01_status_t nrf24l01ReadRxPlWid(SPIDriver *spip, uint8_t *ppaylen) { | ||
372 | |||
373 | uint8_t txbuf[2] = {NRF24L01_CMD_R_RX_PL_WID, 0xFF}; | ||
374 | uint8_t rxbuf[2]; | ||
375 | spiSelect(spip); | ||
376 | spiExchange(spip, 2, txbuf, rxbuf); | ||
377 | spiUnselect(spip); | ||
378 | *ppaylen = rxbuf[1]; | ||
379 | return rxbuf[0]; | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * @brief Writes TX payload associateted to ACK. | ||
384 | * | ||
385 | * @note Used in RX mode. Write Payload to be transmitted together with | ||
386 | * ACK packet on PIPE PPP. (PPP valid in the range from 000 to 101). | ||
387 | * @note EN_ACK_PAY must be set and activated. | ||
388 | * @pre The SPI interface must be initialized and the driver started. | ||
389 | * | ||
390 | * @param[in] spip pointer to the SPI interface | ||
391 | * @param[in] paylen payload length | ||
392 | * @param[in] rxbuf pointer to a buffer | ||
393 | * | ||
394 | * @return the status register value | ||
395 | */ | ||
396 | NRF24L01_status_t nrf24l01WriteAckPl(SPIDriver *spip, uint8_t ppp, uint8_t paylen, | ||
397 | uint8_t* payload){ | ||
398 | |||
399 | payload[0] = NRF24L01_CMD_W_ACK_PAYLOAD | NRF24L01_MAX_PPP; | ||
400 | uint8_t status; | ||
401 | if((paylen > NRF24L01_MAX_PL_LENGHT) || (ppp > NRF24L01_MAX_PPP)) { | ||
402 | return 0; | ||
403 | } | ||
404 | spiSelect(spip); | ||
405 | spiExchange(spip, 1, payload, &status); | ||
406 | spiSend(spip, paylen, payload); | ||
407 | spiUnselect(spip); | ||
408 | return status; | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * @brief Writes next TX payload without ACK. | ||
413 | * | ||
414 | * @note Used in TX mode. | ||
415 | * @note EN_DYN_ACK must be set and activated. | ||
416 | * @pre The SPI interface must be initialized and the driver started. | ||
417 | * | ||
418 | * @param[in] spip pointer to the SPI interface | ||
419 | * @param[in] paylen payload length | ||
420 | * @param[in] rxbuf pointer to a buffer | ||
421 | * | ||
422 | * @return the status register value | ||
423 | */ | ||
424 | NRF24L01_status_t nrf24l01WriteTxPlNoAck(SPIDriver *spip, uint8_t paylen, | ||
425 | uint8_t* txbuf) { | ||
426 | |||
427 | txbuf[0] = NRF24L01_CMD_W_TX_PAYLOAD_NOACK; | ||
428 | uint8_t status; | ||
429 | if(paylen > NRF24L01_MAX_PL_LENGHT) { | ||
430 | return 0; | ||
431 | } | ||
432 | spiSelect(spip); | ||
433 | spiExchange(spip, 1, txbuf, &status); | ||
434 | spiSend(spip, paylen, txbuf); | ||
435 | spiUnselect(spip); | ||
436 | return status; | ||
437 | } | ||
438 | #endif /* NRF24L01_USE_FEATURE */ | ||
439 | |||
440 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.h b/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.h new file mode 100644 index 000000000..86ba1279d --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.h | |||
@@ -0,0 +1,575 @@ | |||
1 | /* | ||
2 | Pretty LAYer for ChibiOS/RT - Copyright (C) 2015 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of PLAY for ChibiOS/RT. | ||
5 | |||
6 | PLAY is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | PLAY is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | Special thanks to Giovanni Di Sirio for teachings, his moral support and | ||
22 | friendship. Note that some or every piece of this file could be part of | ||
23 | the ChibiOS project that is intellectual property of Giovanni Di Sirio. | ||
24 | Please refer to ChibiOS/RT license before use this file. | ||
25 | |||
26 | For suggestion or Bug report - [email protected] | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * @file nrf24l01.h | ||
31 | * @brief NRF24L01 Radio frequency module interface module header. | ||
32 | * | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef _NRF24L01_H_ | ||
37 | #define _NRF24L01_H_ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Driver constants. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | #define NRF24L01_MAX_ADD_LENGHT ((uint8_t) 5) | ||
44 | #define NRF24L01_MAX_PL_LENGHT ((uint8_t) 32) | ||
45 | #define NRF24L01_MAX_PPP ((uint8_t) 5) | ||
46 | |||
47 | /** | ||
48 | * @brief Enables Advanced Features. | ||
49 | */ | ||
50 | #if !defined(NRF24L01_USE_FEATURE) || defined(__DOXYGEN__) | ||
51 | #define NRF24L01_USE_FEATURE TRUE | ||
52 | #endif | ||
53 | |||
54 | /** | ||
55 | * @name NRF24L01 register names | ||
56 | * @{ | ||
57 | */ | ||
58 | /******************************************************************************/ | ||
59 | /* */ | ||
60 | /* NRF24L01 RF Transceiver */ | ||
61 | /* */ | ||
62 | /******************************************************************************/ | ||
63 | /****************** Bit definition for SPI communication ********************/ | ||
64 | #define NRF24L01_DI ((uint8_t)0xFF) /*!< DI[7:0] Data input */ | ||
65 | #define NRF24L01_DI_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
66 | #define NRF24L01_DI_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
67 | #define NRF24L01_DI_2 ((uint8_t)0x04) /*!< bit 2 */ | ||
68 | #define NRF24L01_DI_3 ((uint8_t)0x08) /*!< bit 3 */ | ||
69 | #define NRF24L01_DI_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
70 | #define NRF24L01_DI_5 ((uint8_t)0x20) /*!< bit 5 */ | ||
71 | #define NRF24L01_DI_6 ((uint8_t)0x40) /*!< bit 6 */ | ||
72 | #define NRF24L01_DI_7 ((uint8_t)0x80) /*!< bit 7 */ | ||
73 | |||
74 | #define NRF24L01_AD ((uint8_t)0x1F) /*!< AD[4:0] Address Data */ | ||
75 | #define NRF24L01_AD_0 ((uint8_t)0x01) /*!< bit 0 */ | ||
76 | #define NRF24L01_AD_1 ((uint8_t)0x02) /*!< bit 1 */ | ||
77 | #define NRF24L01_AD_2 ((uint8_t)0x04) /*!< bit 2 */ | ||
78 | #define NRF24L01_AD_3 ((uint8_t)0x08) /*!< bit 3 */ | ||
79 | #define NRF24L01_AD_4 ((uint8_t)0x10) /*!< bit 4 */ | ||
80 | |||
81 | #define NRF24L01_CMD_READ ((uint8_t)0x00) /*!< Read command */ | ||
82 | #define NRF24L01_CMD_WRITE ((uint8_t)0x20) /*!< Write command */ | ||
83 | #define NRF24L01_CMD_R_RX_PAYLOAD ((uint8_t)0x61) /*!< Read RX-payload*/ | ||
84 | #define NRF24L01_CMD_W_TX_PAYLOAD ((uint8_t)0xA0) /*!< Write TX-payload */ | ||
85 | #define NRF24L01_CMD_FLUSH_TX ((uint8_t)0xE1) /*!< Flush TX FIFO */ | ||
86 | #define NRF24L01_CMD_FLUSH_RX ((uint8_t)0xE2) /*!< Flush RX FIFO */ | ||
87 | #define NRF24L01_CMD_REUSE_TX_PL ((uint8_t)0xE3) /*!< Used for a PTX device */ | ||
88 | #define NRF24L01_CMD_ACTIVATE ((uint8_t)0x50) /*!< Activate command */ | ||
89 | #define NRF24L01_CMD_R_RX_PL_WID ((uint8_t)0x60) /*!< Read RX-payload width */ | ||
90 | #define NRF24L01_CMD_W_ACK_PAYLOAD ((uint8_t)0xA8) /*!< Write Payload for ACK */ | ||
91 | #define NRF24L01_CMD_W_TX_PAYLOAD_NOACK ((uint8_t)0xB0) /*!< Disables AUTOACK*/ | ||
92 | #define NRF24L01_CMD_NOP ((uint8_t)0xFF) /*!< No Operation */ | ||
93 | |||
94 | /****************** Bit definition for Registers Addresses *******************/ | ||
95 | #define NRF24L01_AD_CONFIG ((uint8_t)0x00) /*!< Configuration Register */ | ||
96 | #define NRF24L01_AD_EN_AA ((uint8_t)0x01) /*!< Enable �Auto Acknowledgment� */ | ||
97 | #define NRF24L01_AD_EN_RXADDR ((uint8_t)0x02) /*!< Enabled RX Addresses */ | ||
98 | #define NRF24L01_AD_SETUP_AW ((uint8_t)0x03) /*!< Setup of Address Widths */ | ||
99 | #define NRF24L01_AD_SETUP_RETR ((uint8_t)0x04) /*!< Setup of Automatic Retransmission */ | ||
100 | #define NRF24L01_AD_RF_CH ((uint8_t)0x05) /*!< RF Channel */ | ||
101 | #define NRF24L01_AD_RF_SETUP ((uint8_t)0x06) /*!< RF Setup Register */ | ||
102 | #define NRF24L01_AD_STATUS ((uint8_t)0x07) /*!< Status Register */ | ||
103 | #define NRF24L01_AD_OBSERVE_TX ((uint8_t)0x08) /*!< Transmit observe register */ | ||
104 | #define NRF24L01_AD_CD ((uint8_t)0x09) /*!< CD */ | ||
105 | #define NRF24L01_AD_RX_ADDR_P0 ((uint8_t)0x0A) /*!< Receive address data pipe 0 */ | ||
106 | #define NRF24L01_AD_RX_ADDR_P1 ((uint8_t)0x0B) /*!< Receive address data pipe 1 */ | ||
107 | #define NRF24L01_AD_RX_ADDR_P2 ((uint8_t)0x0C) /*!< Receive address data pipe 2 */ | ||
108 | #define NRF24L01_AD_RX_ADDR_P3 ((uint8_t)0x0D) /*!< Receive address data pipe 3 */ | ||
109 | #define NRF24L01_AD_RX_ADDR_P4 ((uint8_t)0x0E) /*!< Receive address data pipe 4 */ | ||
110 | #define NRF24L01_AD_RX_ADDR_P5 ((uint8_t)0x0F) /*!< Receive address data pipe 5 */ | ||
111 | #define NRF24L01_AD_TX_ADDR ((uint8_t)0x10) /*!< Transmit address */ | ||
112 | #define NRF24L01_AD_RX_PW_P0 ((uint8_t)0x11) /*!< Number of bytes in RX payload in data pipe 0 */ | ||
113 | #define NRF24L01_AD_RX_PW_P1 ((uint8_t)0x12) /*!< Number of bytes in RX payload in data pipe 1 */ | ||
114 | #define NRF24L01_AD_RX_PW_P2 ((uint8_t)0x13) /*!< Number of bytes in RX payload in data pipe 2 */ | ||
115 | #define NRF24L01_AD_RX_PW_P3 ((uint8_t)0x14) /*!< Number of bytes in RX payload in data pipe 3 */ | ||
116 | #define NRF24L01_AD_RX_PW_P4 ((uint8_t)0x15) /*!< Number of bytes in RX payload in data pipe 4 */ | ||
117 | #define NRF24L01_AD_RX_PW_P5 ((uint8_t)0x16) /*!< Number of bytes in RX payload in data pipe 5 */ | ||
118 | #define NRF24L01_AD_FIFO_STATUS ((uint8_t)0x17) /*!< FIFO Status Register */ | ||
119 | #define NRF24L01_AD_DYNPD ((uint8_t)0x1C) /*!< Enable dynamic payload length */ | ||
120 | #define NRF24L01_AD_FEATURE ((uint8_t)0x1D) /*!< Feature Register */ | ||
121 | |||
122 | /*************** Bit definition for Registers Configuration *****************/ | ||
123 | #define NRF24L01_DI_CONFIG ((uint8_t)0x7F) /*!< CONTROL REGISTER BIT MASK*/ | ||
124 | #define NRF24L01_DI_CONFIG_PRIM_RX ((uint8_t)0x01) /*!< RX/TX control - 1: PRX, 0: PTX */ | ||
125 | #define NRF24L01_DI_CONFIG_PWR_UP ((uint8_t)0x02) /*!< 1: POWER UP, 0:POWER DOWN */ | ||
126 | #define NRF24L01_DI_CONFIG_CRCO ((uint8_t)0x04) /*!< CRC encoding scheme - 1:two bytes, 0:one byte */ | ||
127 | #define NRF24L01_DI_CONFIG_EN_CRC ((uint8_t)0x08) /*!< Enable CRC. Forced high if one of the bits in the EN_AA is high */ | ||
128 | #define NRF24L01_DI_CONFIG_MASK_MAX_RT ((uint8_t)0x10) /*!< Mask interrupt caused by MAX_RT - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ | ||
129 | #define NRF24L01_DI_CONFIG_MASK_TX_DS ((uint8_t)0x20) /*!< Mask interrupt caused by TX_DS - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ | ||
130 | #define NRF24L01_DI_CONFIG_MASK_RX_DR ((uint8_t)0x40) /*!< Mask interrupt caused by RX_DR - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ | ||
131 | |||
132 | #define NRF24L01_DI_EN_AA ((uint8_t)0x3F) /*!< ENABLE AUTO ACKNOLEDGMENT REGISTER BIT MASK */ | ||
133 | #define NRF24L01_DI_EN_AA_P0 ((uint8_t)0x01) /*!< Enable auto acknowledgement data pipe 0 */ | ||
134 | #define NRF24L01_DI_EN_AA_P1 ((uint8_t)0x02) /*!< Enable auto acknowledgement data pipe 1 */ | ||
135 | #define NRF24L01_DI_EN_AA_P2 ((uint8_t)0x04) /*!< Enable auto acknowledgement data pipe 2 */ | ||
136 | #define NRF24L01_DI_EN_AA_P3 ((uint8_t)0x08) /*!< Enable auto acknowledgement data pipe 3 */ | ||
137 | #define NRF24L01_DI_EN_AA_P4 ((uint8_t)0x10) /*!< Enable auto acknowledgement data pipe 4 */ | ||
138 | #define NRF24L01_DI_EN_AA_P5 ((uint8_t)0x20) /*!< Enable auto acknowledgement data pipe 5 */ | ||
139 | |||
140 | #define NRF24L01_DI_EN_RXADDR ((uint8_t)0x3F) /*!< ENABLE RX ADDRESSES REGISTER BIT MASK */ | ||
141 | #define NRF24L01_DI_EN_RXADDR_P0 ((uint8_t)0x01) /*!< Enable data pipe 0 */ | ||
142 | #define NRF24L01_DI_EN_RXADDR_P1 ((uint8_t)0x02) /*!< Enable data pipe 1 */ | ||
143 | #define NRF24L01_DI_EN_RXADDR_P2 ((uint8_t)0x04) /*!< Enable data pipe 2 */ | ||
144 | #define NRF24L01_DI_EN_RXADDR_P3 ((uint8_t)0x08) /*!< Enable data pipe 3 */ | ||
145 | #define NRF24L01_DI_EN_RXADDR_P4 ((uint8_t)0x10) /*!< Enable data pipe 4 */ | ||
146 | #define NRF24L01_DI_EN_RXADDR_P5 ((uint8_t)0x20) /*!< Enable data pipe 5 */ | ||
147 | |||
148 | #define NRF24L01_DI_SETUP_AW ((uint8_t)0x03) /*!< SETUP OF ADDRESSES WIDTHS REGISTER BIT MASK */ | ||
149 | #define NRF24L01_DI_SETUP_AW_0 ((uint8_t)0x01) /*!< Addressed widths bit 0 */ | ||
150 | #define NRF24L01_DI_SETUP_AW_1 ((uint8_t)0x02) /*!< Addressed widths bit 1 */ | ||
151 | |||
152 | #define NRF24L01_DI_SETUP_RETR ((uint8_t)0xFF) /*!< SETUP OF AUTOMATIC RETRANSMISSION REGISTER BIT MASK */ | ||
153 | #define NRF24L01_DI_SETUP_RETR_ARC_0 ((uint8_t)0x01) /*!< Auto Retransmit Count bit 0 */ | ||
154 | #define NRF24L01_DI_SETUP_RETR_ARC_1 ((uint8_t)0x02) /*!< Auto Retransmit Count bit 1 */ | ||
155 | #define NRF24L01_DI_SETUP_RETR_ARC_2 ((uint8_t)0x04) /*!< Auto Retransmit Count bit 2 */ | ||
156 | #define NRF24L01_DI_SETUP_RETR_ARC_3 ((uint8_t)0x08) /*!< Auto Retransmit Count bit 3 */ | ||
157 | #define NRF24L01_DI_SETUP_RETR_ARD_0 ((uint8_t)0x10) /*!< Auto Retransmit Delay bit 0 */ | ||
158 | #define NRF24L01_DI_SETUP_RETR_ARD_1 ((uint8_t)0x20) /*!< Auto Retransmit Delay bit 1 */ | ||
159 | #define NRF24L01_DI_SETUP_RETR_ARD_2 ((uint8_t)0x40) /*!< Auto Retransmit Delay bit 2 */ | ||
160 | #define NRF24L01_DI_SETUP_RETR_ARD_3 ((uint8_t)0x80) /*!< Auto Retransmit Delay bit 3 */ | ||
161 | |||
162 | |||
163 | #define NRF24L01_DI_RF_CH ((uint8_t)0x7F) /*!< RF CHANNEL REGISTER BIT MASK */ | ||
164 | #define NRF24L01_DI_RF_CH_0 ((uint8_t)0x01) /*!< RF channel bit 0 */ | ||
165 | #define NRF24L01_DI_RF_CH_1 ((uint8_t)0x02) /*!< RF channel bit 1 */ | ||
166 | #define NRF24L01_DI_RF_CH_2 ((uint8_t)0x04) /*!< RF channel bit 2 */ | ||
167 | #define NRF24L01_DI_RF_CH_3 ((uint8_t)0x08) /*!< RF channel bit 3 */ | ||
168 | #define NRF24L01_DI_RF_CH_4 ((uint8_t)0x10) /*!< RF channel bit 4 */ | ||
169 | #define NRF24L01_DI_RF_CH_5 ((uint8_t)0x20) /*!< RF channel bit 5 */ | ||
170 | #define NRF24L01_DI_RF_CH_6 ((uint8_t)0x40) /*!< RF channel bit 6 */ | ||
171 | |||
172 | |||
173 | #define NRF24L01_DI_RF_SETUP ((uint8_t)0x1F) /*!< RF SETUP REGISTER BIT MASK */ | ||
174 | #define NRF24L01_DI_RF_SETUP_LNA_HCURR ((uint8_t)0x01) /*!< Setup LNA gain */ | ||
175 | #define NRF24L01_DI_RF_SETUP_RF_PWR_0 ((uint8_t)0x02) /*!< RF output power bit 0 */ | ||
176 | #define NRF24L01_DI_RF_SETUP_RF_PWR_1 ((uint8_t)0x04) /*!< RF output power bit 1 */ | ||
177 | #define NRF24L01_DI_RF_SETUP_RF_DR ((uint8_t)0x08) /*!< Air Data rate - 0: 1Mbps, 1: 2Mbps */ | ||
178 | #define NRF24L01_DI_RF_SETUP_PLL_LOCK ((uint8_t)0x10) /*!< Force PLL lock signal */ | ||
179 | |||
180 | #define NRF24L01_DI_STATUS ((uint8_t)0x7F) /*!< STATUS REGISTER BIT MASK */ | ||
181 | #define NRF24L01_DI_STATUS_TX_FULL ((uint8_t)0x01) /*!< TX FIFO full flag - 0: Available locations, 1: Full */ | ||
182 | #define NRF24L01_DI_STATUS_RX_P_NO_0 ((uint8_t)0x02) /*!< RX payload number bit 0 */ | ||
183 | #define NRF24L01_DI_STATUS_RX_P_NO_1 ((uint8_t)0x04) /*!< RX payload number bit 1 */ | ||
184 | #define NRF24L01_DI_STATUS_RX_P_NO_2 ((uint8_t)0x08) /*!< RX payload number bit 2 */ | ||
185 | #define NRF24L01_DI_STATUS_MAX_RT ((uint8_t)0x10) /*!< Maximum number of TX retransmits interrupt */ | ||
186 | #define NRF24L01_DI_STATUS_TX_DS ((uint8_t)0x20) /*!< Data Sent TX FIFO interrupt */ | ||
187 | #define NRF24L01_DI_STATUS_RX_DR ((uint8_t)0x40) /*!< Data Ready RX FIFO interrupt */ | ||
188 | |||
189 | #define NRF24L01_DI_OBSERVE_TX ((uint8_t)0xFF) /*!< TRANSMIT OBSERVE REGISTER BIT MASK */ | ||
190 | #define NRF24L01_DI_ARC_CNT_0 ((uint8_t)0x01) /*!< Count retransmitted packets bit 0 */ | ||
191 | #define NRF24L01_DI_ARC_CNT_1 ((uint8_t)0x02) /*!< Count retransmitted packets bit 1 */ | ||
192 | #define NRF24L01_DI_ARC_CNT_2 ((uint8_t)0x04) /*!< Count retransmitted packets bit 2 */ | ||
193 | #define NRF24L01_DI_ARC_CNT_3 ((uint8_t)0x08) /*!< Count retransmitted packets bit 3 */ | ||
194 | #define NRF24L01_DI_PLOS_CNT_0 ((uint8_t)0x10) /*!< Count lost packets bit 0 */ | ||
195 | #define NRF24L01_DI_PLOS_CNT_1 ((uint8_t)0x20) /*!< Count lost packets bit 1 */ | ||
196 | #define NRF24L01_DI_PLOS_CNT_2 ((uint8_t)0x40) /*!< Count lost packets bit 2 */ | ||
197 | #define NRF24L01_DI_PLOS_CNT_3 ((uint8_t)0x80) /*!< Count lost packets bit 3 */ | ||
198 | |||
199 | #define NRF24L01_DI_CD ((uint8_t)0x01) /*!< REGISTER BIT MASK */ | ||
200 | #define NRF24L01_DI_CARRIER_DETECT ((uint8_t)0x01) /*!< Carrier detect */ | ||
201 | |||
202 | #define NRF24L01_DI_RX_PW_P0 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 0 REGISTER BIT MASK */ | ||
203 | #define NRF24L01_DI_RX_PW_P0_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
204 | #define NRF24L01_DI_RX_PW_P0_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
205 | #define NRF24L01_DI_RX_PW_P0_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
206 | #define NRF24L01_DI_RX_PW_P0_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
207 | #define NRF24L01_DI_RX_PW_P0_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
208 | #define NRF24L01_DI_RX_PW_P0_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
209 | |||
210 | #define NRF24L01_DI_RX_PW_P1 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 1 REGISTER BIT MASK */ | ||
211 | #define NRF24L01_DI_RX_PW_P1_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
212 | #define NRF24L01_DI_RX_PW_P1_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
213 | #define NRF24L01_DI_RX_PW_P1_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
214 | #define NRF24L01_DI_RX_PW_P1_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
215 | #define NRF24L01_DI_RX_PW_P1_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
216 | #define NRF24L01_DI_RX_PW_P1_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
217 | |||
218 | #define NRF24L01_DI_RX_PW_P2 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 2 REGISTER BIT MASK */ | ||
219 | #define NRF24L01_DI_RX_PW_P2_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
220 | #define NRF24L01_DI_RX_PW_P2_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
221 | #define NRF24L01_DI_RX_PW_P2_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
222 | #define NRF24L01_DI_RX_PW_P2_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
223 | #define NRF24L01_DI_RX_PW_P2_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
224 | #define NRF24L01_DI_RX_PW_P2_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
225 | |||
226 | #define NRF24L01_DI_RX_PW_P3 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 3 REGISTER BIT MASK */ | ||
227 | #define NRF24L01_DI_RX_PW_P3_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
228 | #define NRF24L01_DI_RX_PW_P3_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
229 | #define NRF24L01_DI_RX_PW_P3_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
230 | #define NRF24L01_DI_RX_PW_P3_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
231 | #define NRF24L01_DI_RX_PW_P3_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
232 | #define NRF24L01_DI_RX_PW_P3_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
233 | |||
234 | #define NRF24L01_DI_RX_PW_P4 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 4 REGISTER BIT MASK */ | ||
235 | #define NRF24L01_DI_RX_PW_P4_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
236 | #define NRF24L01_DI_RX_PW_P4_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
237 | #define NRF24L01_DI_RX_PW_P4_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
238 | #define NRF24L01_DI_RX_PW_P4_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
239 | #define NRF24L01_DI_RX_PW_P4_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
240 | #define NRF24L01_DI_RX_PW_P4_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
241 | |||
242 | #define NRF24L01_DI_RX_PW_P5 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 5 REGISTER BIT MASK */ | ||
243 | #define NRF24L01_DI_RX_PW_P5_0 ((uint8_t)0x01) /*!< Bit 0 */ | ||
244 | #define NRF24L01_DI_RX_PW_P5_1 ((uint8_t)0x02) /*!< Bit 1 */ | ||
245 | #define NRF24L01_DI_RX_PW_P5_2 ((uint8_t)0x04) /*!< Bit 2 */ | ||
246 | #define NRF24L01_DI_RX_PW_P5_3 ((uint8_t)0x08) /*!< Bit 3 */ | ||
247 | #define NRF24L01_DI_RX_PW_P5_4 ((uint8_t)0x10) /*!< Bit 4 */ | ||
248 | #define NRF24L01_DI_RX_PW_P5_5 ((uint8_t)0x20) /*!< Bit 5 */ | ||
249 | |||
250 | #define NRF24L01_DI_FIFO_STATUS ((uint8_t)0x73) /*!< FIFO STATUS REGISTER BIT MASK*/ | ||
251 | #define NRF24L01_DI_FIFO_STATUS_RX_EMPTY ((uint8_t)0x01) /*!< RX FIFO empty flag - 0:Data in RX FIFO, 1:RX FIFO empty */ | ||
252 | #define NRF24L01_DI_FIFO_STATUS_RX_FULL ((uint8_t)0x02) /*!< RX FIFO full flag - 0:Available locations in RX FIFO, 1:RX FIFO empty */ | ||
253 | #define NRF24L01_DI_FIFO_STATUS_TX_EMPTY ((uint8_t)0x10) /*!< TX FIFO empty flag - 0:Data in TX FIFO, 1:TX FIFO empty */ | ||
254 | #define NRF24L01_DI_FIFO_STATUS_TX_FULL ((uint8_t)0x20) /*!< TX FIFO full flag - 0:Available locations in TX FIFO, 1:TX FIFO empty */ | ||
255 | #define NRF24L01_DI_FIFO_STATUS_TX_REUSE ((uint8_t)0x40) /*!< Reuse last transmitted data packet if set high */ | ||
256 | |||
257 | #define NRF24L01_DI_DYNPD ((uint8_t)0x3F) /*!< ENABLE DYNAMIC PAYLOAD LENGHT REGISTER BIT MASK */ | ||
258 | #define NRF24L01_DI_DYNPD_DPL_P0 ((uint8_t)0x01) /*!< Enable dyn. payload length data pipe 0 */ | ||
259 | #define NRF24L01_DI_DYNPD_DPL_P1 ((uint8_t)0x02) /*!< Enable dyn. payload length data pipe 1 */ | ||
260 | #define NRF24L01_DI_DYNPD_DPL_P2 ((uint8_t)0x04) /*!< Enable dyn. payload length data pipe 2 */ | ||
261 | #define NRF24L01_DI_DYNPD_DPL_P3 ((uint8_t)0x08) /*!< Enable dyn. payload length data pipe 3 */ | ||
262 | #define NRF24L01_DI_DYNPD_DPL_P4 ((uint8_t)0x10) /*!< Enable dyn. payload length data pipe 4 */ | ||
263 | #define NRF24L01_DI_DYNPD_DPL_P5 ((uint8_t)0x20) /*!< Enable dyn. payload length data pipe 5 */ | ||
264 | |||
265 | #define NRF24L01_DI_FEATURE ((uint8_t)0x07) /*!< FEATURE REGISTER REGISTER BIT MASK */ | ||
266 | #define NRF24L01_DI_FEATURE_EN_DYN_ACK ((uint8_t)0x01) /*!< Enables the W_TX_PAYLOAD_NOACK command */ | ||
267 | #define NRF24L01_DI_FEATURE_EN_ACK_PAY ((uint8_t)0x02) /*!< Enables Payload with ACK */ | ||
268 | #define NRF24L01_DI_FEATURE_EN_DPL ((uint8_t)0x04) /*!< Enables Dynamic Payload Length */ | ||
269 | /** @} */ | ||
270 | |||
271 | /*===========================================================================*/ | ||
272 | /* Driver pre-compile time settings. */ | ||
273 | /*===========================================================================*/ | ||
274 | |||
275 | /*===========================================================================*/ | ||
276 | /* Derived constants and error checks. */ | ||
277 | /*===========================================================================*/ | ||
278 | |||
279 | #if !(HAL_USE_SPI) | ||
280 | #error "RF_NRF24L01 requires HAL_USE_SPI." | ||
281 | #endif | ||
282 | |||
283 | #if !(HAL_USE_EXT) | ||
284 | #error "RF_NRF24L01 requires HAL_USE_EXT." | ||
285 | #endif | ||
286 | /*===========================================================================*/ | ||
287 | /* Driver data structures and types. */ | ||
288 | /*===========================================================================*/ | ||
289 | |||
290 | /** | ||
291 | * @name RF Transceiver data structures and types | ||
292 | * @{ | ||
293 | */ | ||
294 | |||
295 | /** | ||
296 | * @brief RF Transceiver RX/TX Address field width | ||
297 | */ | ||
298 | typedef enum { | ||
299 | |||
300 | NRF24L01_AW_3_bytes = 0x01, /*!< 3 bytes width */ | ||
301 | NRF24L01_AW_4_bytes = 0x02, /*!< 4 bytes width */ | ||
302 | NRF24L01_AW_5_bytes = 0x03 /*!< 5 bytes width */ | ||
303 | } NRF24L01_AW_t; | ||
304 | |||
305 | /** | ||
306 | * @brief RF Transceiver Auto Retransmit Delay | ||
307 | */ | ||
308 | typedef enum { | ||
309 | |||
310 | NRF24L01_ARD_250us = 0x00, /*!< Wait 250us */ | ||
311 | NRF24L01_ARD_500us = 0x10, /*!< Wait 500us */ | ||
312 | NRF24L01_ARD_750us = 0x20, /*!< Wait 750us */ | ||
313 | NRF24L01_ARD_1000us = 0x30, /*!< Wait 1000us */ | ||
314 | NRF24L01_ARD_1250us = 0x40, /*!< Wait 1250us */ | ||
315 | NRF24L01_ARD_1500us = 0x50, /*!< Wait 1500us */ | ||
316 | NRF24L01_ARD_1750us = 0x60, /*!< Wait 1750us */ | ||
317 | NRF24L01_ARD_2000us = 0x70, /*!< Wait 2000us */ | ||
318 | NRF24L01_ARD_2250us = 0x80, /*!< Wait 2250us */ | ||
319 | NRF24L01_ARD_2500us = 0x90, /*!< Wait 2500us */ | ||
320 | NRF24L01_ARD_2750us = 0xA0, /*!< Wait 2750us */ | ||
321 | NRF24L01_ARD_3000us = 0xB0, /*!< Wait 3000us */ | ||
322 | NRF24L01_ARD_3250us = 0xC0, /*!< Wait 3250us */ | ||
323 | NRF24L01_ARD_3500us = 0xD0, /*!< Wait 3500us */ | ||
324 | NRF24L01_ARD_3750us = 0xE0, /*!< Wait 3750us */ | ||
325 | NRF24L01_ARD_4000us = 0xF0 /*!< Wait 4000us */ | ||
326 | } NRF24L01_ARD_t; | ||
327 | |||
328 | /** | ||
329 | * @brief RF Transceiver Auto Retransmit Count | ||
330 | */ | ||
331 | typedef enum { | ||
332 | |||
333 | NRF24L01_ARC_disabled = 0x00, /*!< Re-Transmit disabled */ | ||
334 | NRF24L01_ARC_1_time = 0x01, /*!< Up to 1 Re-Transmit on fail of AA */ | ||
335 | NRF24L01_ARC_2_times = 0x02, /*!< Up to 2 Re-Transmit on fail of AA */ | ||
336 | NRF24L01_ARC_3_times = 0x03, /*!< Up to 3 Re-Transmit on fail of AA */ | ||
337 | NRF24L01_ARC_4_times = 0x04, /*!< Up to 4 Re-Transmit on fail of AA */ | ||
338 | NRF24L01_ARC_5_times = 0x05, /*!< Up to 5 Re-Transmit on fail of AAs */ | ||
339 | NRF24L01_ARC_6_times = 0x06, /*!< Up to 6 Re-Transmit on fail of AA */ | ||
340 | NRF24L01_ARC_7_times = 0x07, /*!< Up to 7 Re-Transmit on fail of AA */ | ||
341 | NRF24L01_ARC_8_times = 0x08, /*!< Up to 8 Re-Transmit on fail of AA */ | ||
342 | NRF24L01_ARC_9_times = 0x09, /*!< Up to 9 Re-Transmit on fail of AA */ | ||
343 | NRF24L01_ARC_10_times = 0x0A, /*!< Up to 10 Re-Transmit on fail of AA */ | ||
344 | NRF24L01_ARC_11_times = 0x0B, /*!< Up to 11 Re-Transmit on fail of AA */ | ||
345 | NRF24L01_ARC_12_times = 0x0C, /*!< Up to 12 Re-Transmit on fail of AA */ | ||
346 | NRF24L01_ARC_13_times = 0x0D, /*!< Up to 13 Re-Transmit on fail of AA */ | ||
347 | NRF24L01_ARC_14_times = 0x0E, /*!< Up to 14 Re-Transmit on fail of AA */ | ||
348 | NRF24L01_ARC_15_times = 0x0F /*!< Up to 15 Re-Transmit on fail of AA */ | ||
349 | } NRF24L01_ARC_t; | ||
350 | |||
351 | |||
352 | /** | ||
353 | * @brief RF Transceiver configuration typedef. | ||
354 | * | ||
355 | * @detail This will select frequency channel beetween 2,4 GHz and 2,525 GHz | ||
356 | * @detail according to formula 2,4GHz + RF_CH[MHz]. This value must be included | ||
357 | * @detail between 0 and 125. | ||
358 | */ | ||
359 | typedef uint8_t NRF24L01_RF_CH_t; | ||
360 | |||
361 | /** | ||
362 | * @brief RF Transceiver Air Data Rate | ||
363 | */ | ||
364 | typedef enum { | ||
365 | |||
366 | NRF24L01_ADR_1Mbps = 0x00, /*!< Air data rate 1 Mbps */ | ||
367 | NRF24L01_ADR_2Mbps = 0x08 /*!< Air data rate 2 Mbps */ | ||
368 | } NRF24L01_ADR_t; | ||
369 | |||
370 | /** | ||
371 | * @brief RF Transceiver Output Power | ||
372 | */ | ||
373 | typedef enum { | ||
374 | |||
375 | NRF24L01_PWR_0dBm = 0x06, /*!< RF output power 0 dBm */ | ||
376 | NRF24L01_PWR_neg6dBm = 0x04, /*!< RF output power -6 dBm */ | ||
377 | NRF24L01_PWR_neg12dBm = 0x02, /*!< RF output power -12 dBm */ | ||
378 | NRF24L01_PWR_neg18dBm = 0x00 /*!< RF output power -18 dBm */ | ||
379 | } NRF24L01_PWR_t; | ||
380 | |||
381 | /** | ||
382 | * @brief RF Transceiver Low Noise Amplifier | ||
383 | * | ||
384 | * @details Reduce current consumption in RX mode with 0.8 mA at cost of 1.5dB | ||
385 | * reduction in receiver sensitivity. | ||
386 | */ | ||
387 | typedef enum { | ||
388 | NRF24L01_LNA_enabled = 0x01, /*!< LNA_CURR enabled */ | ||
389 | NRF24L01_LNA_disabled = 0x00 /*!< LNA_CURR disabled */ | ||
390 | } NRF24L01_LNA_t; | ||
391 | |||
392 | /** | ||
393 | * @brief RF Transceiver Backward Compatibility | ||
394 | * | ||
395 | * @details This type specifies if trasmission must be compatible to receive | ||
396 | * from an nRF2401/nRF2402/nRF24E1/nRF24E. | ||
397 | */ | ||
398 | typedef bool_t NRF24L01_bckwrdcmp_t; | ||
399 | |||
400 | #if NRF24L01_USE_FEATURE || defined(__doxigen__) | ||
401 | /** | ||
402 | * @brief RF Transceiver Dynamic Payload enabler | ||
403 | * | ||
404 | * @details Enables Dynamic Payload Length | ||
405 | */ | ||
406 | typedef enum { | ||
407 | NRF24L01_DPL_enabled = 0x04, /*!< EN_DPL enabled */ | ||
408 | NRF24L01_DPL_disabled = 0x00 /*!< EN_DPL disabled */ | ||
409 | } NRF24L01_DPL_t; | ||
410 | |||
411 | /** | ||
412 | * @brief RF Transceiver Dynamic Acknowledge with Payload enabler | ||
413 | * | ||
414 | * @details Enables Payload with ACK | ||
415 | */ | ||
416 | typedef enum { | ||
417 | NRF24L01_ACK_PAY_enabled = 0x02, /*!< EN_ACK_PAY enabled */ | ||
418 | NRF24L01_ACK_PAY_disabled = 0x00 /*!< EN_ACK_PAY disabled */ | ||
419 | } NRF24L01_ACK_PAY_t; | ||
420 | |||
421 | /** | ||
422 | * @brief RF Transceiver Dynamic Acknowledge enabler | ||
423 | * | ||
424 | * @details Enables the W_TX_PAYLOAD_NOACK command | ||
425 | */ | ||
426 | typedef enum { | ||
427 | NRF24L01_DYN_ACK_enabled = 0x01, /*!< EN_DYN_ACK enabled */ | ||
428 | NRF24L01_DYN_ACK_disabled = 0x00 /*!< EN_DYN_ACK disabled */ | ||
429 | } NRF24L01_DYN_ACK_t; | ||
430 | #endif /* NRF24L01_USE_FEATURE */ | ||
431 | |||
432 | /** | ||
433 | * @brief RF Transceiver configuration structure. | ||
434 | */ | ||
435 | typedef struct { | ||
436 | |||
437 | /** | ||
438 | * @brief The chip enable line port. | ||
439 | */ | ||
440 | ioportid_t ceport; | ||
441 | /** | ||
442 | * @brief The chip enable line pad number. | ||
443 | */ | ||
444 | uint16_t cepad; | ||
445 | /** | ||
446 | * @brief The interrupt line port. | ||
447 | */ | ||
448 | ioportid_t irqport; | ||
449 | /** | ||
450 | * @brief The interrupt line pad number. | ||
451 | */ | ||
452 | uint16_t irqpad; | ||
453 | /** | ||
454 | * @brief Pointer to the SPI driver associated to this RF. | ||
455 | */ | ||
456 | SPIDriver *spip; | ||
457 | /** | ||
458 | * @brief Pointer to the SPI configuration . | ||
459 | */ | ||
460 | const SPIConfig *spicfg; | ||
461 | /** | ||
462 | * @brief Pointer to the EXT driver associated to this RF. | ||
463 | */ | ||
464 | EXTDriver *extp; | ||
465 | /** | ||
466 | * @brief EXT configuration. | ||
467 | */ | ||
468 | EXTConfig *extcfg; | ||
469 | /** | ||
470 | * @brief RF Transceiver auto retransmit count. | ||
471 | */ | ||
472 | NRF24L01_ARC_t auto_retr_count; | ||
473 | /** | ||
474 | * @brief RF Transceiver auto retransmit delay. | ||
475 | */ | ||
476 | NRF24L01_ARD_t auto_retr_delay; | ||
477 | /** | ||
478 | * @brief RF Transceiver address width. | ||
479 | */ | ||
480 | NRF24L01_AW_t address_width; | ||
481 | /** | ||
482 | * @brief RF Transceiver channel frequency. | ||
483 | */ | ||
484 | NRF24L01_RF_CH_t channel_freq; | ||
485 | /** | ||
486 | * @brief RF Transceiver air data rate. | ||
487 | */ | ||
488 | NRF24L01_ADR_t data_rate; | ||
489 | /** | ||
490 | * @brief RF Transceiver output power. | ||
491 | */ | ||
492 | NRF24L01_PWR_t out_pwr; | ||
493 | /** | ||
494 | * @brief RF Transceiver Low Noise Amplifier | ||
495 | */ | ||
496 | NRF24L01_LNA_t lna; | ||
497 | #if NRF24L01_USE_FEATURE || defined(__doxigen__) | ||
498 | /** | ||
499 | * @brief RF Transceiver Dynamic Payload enabler | ||
500 | */ | ||
501 | NRF24L01_DPL_t en_dpl; | ||
502 | |||
503 | /** | ||
504 | * @brief RF Transceiver Dynamic Acknowledge with Payload enabler | ||
505 | */ | ||
506 | NRF24L01_ACK_PAY_t en_ack_pay; | ||
507 | |||
508 | /** | ||
509 | * @brief RF Transceiver Dynamic Acknowledge enabler | ||
510 | */ | ||
511 | NRF24L01_DYN_ACK_t en_dyn_ack; | ||
512 | #endif /* NRF24L01_USE_FEATURE */ | ||
513 | } NRF24L01_Config; | ||
514 | |||
515 | /** | ||
516 | * @brief RF Transceiver status register value. | ||
517 | */ | ||
518 | typedef uint8_t NRF24L01_status_t; | ||
519 | /** @} */ | ||
520 | /*===========================================================================*/ | ||
521 | /* Driver macros. */ | ||
522 | /*===========================================================================*/ | ||
523 | |||
524 | /*===========================================================================*/ | ||
525 | /* External declarations. */ | ||
526 | /*===========================================================================*/ | ||
527 | |||
528 | /** | ||
529 | * @brief Flushes FIFOs and resets all Status flags. | ||
530 | * | ||
531 | * @pre The SPI interface must be initialized and the driver started. | ||
532 | * | ||
533 | * @param[in] spip pointer to the SPI interface | ||
534 | * | ||
535 | * @return the status register value | ||
536 | */ | ||
537 | #define nrf24l01Reset(spip) { \ | ||
538 | \ | ||
539 | nrf24l01WriteRegister(spip, NRF24L01_AD_STATUS, \ | ||
540 | NRF24L01_DI_STATUS_MAX_RT | \ | ||
541 | NRF24L01_DI_STATUS_RX_DR | \ | ||
542 | NRF24L01_DI_STATUS_TX_DS); \ | ||
543 | } | ||
544 | |||
545 | #ifdef __cplusplus | ||
546 | extern "C" { | ||
547 | #endif | ||
548 | NRF24L01_status_t nrf24l01GetStatus(SPIDriver *spip); | ||
549 | NRF24L01_status_t nrf24l01ReadRegister(SPIDriver *spip, uint8_t reg, | ||
550 | uint8_t* pvalue); | ||
551 | NRF24L01_status_t nrf24l01WriteRegister(SPIDriver *spip, uint8_t reg, | ||
552 | uint8_t value); | ||
553 | NRF24L01_status_t nrf24l01WriteAddress(SPIDriver *spip, uint8_t reg, | ||
554 | uint8_t *pvalue, uint8_t addlen); | ||
555 | NRF24L01_status_t nrf24l01GetRxPl(SPIDriver *spip, uint8_t paylen, | ||
556 | uint8_t* rxbuf); | ||
557 | NRF24L01_status_t nrf24l01WriteTxPl(SPIDriver *spip, uint8_t paylen, | ||
558 | uint8_t* txbuf); | ||
559 | NRF24L01_status_t nrf24l01FlushTx(SPIDriver *spip); | ||
560 | NRF24L01_status_t nrf24l01FlushRx(SPIDriver *spip); | ||
561 | #if NRF24L01_USE_FEATURE || defined(__DOXYGEN__) | ||
562 | NRF24L01_status_t nrf24l01Activate(SPIDriver *spip); | ||
563 | NRF24L01_status_t nrf24l01ReadRxPlWid(SPIDriver *spip, uint8_t* ppaylen); | ||
564 | NRF24L01_status_t nrf24l01WriteAckPl(SPIDriver *spip, uint8_t ppp, uint8_t paylen, | ||
565 | uint8_t* payload); | ||
566 | NRF24L01_status_t nrf24l01WriteTxPlNoAck(SPIDriver *spip, uint8_t paylen, | ||
567 | uint8_t* txbuf); | ||
568 | #endif /* NRF24L01_USE_FEATURE */ | ||
569 | #ifdef __cplusplus | ||
570 | } | ||
571 | #endif | ||
572 | |||
573 | #endif /* _NRF24L01_H_ */ | ||
574 | |||
575 | /** @} */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.c b/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.c new file mode 100644 index 000000000..9829935e7 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. | ||
2 | * | ||
3 | * The information contained herein is property of Nordic Semiconductor ASA. | ||
4 | * Terms and conditions of usage are described in detail in NORDIC | ||
5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. | ||
6 | * | ||
7 | * Licensees are granted free, non-transferable use of the information. NO | ||
8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from | ||
9 | * the file. | ||
10 | * | ||
11 | * Enhanced ShockBurst proprietary protocol to ChibiOS port | ||
12 | * | ||
13 | * ported on: 25/10/2018, by andru | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <stdint.h> | ||
18 | #include <string.h> | ||
19 | |||
20 | #include "ch.h" | ||
21 | #include "hal.h" | ||
22 | |||
23 | #include "nrf52_radio.h" | ||
24 | |||
25 | |||
26 | #define BIT_MASK_UINT_8(x) (0xFF >> (8 - (x))) | ||
27 | #define NRF52_PIPE_COUNT 9 | ||
28 | |||
29 | #define RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \ | ||
30 | RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk ) | ||
31 | |||
32 | // Constant parameters | ||
33 | #define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS (48) /**< 2MBit RX wait for ack timeout value. Smallest reliable value - 43 */ | ||
34 | #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS (64) /**< 1MBit RX wait for ack timeout value. Smallest reliable value - 59 */ | ||
35 | |||
36 | #define NRF52_ADDR_UPDATE_MASK_BASE0 (1 << 0) /*< Mask value to signal updating BASE0 radio address. */ | ||
37 | #define NRF52_ADDR_UPDATE_MASK_BASE1 (1 << 1) /*< Mask value to signal updating BASE1 radio address. */ | ||
38 | #define NRF52_ADDR_UPDATE_MASK_PREFIX (1 << 2) /*< Mask value to signal updating radio prefixes */ | ||
39 | |||
40 | #define NRF52_PID_RESET_VALUE 0xFF /**< Invalid PID value which is guaranteed to not collide with any valid PID value. */ | ||
41 | #define NRF52_PID_MAX 3 /**< Maximum value for PID. */ | ||
42 | #define NRF52_CRC_RESET_VALUE 0xFFFF /**< CRC reset value*/ | ||
43 | |||
44 | #ifndef NRF52_RADIO_USE_TIMER0 | ||
45 | #define NRF52_RADIO_USE_TIMER0 FALSE | ||
46 | #endif | ||
47 | |||
48 | #ifndef NRF52_RADIO_USE_TIMER1 | ||
49 | #define NRF52_RADIO_USE_TIMER1 FALSE | ||
50 | #endif | ||
51 | |||
52 | #ifndef NRF52_RADIO_USE_TIMER2 | ||
53 | #define NRF52_RADIO_USE_TIMER2 FALSE | ||
54 | #endif | ||
55 | |||
56 | #ifndef NRF52_RADIO_USE_TIMER3 | ||
57 | #define NRF52_RADIO_USE_TIMER3 FALSE | ||
58 | #endif | ||
59 | |||
60 | #ifndef NRF52_RADIO_USE_TIMER4 | ||
61 | #define NRF52_RADIO_USE_TIMER4 FALSE | ||
62 | #endif | ||
63 | |||
64 | #ifndef NRF52_RADIO_IRQ_PRIORITY | ||
65 | #define NRF52_RADIO_IRQ_PRIORITY 3 /**< RADIO interrupt priority. */ | ||
66 | #endif | ||
67 | |||
68 | #ifndef NRF52_RADIO_PPI_TIMER_START | ||
69 | #error "PPI channel NRF52_RADIO_PPI_TIMER_START need to be defined" | ||
70 | #endif | ||
71 | |||
72 | #ifndef NRF52_RADIO_PPI_TIMER_STOP | ||
73 | #error "PPI channel NRF52_RADIO_PPI_TIMER_STOP need to be defined" | ||
74 | #endif | ||
75 | |||
76 | #ifndef NRF52_RADIO_PPI_RX_TIMEOUT | ||
77 | #error "PPI channel NRF52_RADIO_PPI_RX_TIMEOUT need to be defined" | ||
78 | #endif | ||
79 | |||
80 | #ifndef NRF52_RADIO_PPI_TX_START | ||
81 | #error "PPI channel NRF52_RADIO_PPI_TX_START need to be defined" | ||
82 | #endif | ||
83 | |||
84 | #if (NRF52_RADIO_USE_TIMER0 == FALSE) && (NRF52_RADIO_USE_TIMER1 == FALSE) && \ | ||
85 | (NRF52_RADIO_USE_TIMER2 == FALSE) && (NRF52_RADIO_USE_TIMER3 == FALSE) && \ | ||
86 | (NRF52_RADIO_USE_TIMER4 == FALSE) | ||
87 | #error "At least one hardware TIMER must be defined" | ||
88 | #endif | ||
89 | |||
90 | #ifndef NRF52_RADIO_INTTHD_PRIORITY | ||
91 | #error "Interrupt handle thread priority need to be defined" | ||
92 | #endif | ||
93 | |||
94 | #ifndef NRF52_RADIO_EVTTHD_PRIORITY | ||
95 | #error "Event thread priority need to be defined" | ||
96 | #endif | ||
97 | |||
98 | #define VERIFY_PAYLOAD_LENGTH(p) \ | ||
99 | do \ | ||
100 | { \ | ||
101 | if(p->length == 0 || \ | ||
102 | p->length > NRF52_MAX_PAYLOAD_LENGTH || \ | ||
103 | (RFD1.config.protocol == NRF52_PROTOCOL_ESB && \ | ||
104 | p->length > RFD1.config.payload_length)) \ | ||
105 | { \ | ||
106 | return NRF52_ERROR_INVALID_LENGTH; \ | ||
107 | } \ | ||
108 | }while(0) | ||
109 | |||
110 | //Structure holding pipe info PID and CRC and ack payload. | ||
111 | typedef struct | ||
112 | { | ||
113 | uint16_t m_crc; | ||
114 | uint8_t m_pid; | ||
115 | uint8_t m_ack_payload; | ||
116 | } pipe_info_t; | ||
117 | |||
118 | // First in first out queue of payloads to be transmitted. | ||
119 | typedef struct | ||
120 | { | ||
121 | nrf52_payload_t * p_payload[NRF52_TX_FIFO_SIZE]; /**< Pointer to the actual queue. */ | ||
122 | uint32_t entry_point; /**< Current start of queue. */ | ||
123 | uint32_t exit_point; /**< Current end of queue. */ | ||
124 | uint32_t count; /**< Current number of elements in the queue. */ | ||
125 | } nrf52_payload_tx_fifo_t; | ||
126 | |||
127 | // First in first out queue of received payloads. | ||
128 | typedef struct | ||
129 | { | ||
130 | nrf52_payload_t * p_payload[NRF52_RX_FIFO_SIZE]; /**< Pointer to the actual queue. */ | ||
131 | uint32_t entry_point; /**< Current start of queue. */ | ||
132 | uint32_t exit_point; /**< Current end of queue. */ | ||
133 | uint32_t count; /**< Current number of elements in the queue. */ | ||
134 | } nrf52_payload_rx_fifo_t; | ||
135 | |||
136 | // These function pointers are changed dynamically, depending on protocol configuration and state. | ||
137 | //static void (*on_radio_end)(RFDriver *rfp) = NULL; | ||
138 | static void (*set_rf_payload_format)(RFDriver *rfp, uint32_t payload_length) = NULL; | ||
139 | |||
140 | // The following functions are assigned to the function pointers above. | ||
141 | static void on_radio_disabled_tx_noack(RFDriver *rfp); | ||
142 | static void on_radio_disabled_tx(RFDriver *rfp); | ||
143 | static void on_radio_disabled_tx_wait_for_ack(RFDriver *rfp); | ||
144 | static void on_radio_disabled_rx(RFDriver *rfp); | ||
145 | static void on_radio_disabled_rx_ack(RFDriver *rfp); | ||
146 | |||
147 | static volatile uint16_t wait_for_ack_timeout_us; | ||
148 | static nrf52_payload_t * p_current_payload; | ||
149 | |||
150 | // TX FIFO | ||
151 | static nrf52_payload_t tx_fifo_payload[NRF52_TX_FIFO_SIZE]; | ||
152 | static nrf52_payload_tx_fifo_t tx_fifo; | ||
153 | |||
154 | // RX FIFO | ||
155 | static nrf52_payload_t rx_fifo_payload[NRF52_RX_FIFO_SIZE]; | ||
156 | static nrf52_payload_rx_fifo_t rx_fifo; | ||
157 | |||
158 | // Payload buffers | ||
159 | static uint8_t tx_payload_buffer[NRF52_MAX_PAYLOAD_LENGTH + 2]; | ||
160 | static uint8_t rx_payload_buffer[NRF52_MAX_PAYLOAD_LENGTH + 2]; | ||
161 | |||
162 | static uint8_t pids[NRF52_PIPE_COUNT]; | ||
163 | static pipe_info_t rx_pipe_info[NRF52_PIPE_COUNT]; | ||
164 | |||
165 | // disable and events semaphores. | ||
166 | static binary_semaphore_t disable_sem; | ||
167 | static binary_semaphore_t events_sem; | ||
168 | |||
169 | RFDriver RFD1; | ||
170 | |||
171 | // Function to do bytewise bit-swap on a unsigned 32 bit value | ||
172 | static uint32_t bytewise_bit_swap(uint8_t const * p_inp) { | ||
173 | uint32_t inp = (*(uint32_t*)p_inp); | ||
174 | |||
175 | return __REV((uint32_t)__RBIT(inp)); //lint -esym(628, __rev) -esym(526, __rev) -esym(628, __rbit) -esym(526, __rbit) */ | ||
176 | } | ||
177 | |||
178 | // Internal function to convert base addresses from nRF24L type addressing to nRF52 type addressing | ||
179 | static uint32_t addr_conv(uint8_t const* p_addr) { | ||
180 | return __REV(bytewise_bit_swap(p_addr)); //lint -esym(628, __rev) -esym(526, __rev) */ | ||
181 | } | ||
182 | |||
183 | static thread_t *rfEvtThread_p; | ||
184 | static THD_WORKING_AREA(waRFEvtThread, 128); | ||
185 | static THD_FUNCTION(rfEvtThread, arg) { | ||
186 | (void)arg; | ||
187 | |||
188 | chRegSetThreadName("rfevent"); | ||
189 | |||
190 | while (!chThdShouldTerminateX()) { | ||
191 | chBSemWait(&events_sem); | ||
192 | |||
193 | nrf52_int_flags_t interrupts = RFD1.flags; | ||
194 | RFD1.flags = 0; | ||
195 | |||
196 | if (interrupts & NRF52_INT_TX_SUCCESS_MSK) { | ||
197 | chEvtBroadcastFlags(&RFD1.eventsrc, (eventflags_t) NRF52_EVENT_TX_SUCCESS); | ||
198 | } | ||
199 | if (interrupts & NRF52_INT_TX_FAILED_MSK) { | ||
200 | chEvtBroadcastFlags(&RFD1.eventsrc, (eventflags_t) NRF52_EVENT_TX_FAILED); | ||
201 | } | ||
202 | if (interrupts & NRF52_INT_RX_DR_MSK) { | ||
203 | chEvtBroadcastFlags(&RFD1.eventsrc, (eventflags_t) NRF52_EVENT_RX_RECEIVED); | ||
204 | } | ||
205 | } | ||
206 | chThdExit((msg_t) 0); | ||
207 | } | ||
208 | |||
209 | static thread_t *rfIntThread_p; | ||
210 | static THD_WORKING_AREA(waRFIntThread, 128); | ||
211 | static THD_FUNCTION(rfIntThread, arg) { | ||
212 | (void)arg; | ||
213 | |||
214 | chRegSetThreadName("rfint"); | ||
215 | |||
216 | while (!chThdShouldTerminateX()) { | ||
217 | chBSemWait(&disable_sem); | ||
218 | switch (RFD1.state) { | ||
219 | case NRF52_STATE_PTX_TX: | ||
220 | on_radio_disabled_tx_noack(&RFD1); | ||
221 | break; | ||
222 | case NRF52_STATE_PTX_TX_ACK: | ||
223 | on_radio_disabled_tx(&RFD1); | ||
224 | break; | ||
225 | case NRF52_STATE_PTX_RX_ACK: | ||
226 | on_radio_disabled_tx_wait_for_ack(&RFD1); | ||
227 | break; | ||
228 | case NRF52_STATE_PRX: | ||
229 | on_radio_disabled_rx(&RFD1); | ||
230 | break; | ||
231 | case NRF52_STATE_PRX_SEND_ACK: | ||
232 | on_radio_disabled_rx_ack(&RFD1); | ||
233 | break; | ||
234 | default: | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | chThdExit((msg_t) 0); | ||
239 | } | ||
240 | |||
241 | static void serve_radio_interrupt(RFDriver *rfp) { | ||
242 | if ((NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk) && NRF_RADIO->EVENTS_READY) { | ||
243 | NRF_RADIO->EVENTS_READY = 0; | ||
244 | (void) NRF_RADIO->EVENTS_READY; | ||
245 | } | ||
246 | if ((NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { | ||
247 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
248 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
249 | chSysLockFromISR(); | ||
250 | chBSemSignalI(&disable_sem); | ||
251 | chSysUnlockFromISR(); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * @brief RADIO events interrupt handler. | ||
257 | * | ||
258 | * @isr | ||
259 | */ | ||
260 | OSAL_IRQ_HANDLER(Vector44) { | ||
261 | |||
262 | OSAL_IRQ_PROLOGUE(); | ||
263 | |||
264 | serve_radio_interrupt(&RFD1); | ||
265 | |||
266 | OSAL_IRQ_EPILOGUE(); | ||
267 | } | ||
268 | |||
269 | static void set_rf_payload_format_esb_dpl(RFDriver *rfp, uint32_t payload_length) { | ||
270 | #if (NRF52_MAX_PAYLOAD_LENGTH <= 32) | ||
271 | // Using 6 bits for length | ||
272 | NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | | ||
273 | (6 << RADIO_PCNF0_LFLEN_Pos) | | ||
274 | (3 << RADIO_PCNF0_S1LEN_Pos) ; | ||
275 | #else | ||
276 | // Using 8 bits for length | ||
277 | NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | | ||
278 | (8 << RADIO_PCNF0_LFLEN_Pos) | | ||
279 | (3 << RADIO_PCNF0_S1LEN_Pos) ; | ||
280 | #endif | ||
281 | NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | | ||
282 | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | | ||
283 | ((rfp->config.address.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | | ||
284 | (0 << RADIO_PCNF1_STATLEN_Pos) | | ||
285 | (NRF52_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos); | ||
286 | } | ||
287 | |||
288 | static void set_rf_payload_format_esb(RFDriver *rfp, uint32_t payload_length) { | ||
289 | NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) | | ||
290 | (0 << RADIO_PCNF0_LFLEN_Pos) | | ||
291 | (1 << RADIO_PCNF0_S1LEN_Pos); | ||
292 | |||
293 | NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | | ||
294 | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | | ||
295 | ((rfp->config.address.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | | ||
296 | (payload_length << RADIO_PCNF1_STATLEN_Pos) | | ||
297 | (payload_length << RADIO_PCNF1_MAXLEN_Pos); | ||
298 | } | ||
299 | |||
300 | /* Set BASE0 and BASE1 addresses & prefixes registers | ||
301 | * NRF52 { prefixes[0], base0_addr[0], base0_addr[1], base0_addr[2], base0_addr[3] } == | ||
302 | * NRF24 { addr[0], addr[1], addr[2], addr[3], addr[4] } | ||
303 | */ | ||
304 | static void set_addresses(RFDriver *rfp, uint8_t update_mask) { | ||
305 | if (update_mask & NRF52_ADDR_UPDATE_MASK_BASE0) { | ||
306 | NRF_RADIO->BASE0 = addr_conv(rfp->config.address.base_addr_p0); | ||
307 | NRF_RADIO->DAB[0] = addr_conv(rfp->config.address.base_addr_p0); | ||
308 | } | ||
309 | |||
310 | if (update_mask & NRF52_ADDR_UPDATE_MASK_BASE1) { | ||
311 | NRF_RADIO->BASE1 = addr_conv(rfp->config.address.base_addr_p1); | ||
312 | NRF_RADIO->DAB[1] = addr_conv(rfp->config.address.base_addr_p1); | ||
313 | } | ||
314 | |||
315 | if (update_mask & NRF52_ADDR_UPDATE_MASK_PREFIX) { | ||
316 | NRF_RADIO->PREFIX0 = bytewise_bit_swap(&rfp->config.address.pipe_prefixes[0]); | ||
317 | NRF_RADIO->DAP[0] = bytewise_bit_swap(&rfp->config.address.pipe_prefixes[0]); | ||
318 | NRF_RADIO->PREFIX1 = bytewise_bit_swap(&rfp->config.address.pipe_prefixes[4]); | ||
319 | NRF_RADIO->DAP[1] = bytewise_bit_swap(&rfp->config.address.pipe_prefixes[4]); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | static void set_tx_power(RFDriver *rfp) { | ||
324 | NRF_RADIO->TXPOWER = rfp->config.tx_power << RADIO_TXPOWER_TXPOWER_Pos; | ||
325 | } | ||
326 | |||
327 | static void set_bitrate(RFDriver *rfp) { | ||
328 | NRF_RADIO->MODE = rfp->config.bitrate << RADIO_MODE_MODE_Pos; | ||
329 | |||
330 | switch (rfp->config.bitrate) { | ||
331 | case NRF52_BITRATE_2MBPS: | ||
332 | wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS; | ||
333 | break; | ||
334 | case NRF52_BITRATE_1MBPS: | ||
335 | wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS; | ||
336 | break; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static void set_protocol(RFDriver *rfp) { | ||
341 | switch (rfp->config.protocol) { | ||
342 | case NRF52_PROTOCOL_ESB_DPL: | ||
343 | set_rf_payload_format = set_rf_payload_format_esb_dpl; | ||
344 | break; | ||
345 | case NRF52_PROTOCOL_ESB: | ||
346 | set_rf_payload_format = set_rf_payload_format_esb; | ||
347 | break; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | static void set_crc(RFDriver *rfp) { | ||
352 | NRF_RADIO->CRCCNF = rfp->config.crc << RADIO_CRCCNF_LEN_Pos; | ||
353 | |||
354 | if (rfp->config.crc == RADIO_CRCCNF_LEN_Two) | ||
355 | { | ||
356 | NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value | ||
357 | NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1 | ||
358 | } | ||
359 | else if (rfp->config.crc == RADIO_CRCCNF_LEN_One) | ||
360 | { | ||
361 | NRF_RADIO->CRCINIT = 0xFFUL; // Initial value | ||
362 | NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1 | ||
363 | } | ||
364 | } | ||
365 | |||
366 | static void ppi_init(RFDriver *rfp) { | ||
367 | NRF_PPI->CH[NRF52_RADIO_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY; | ||
368 | NRF_PPI->CH[NRF52_RADIO_PPI_TIMER_START].TEP = (uint32_t)&rfp->timer->TASKS_START; | ||
369 | |||
370 | NRF_PPI->CH[NRF52_RADIO_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS; | ||
371 | NRF_PPI->CH[NRF52_RADIO_PPI_TIMER_STOP].TEP = (uint32_t)&rfp->timer->TASKS_STOP; | ||
372 | |||
373 | NRF_PPI->CH[NRF52_RADIO_PPI_RX_TIMEOUT].EEP = (uint32_t)&rfp->timer->EVENTS_COMPARE[0]; | ||
374 | NRF_PPI->CH[NRF52_RADIO_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE; | ||
375 | |||
376 | NRF_PPI->CH[NRF52_RADIO_PPI_TX_START].EEP = (uint32_t)&rfp->timer->EVENTS_COMPARE[1]; | ||
377 | NRF_PPI->CH[NRF52_RADIO_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; | ||
378 | } | ||
379 | |||
380 | static void set_parameters(RFDriver *rfp) { | ||
381 | set_tx_power(rfp); | ||
382 | set_bitrate(rfp); | ||
383 | set_protocol(rfp); | ||
384 | set_crc(rfp); | ||
385 | set_rf_payload_format(rfp, rfp->config.payload_length); | ||
386 | } | ||
387 | |||
388 | static void reset_fifo(void) { | ||
389 | tx_fifo.entry_point = 0; | ||
390 | tx_fifo.exit_point = 0; | ||
391 | tx_fifo.count = 0; | ||
392 | |||
393 | rx_fifo.entry_point = 0; | ||
394 | rx_fifo.exit_point = 0; | ||
395 | rx_fifo.count = 0; | ||
396 | } | ||
397 | |||
398 | static void init_fifo(void) { | ||
399 | reset_fifo(); | ||
400 | |||
401 | for (int i = 0; i < NRF52_TX_FIFO_SIZE; i++) { | ||
402 | tx_fifo.p_payload[i] = &tx_fifo_payload[i]; | ||
403 | } | ||
404 | |||
405 | for (int i = 0; i < NRF52_RX_FIFO_SIZE; i++) { | ||
406 | rx_fifo.p_payload[i] = &rx_fifo_payload[i]; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | static void tx_fifo_remove_last(void) { | ||
411 | if (tx_fifo.count > 0) { | ||
412 | nvicDisableVector(RADIO_IRQn); | ||
413 | |||
414 | tx_fifo.count--; | ||
415 | if (++tx_fifo.exit_point >= NRF52_TX_FIFO_SIZE) { | ||
416 | tx_fifo.exit_point = 0; | ||
417 | } | ||
418 | |||
419 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /** @brief Function to push the content of the rx_buffer to the RX FIFO. | ||
424 | * | ||
425 | * The module will point the register NRF_RADIO->PACKETPTR to a buffer for receiving packets. | ||
426 | * After receiving a packet the module will call this function to copy the received data to | ||
427 | * the RX FIFO. | ||
428 | * | ||
429 | * @param pipe Pipe number to set for the packet. | ||
430 | * @param pid Packet ID. | ||
431 | * | ||
432 | * @retval true Operation successful. | ||
433 | * @retval false Operation failed. | ||
434 | */ | ||
435 | static bool rx_fifo_push_rfbuf(RFDriver *rfp, uint8_t pipe, uint8_t pid) { | ||
436 | if (rx_fifo.count < NRF52_RX_FIFO_SIZE) { | ||
437 | if (rfp->config.protocol == NRF52_PROTOCOL_ESB_DPL) { | ||
438 | if (rx_payload_buffer[0] > NRF52_MAX_PAYLOAD_LENGTH) { | ||
439 | return false; | ||
440 | } | ||
441 | |||
442 | rx_fifo.p_payload[rx_fifo.entry_point]->length = rx_payload_buffer[0]; | ||
443 | } | ||
444 | else if (rfp->state == NRF52_STATE_PTX_RX_ACK) { | ||
445 | // Received packet is an acknowledgment | ||
446 | rx_fifo.p_payload[rx_fifo.entry_point]->length = 0; | ||
447 | } | ||
448 | else { | ||
449 | rx_fifo.p_payload[rx_fifo.entry_point]->length = rfp->config.payload_length; | ||
450 | } | ||
451 | |||
452 | memcpy(rx_fifo.p_payload[rx_fifo.entry_point]->data, &rx_payload_buffer[2], | ||
453 | rx_fifo.p_payload[rx_fifo.entry_point]->length); | ||
454 | |||
455 | rx_fifo.p_payload[rx_fifo.entry_point]->pipe = pipe; | ||
456 | rx_fifo.p_payload[rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE; | ||
457 | rx_fifo.p_payload[rx_fifo.entry_point]->pid = pid; | ||
458 | if (++rx_fifo.entry_point >= NRF52_RX_FIFO_SIZE) { | ||
459 | rx_fifo.entry_point = 0; | ||
460 | } | ||
461 | rx_fifo.count++; | ||
462 | |||
463 | return true; | ||
464 | } | ||
465 | |||
466 | return false; | ||
467 | } | ||
468 | |||
469 | static void timer_init(RFDriver *rfp) { | ||
470 | // Configure the system timer with a 1 MHz base frequency | ||
471 | rfp->timer->PRESCALER = 4; | ||
472 | rfp->timer->BITMODE = TIMER_BITMODE_BITMODE_16Bit; | ||
473 | rfp->timer->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk; | ||
474 | } | ||
475 | |||
476 | static void start_tx_transaction(RFDriver *rfp) { | ||
477 | bool ack; | ||
478 | |||
479 | rfp->tx_attempt = 1; | ||
480 | rfp->tx_remaining = rfp->config.retransmit.count; | ||
481 | |||
482 | // Prepare the payload | ||
483 | p_current_payload = tx_fifo.p_payload[tx_fifo.exit_point]; | ||
484 | |||
485 | // Handling ack if noack is set to false or if selctive auto ack is turned turned off | ||
486 | ack = !p_current_payload->noack || !rfp->config.selective_auto_ack; | ||
487 | |||
488 | switch (rfp->config.protocol) { | ||
489 | case NRF52_PROTOCOL_ESB: | ||
490 | set_rf_payload_format(rfp, p_current_payload->length); | ||
491 | tx_payload_buffer[0] = p_current_payload->pid; | ||
492 | tx_payload_buffer[1] = 0; | ||
493 | memcpy(&tx_payload_buffer[2], p_current_payload->data, p_current_payload->length); | ||
494 | |||
495 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; | ||
496 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; | ||
497 | |||
498 | // Configure the retransmit counter | ||
499 | rfp->tx_remaining = rfp->config.retransmit.count; | ||
500 | rfp->state = NRF52_STATE_PTX_TX_ACK; | ||
501 | break; | ||
502 | |||
503 | case NRF52_PROTOCOL_ESB_DPL: | ||
504 | tx_payload_buffer[0] = p_current_payload->length; | ||
505 | tx_payload_buffer[1] = p_current_payload->pid << 1; | ||
506 | tx_payload_buffer[1] |= ack ? 0x00 : 0x01; | ||
507 | memcpy(&tx_payload_buffer[2], p_current_payload->data, p_current_payload->length); | ||
508 | |||
509 | if (ack) { | ||
510 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; | ||
511 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; | ||
512 | |||
513 | // Configure the retransmit counter | ||
514 | rfp->tx_remaining = rfp->config.retransmit.count; | ||
515 | rfp->state = NRF52_STATE_PTX_TX_ACK; | ||
516 | } | ||
517 | else { | ||
518 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; | ||
519 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; | ||
520 | rfp->state = NRF52_STATE_PTX_TX; | ||
521 | } | ||
522 | break; | ||
523 | } | ||
524 | |||
525 | NRF_RADIO->TXADDRESS = p_current_payload->pipe; | ||
526 | NRF_RADIO->RXADDRESSES = 1 << p_current_payload->pipe; | ||
527 | |||
528 | NRF_RADIO->FREQUENCY = rfp->config.address.rf_channel; | ||
529 | NRF_RADIO->PACKETPTR = (uint32_t)tx_payload_buffer; | ||
530 | |||
531 | NRF_RADIO->EVENTS_READY = 0; | ||
532 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
533 | (void)NRF_RADIO->EVENTS_READY; | ||
534 | (void)NRF_RADIO->EVENTS_DISABLED; | ||
535 | |||
536 | nvicClearPending(RADIO_IRQn); | ||
537 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
538 | |||
539 | NRF_RADIO->TASKS_TXEN = 1; | ||
540 | } | ||
541 | |||
542 | static void on_radio_disabled_tx_noack(RFDriver *rfp) { | ||
543 | rfp->flags |= NRF52_INT_TX_SUCCESS_MSK; | ||
544 | tx_fifo_remove_last(); | ||
545 | |||
546 | chBSemSignal(&events_sem); | ||
547 | |||
548 | if (tx_fifo.count == 0) { | ||
549 | rfp->state = NRF52_STATE_IDLE; | ||
550 | } | ||
551 | else { | ||
552 | start_tx_transaction(rfp); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | static void on_radio_disabled_tx(RFDriver *rfp) { | ||
557 | // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays | ||
558 | // disabled after the RX window | ||
559 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; | ||
560 | |||
561 | // Make sure the timer is started the next time the radio is ready, | ||
562 | // and that it will disable the radio automatically if no packet is | ||
563 | // received by the time defined in m_wait_for_ack_timeout_us | ||
564 | rfp->timer->CC[0] = wait_for_ack_timeout_us + 130; | ||
565 | rfp->timer->CC[1] = rfp->config.retransmit.delay - 130; | ||
566 | rfp->timer->TASKS_CLEAR = 1; | ||
567 | rfp->timer->EVENTS_COMPARE[0] = 0; | ||
568 | rfp->timer->EVENTS_COMPARE[1] = 0; | ||
569 | (void)rfp->timer->EVENTS_COMPARE[0]; | ||
570 | (void)rfp->timer->EVENTS_COMPARE[1]; | ||
571 | |||
572 | NRF_PPI->CHENSET = (1 << NRF52_RADIO_PPI_TIMER_START) | | ||
573 | (1 << NRF52_RADIO_PPI_RX_TIMEOUT) | | ||
574 | (1 << NRF52_RADIO_PPI_TIMER_STOP); | ||
575 | NRF_PPI->CHENCLR = (1 << NRF52_RADIO_PPI_TX_START); | ||
576 | |||
577 | NRF_RADIO->EVENTS_END = 0; | ||
578 | (void)NRF_RADIO->EVENTS_END; | ||
579 | |||
580 | if (rfp->config.protocol == NRF52_PROTOCOL_ESB) { | ||
581 | set_rf_payload_format(rfp, 0); | ||
582 | } | ||
583 | |||
584 | NRF_RADIO->PACKETPTR = (uint32_t)rx_payload_buffer; | ||
585 | rfp->state = NRF52_STATE_PTX_RX_ACK; | ||
586 | } | ||
587 | |||
588 | static void on_radio_disabled_tx_wait_for_ack(RFDriver *rfp) { | ||
589 | // This marks the completion of a TX_RX sequence (TX with ACK) | ||
590 | |||
591 | // Make sure the timer will not deactivate the radio if a packet is received | ||
592 | NRF_PPI->CHENCLR = (1 << NRF52_RADIO_PPI_TIMER_START) | | ||
593 | (1 << NRF52_RADIO_PPI_RX_TIMEOUT) | | ||
594 | (1 << NRF52_RADIO_PPI_TIMER_STOP); | ||
595 | |||
596 | // If the radio has received a packet and the CRC status is OK | ||
597 | if (NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0) { | ||
598 | rfp->timer->TASKS_STOP = 1; | ||
599 | NRF_PPI->CHENCLR = (1 << NRF52_RADIO_PPI_TX_START); | ||
600 | rfp->flags |= NRF52_INT_TX_SUCCESS_MSK; | ||
601 | rfp->tx_attempt++;// = rfp->config.retransmit.count - rfp->tx_remaining + 1; | ||
602 | |||
603 | tx_fifo_remove_last(); | ||
604 | |||
605 | if (rfp->config.protocol != NRF52_PROTOCOL_ESB && rx_payload_buffer[0] > 0) { | ||
606 | if (rx_fifo_push_rfbuf(rfp, (uint8_t)NRF_RADIO->TXADDRESS, 0)) { | ||
607 | rfp->flags |= NRF52_INT_RX_DR_MSK; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | chBSemSignal(&events_sem); | ||
612 | |||
613 | if ((tx_fifo.count == 0) || (rfp->config.tx_mode == NRF52_TXMODE_MANUAL)) { | ||
614 | rfp->state = NRF52_STATE_IDLE; | ||
615 | } | ||
616 | else { | ||
617 | start_tx_transaction(rfp); | ||
618 | } | ||
619 | } | ||
620 | else { | ||
621 | if (rfp->tx_remaining-- == 0) { | ||
622 | rfp->timer->TASKS_STOP = 1; | ||
623 | NRF_PPI->CHENCLR = (1 << NRF52_RADIO_PPI_TX_START); | ||
624 | // All retransmits are expended, and the TX operation is suspended | ||
625 | rfp->tx_attempt = rfp->config.retransmit.count + 1; | ||
626 | rfp->flags |= NRF52_INT_TX_FAILED_MSK; | ||
627 | |||
628 | chBSemSignal(&events_sem); | ||
629 | |||
630 | rfp->state = NRF52_STATE_IDLE; | ||
631 | } | ||
632 | else { | ||
633 | // There are still have more retransmits left, TX mode should be | ||
634 | // entered again as soon as the system timer reaches CC[1]. | ||
635 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; | ||
636 | set_rf_payload_format(rfp, p_current_payload->length); | ||
637 | NRF_RADIO->PACKETPTR = (uint32_t)tx_payload_buffer; | ||
638 | rfp->state = NRF52_STATE_PTX_TX_ACK; | ||
639 | rfp->timer->TASKS_START = 1; | ||
640 | NRF_PPI->CHENSET = (1 << NRF52_RADIO_PPI_TX_START); | ||
641 | if (rfp->timer->EVENTS_COMPARE[1]) | ||
642 | NRF_RADIO->TASKS_TXEN = 1; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
647 | static void clear_events_restart_rx(RFDriver *rfp) { | ||
648 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; | ||
649 | set_rf_payload_format(rfp, rfp->config.payload_length); | ||
650 | NRF_RADIO->PACKETPTR = (uint32_t)rx_payload_buffer; | ||
651 | |||
652 | NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; | ||
653 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
654 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
655 | |||
656 | NRF_RADIO->TASKS_DISABLE = 1; | ||
657 | while (NRF_RADIO->EVENTS_DISABLED == 0); | ||
658 | |||
659 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
660 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
661 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; | ||
662 | |||
663 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; | ||
664 | NRF_RADIO->TASKS_RXEN = 1; | ||
665 | } | ||
666 | |||
667 | static void on_radio_disabled_rx(RFDriver *rfp) { | ||
668 | bool ack = false; | ||
669 | bool retransmit_payload = false; | ||
670 | bool send_rx_event = true; | ||
671 | pipe_info_t * p_pipe_info; | ||
672 | |||
673 | if (NRF_RADIO->CRCSTATUS == 0) { | ||
674 | clear_events_restart_rx(rfp); | ||
675 | return; | ||
676 | } | ||
677 | |||
678 | if(rx_fifo.count >= NRF52_RX_FIFO_SIZE) { | ||
679 | clear_events_restart_rx(rfp); | ||
680 | return; | ||
681 | } | ||
682 | |||
683 | p_pipe_info = &rx_pipe_info[NRF_RADIO->RXMATCH]; | ||
684 | if (NRF_RADIO->RXCRC == p_pipe_info->m_crc && | ||
685 | (rx_payload_buffer[1] >> 1) == p_pipe_info->m_pid ) { | ||
686 | retransmit_payload = true; | ||
687 | send_rx_event = false; | ||
688 | } | ||
689 | |||
690 | p_pipe_info->m_pid = rx_payload_buffer[1] >> 1; | ||
691 | p_pipe_info->m_crc = NRF_RADIO->RXCRC; | ||
692 | |||
693 | if(rfp->config.selective_auto_ack == false || ((rx_payload_buffer[1] & 0x01) == 0)) | ||
694 | ack = true; | ||
695 | |||
696 | if(ack) { | ||
697 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; | ||
698 | |||
699 | switch(rfp->config.protocol) { | ||
700 | case NRF52_PROTOCOL_ESB_DPL: | ||
701 | { | ||
702 | if (tx_fifo.count > 0 && | ||
703 | (tx_fifo.p_payload[tx_fifo.exit_point]->pipe == NRF_RADIO->RXMATCH)) | ||
704 | { | ||
705 | // Pipe stays in ACK with payload until TX fifo is empty | ||
706 | // Do not report TX success on first ack payload or retransmit | ||
707 | if (p_pipe_info->m_ack_payload != 0 && !retransmit_payload) { | ||
708 | if(++tx_fifo.exit_point >= NRF52_TX_FIFO_SIZE) { | ||
709 | tx_fifo.exit_point = 0; | ||
710 | } | ||
711 | |||
712 | tx_fifo.count--; | ||
713 | |||
714 | // ACK payloads also require TX_DS | ||
715 | // (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf'). | ||
716 | rfp->flags |= NRF52_INT_TX_SUCCESS_MSK; | ||
717 | } | ||
718 | |||
719 | p_pipe_info->m_ack_payload = 1; | ||
720 | |||
721 | p_current_payload = tx_fifo.p_payload[tx_fifo.exit_point]; | ||
722 | |||
723 | set_rf_payload_format(rfp, p_current_payload->length); | ||
724 | tx_payload_buffer[0] = p_current_payload->length; | ||
725 | memcpy(&tx_payload_buffer[2], | ||
726 | p_current_payload->data, | ||
727 | p_current_payload->length); | ||
728 | } | ||
729 | else { | ||
730 | p_pipe_info->m_ack_payload = 0; | ||
731 | set_rf_payload_format(rfp, 0); | ||
732 | tx_payload_buffer[0] = 0; | ||
733 | } | ||
734 | |||
735 | tx_payload_buffer[1] = rx_payload_buffer[1]; | ||
736 | } | ||
737 | break; | ||
738 | |||
739 | case NRF52_PROTOCOL_ESB: | ||
740 | { | ||
741 | set_rf_payload_format(rfp, 0); | ||
742 | tx_payload_buffer[0] = rx_payload_buffer[0]; | ||
743 | tx_payload_buffer[1] = 0; | ||
744 | } | ||
745 | break; | ||
746 | } | ||
747 | |||
748 | rfp->state = NRF52_STATE_PRX_SEND_ACK; | ||
749 | NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH; | ||
750 | NRF_RADIO->PACKETPTR = (uint32_t)tx_payload_buffer; | ||
751 | } | ||
752 | else { | ||
753 | clear_events_restart_rx(rfp); | ||
754 | } | ||
755 | |||
756 | if (send_rx_event) { | ||
757 | // Push the new packet to the RX buffer and trigger a received event if the operation was | ||
758 | // successful. | ||
759 | if (rx_fifo_push_rfbuf(rfp, NRF_RADIO->RXMATCH, p_pipe_info->m_pid)) { | ||
760 | rfp->flags |= NRF52_INT_RX_DR_MSK; | ||
761 | chBSemSignal(&events_sem); | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | static void on_radio_disabled_rx_ack(RFDriver *rfp) { | ||
767 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; | ||
768 | set_rf_payload_format(rfp, rfp->config.payload_length); | ||
769 | |||
770 | NRF_RADIO->PACKETPTR = (uint32_t)rx_payload_buffer; | ||
771 | |||
772 | rfp->state = NRF52_STATE_PRX; | ||
773 | } | ||
774 | |||
775 | nrf52_error_t radio_disable(void) { | ||
776 | NRF_RADIO->SHORTS = 0; | ||
777 | NRF_RADIO->INTENCLR = 0xFFFFFFFF; | ||
778 | |||
779 | nvicDisableVector(RADIO_IRQn); | ||
780 | |||
781 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
782 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
783 | |||
784 | NRF_RADIO->TASKS_STOP = 1; | ||
785 | NRF_RADIO->TASKS_DISABLE = 1; | ||
786 | |||
787 | RFD1.state = NRF52_STATE_IDLE; | ||
788 | |||
789 | // Clear PPI | ||
790 | NRF_PPI->CHENCLR = (1 << NRF52_RADIO_PPI_TIMER_START) | | ||
791 | (1 << NRF52_RADIO_PPI_TIMER_STOP) | | ||
792 | (1 << NRF52_RADIO_PPI_RX_TIMEOUT) | | ||
793 | (1 << NRF52_RADIO_PPI_TX_START); | ||
794 | |||
795 | reset_fifo(); | ||
796 | |||
797 | memset(rx_pipe_info, 0, sizeof(rx_pipe_info)); | ||
798 | memset(pids, 0, sizeof(pids)); | ||
799 | |||
800 | // Terminate interrupts handle thread | ||
801 | chThdTerminate(rfIntThread_p); | ||
802 | chBSemSignal(&disable_sem); | ||
803 | chThdWait(rfIntThread_p); | ||
804 | |||
805 | // Terminate events handle thread | ||
806 | chThdTerminate(rfEvtThread_p); | ||
807 | RFD1.flags = 0; | ||
808 | chBSemSignal(&events_sem); | ||
809 | chThdWait(rfEvtThread_p); | ||
810 | |||
811 | RFD1.state = NRF52_STATE_UNINIT; | ||
812 | |||
813 | return NRF52_SUCCESS; | ||
814 | } | ||
815 | |||
816 | // | ||
817 | nrf52_error_t radio_init(nrf52_config_t const *config) { | ||
818 | osalDbgAssert(config != NULL, | ||
819 | "config must be defined"); | ||
820 | osalDbgAssert(&config->address != NULL, | ||
821 | "address must be defined"); | ||
822 | osalDbgAssert(NRF52_RADIO_IRQ_PRIORITY <= 7, | ||
823 | "wrong radio irq priority"); | ||
824 | |||
825 | if (RFD1.state != NRF52_STATE_UNINIT) { | ||
826 | nrf52_error_t err = radio_disable(); | ||
827 | if (err != NRF52_SUCCESS) | ||
828 | return err; | ||
829 | } | ||
830 | |||
831 | RFD1.radio = NRF_RADIO; | ||
832 | RFD1.config = *config; | ||
833 | RFD1.flags = 0; | ||
834 | |||
835 | init_fifo(); | ||
836 | |||
837 | #if NRF52_RADIO_USE_TIMER0 | ||
838 | RFD1.timer = NRF_TIMER0; | ||
839 | #endif | ||
840 | #if NRF52_RADIO_USE_TIMER1 | ||
841 | RFD1.timer = NRF_TIMER1; | ||
842 | #endif | ||
843 | #if NRF52_RADIO_USE_TIMER2 | ||
844 | RFD1.timer = NRF_TIMER2; | ||
845 | #endif | ||
846 | #if NRF52_RADIO_USE_TIMER3 | ||
847 | RFD1.timer = NRF_TIMER3; | ||
848 | #endif | ||
849 | #if NRF52_RADIO_USE_TIMER4 | ||
850 | RFD1.timer = NRF_TIMER4; | ||
851 | #endif | ||
852 | |||
853 | set_parameters(&RFD1); | ||
854 | |||
855 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_BASE0); | ||
856 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_BASE1); | ||
857 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_PREFIX); | ||
858 | |||
859 | ppi_init(&RFD1); | ||
860 | timer_init(&RFD1); | ||
861 | |||
862 | chBSemObjectInit(&disable_sem, TRUE); | ||
863 | chBSemObjectInit(&events_sem, TRUE); | ||
864 | |||
865 | chEvtObjectInit(&RFD1.eventsrc); | ||
866 | |||
867 | // interrupt handle thread | ||
868 | rfIntThread_p = chThdCreateStatic(waRFIntThread, sizeof(waRFIntThread), | ||
869 | NRF52_RADIO_INTTHD_PRIORITY, rfIntThread, NULL); | ||
870 | |||
871 | // events handle thread | ||
872 | rfEvtThread_p = chThdCreateStatic(waRFEvtThread, sizeof(waRFEvtThread), | ||
873 | NRF52_RADIO_EVTTHD_PRIORITY, rfEvtThread, NULL); | ||
874 | |||
875 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
876 | |||
877 | RFD1.state = NRF52_STATE_IDLE; | ||
878 | |||
879 | return NRF52_SUCCESS; | ||
880 | } | ||
881 | |||
882 | nrf52_error_t radio_write_payload(nrf52_payload_t const * p_payload) { | ||
883 | if (RFD1.state == NRF52_STATE_UNINIT) | ||
884 | return NRF52_INVALID_STATE; | ||
885 | if(p_payload == NULL) | ||
886 | return NRF52_ERROR_NULL; | ||
887 | VERIFY_PAYLOAD_LENGTH(p_payload); | ||
888 | if (tx_fifo.count >= NRF52_TX_FIFO_SIZE) | ||
889 | return NRF52_ERROR_INVALID_LENGTH; | ||
890 | |||
891 | if (RFD1.config.mode == NRF52_MODE_PTX && | ||
892 | p_payload->noack && !RFD1.config.selective_auto_ack ) | ||
893 | { | ||
894 | return NRF52_ERROR_NOT_SUPPORTED; | ||
895 | } | ||
896 | |||
897 | nvicDisableVector(RADIO_IRQn); | ||
898 | |||
899 | memcpy(tx_fifo.p_payload[tx_fifo.entry_point], p_payload, sizeof(nrf52_payload_t)); | ||
900 | |||
901 | pids[p_payload->pipe] = (pids[p_payload->pipe] + 1) % (NRF52_PID_MAX + 1); | ||
902 | tx_fifo.p_payload[tx_fifo.entry_point]->pid = pids[p_payload->pipe]; | ||
903 | |||
904 | if (++tx_fifo.entry_point >= NRF52_TX_FIFO_SIZE) { | ||
905 | tx_fifo.entry_point = 0; | ||
906 | } | ||
907 | |||
908 | tx_fifo.count++; | ||
909 | |||
910 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
911 | |||
912 | if (RFD1.config.mode == NRF52_MODE_PTX && | ||
913 | RFD1.config.tx_mode == NRF52_TXMODE_AUTO && | ||
914 | RFD1.state == NRF52_STATE_IDLE) | ||
915 | { | ||
916 | start_tx_transaction(&RFD1); | ||
917 | } | ||
918 | |||
919 | return NRF52_SUCCESS; | ||
920 | } | ||
921 | |||
922 | nrf52_error_t radio_read_rx_payload(nrf52_payload_t * p_payload) { | ||
923 | if (RFD1.state == NRF52_STATE_UNINIT) | ||
924 | return NRF52_INVALID_STATE; | ||
925 | if (p_payload == NULL) | ||
926 | return NRF52_ERROR_NULL; | ||
927 | |||
928 | if (rx_fifo.count == 0) { | ||
929 | return NRF52_ERROR_INVALID_LENGTH; | ||
930 | } | ||
931 | |||
932 | nvicDisableVector(RADIO_IRQn); | ||
933 | |||
934 | p_payload->length = rx_fifo.p_payload[rx_fifo.exit_point]->length; | ||
935 | p_payload->pipe = rx_fifo.p_payload[rx_fifo.exit_point]->pipe; | ||
936 | p_payload->rssi = rx_fifo.p_payload[rx_fifo.exit_point]->rssi; | ||
937 | p_payload->pid = rx_fifo.p_payload[rx_fifo.exit_point]->pid; | ||
938 | memcpy(p_payload->data, rx_fifo.p_payload[rx_fifo.exit_point]->data, p_payload->length); | ||
939 | |||
940 | if (++rx_fifo.exit_point >= NRF52_RX_FIFO_SIZE) { | ||
941 | rx_fifo.exit_point = 0; | ||
942 | } | ||
943 | |||
944 | rx_fifo.count--; | ||
945 | |||
946 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
947 | |||
948 | return NRF52_SUCCESS; | ||
949 | } | ||
950 | |||
951 | nrf52_error_t radio_start_tx(void) { | ||
952 | if (RFD1.state != NRF52_STATE_IDLE) | ||
953 | return NRF52_ERROR_BUSY; | ||
954 | |||
955 | if (tx_fifo.count == 0) { | ||
956 | return NRF52_ERROR_INVALID_LENGTH; | ||
957 | } | ||
958 | |||
959 | start_tx_transaction(&RFD1); | ||
960 | |||
961 | return NRF52_SUCCESS; | ||
962 | } | ||
963 | |||
964 | nrf52_error_t radio_start_rx(void) { | ||
965 | if (RFD1.state != NRF52_STATE_IDLE) | ||
966 | return NRF52_ERROR_BUSY; | ||
967 | |||
968 | NRF_RADIO->INTENCLR = 0xFFFFFFFF; | ||
969 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
970 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
971 | |||
972 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; | ||
973 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; | ||
974 | RFD1.state = NRF52_STATE_PRX; | ||
975 | |||
976 | NRF_RADIO->RXADDRESSES = RFD1.config.address.rx_pipes; | ||
977 | NRF_RADIO->FREQUENCY = RFD1.config.address.rf_channel; | ||
978 | NRF_RADIO->PACKETPTR = (uint32_t)rx_payload_buffer; | ||
979 | |||
980 | nvicClearPending(RADIO_IRQn); | ||
981 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
982 | |||
983 | NRF_RADIO->EVENTS_ADDRESS = 0; | ||
984 | NRF_RADIO->EVENTS_PAYLOAD = 0; | ||
985 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
986 | (void) NRF_RADIO->EVENTS_ADDRESS; | ||
987 | (void) NRF_RADIO->EVENTS_PAYLOAD; | ||
988 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
989 | |||
990 | NRF_RADIO->TASKS_RXEN = 1; | ||
991 | |||
992 | return NRF52_SUCCESS; | ||
993 | } | ||
994 | |||
995 | nrf52_error_t radio_stop_rx(void) { | ||
996 | if (RFD1.state != NRF52_STATE_PRX) { | ||
997 | return NRF52_INVALID_STATE; | ||
998 | } | ||
999 | |||
1000 | NRF_RADIO->SHORTS = 0; | ||
1001 | NRF_RADIO->INTENCLR = 0xFFFFFFFF; | ||
1002 | NRF_RADIO->EVENTS_DISABLED = 0; | ||
1003 | (void) NRF_RADIO->EVENTS_DISABLED; | ||
1004 | NRF_RADIO->TASKS_DISABLE = 1; | ||
1005 | while (NRF_RADIO->EVENTS_DISABLED == 0); | ||
1006 | RFD1.state = NRF52_STATE_IDLE; | ||
1007 | |||
1008 | return NRF52_SUCCESS; | ||
1009 | } | ||
1010 | |||
1011 | nrf52_error_t radio_flush_tx(void) { | ||
1012 | if (RFD1.state == NRF52_STATE_UNINIT) | ||
1013 | return NRF52_INVALID_STATE; | ||
1014 | |||
1015 | nvicDisableVector(RADIO_IRQn); | ||
1016 | |||
1017 | tx_fifo.count = 0; | ||
1018 | tx_fifo.entry_point = 0; | ||
1019 | tx_fifo.exit_point = 0; | ||
1020 | |||
1021 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
1022 | |||
1023 | return NRF52_SUCCESS; | ||
1024 | } | ||
1025 | |||
1026 | nrf52_error_t radio_pop_tx(void) { | ||
1027 | if (RFD1.state == NRF52_STATE_UNINIT) | ||
1028 | return NRF52_INVALID_STATE; | ||
1029 | if (tx_fifo.count == 0) | ||
1030 | return NRF52_ERROR_INVALID_LENGTH; | ||
1031 | |||
1032 | nvicDisableVector(RADIO_IRQn); | ||
1033 | |||
1034 | if (++tx_fifo.entry_point >= NRF52_TX_FIFO_SIZE) { | ||
1035 | tx_fifo.entry_point = 0; | ||
1036 | } | ||
1037 | tx_fifo.count--; | ||
1038 | |||
1039 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
1040 | |||
1041 | return NRF52_SUCCESS; | ||
1042 | } | ||
1043 | |||
1044 | nrf52_error_t radio_flush_rx(void) { | ||
1045 | if (RFD1.state == NRF52_STATE_UNINIT) | ||
1046 | return NRF52_INVALID_STATE; | ||
1047 | |||
1048 | nvicDisableVector(RADIO_IRQn); | ||
1049 | |||
1050 | rx_fifo.count = 0; | ||
1051 | rx_fifo.entry_point = 0; | ||
1052 | rx_fifo.exit_point = 0; | ||
1053 | |||
1054 | memset(rx_pipe_info, 0, sizeof(rx_pipe_info)); | ||
1055 | |||
1056 | nvicEnableVector(RADIO_IRQn, NRF52_RADIO_IRQ_PRIORITY); | ||
1057 | |||
1058 | return NRF52_SUCCESS; | ||
1059 | } | ||
1060 | |||
1061 | nrf52_error_t radio_set_base_address_0(uint8_t const * p_addr) { | ||
1062 | if (RFD1.state != NRF52_STATE_IDLE) | ||
1063 | return NRF52_ERROR_BUSY; | ||
1064 | if (p_addr == NULL) | ||
1065 | return NRF52_ERROR_NULL; | ||
1066 | |||
1067 | memcpy(RFD1.config.address.base_addr_p0, p_addr, 4); | ||
1068 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_BASE0); | ||
1069 | |||
1070 | return NRF52_SUCCESS; | ||
1071 | } | ||
1072 | |||
1073 | nrf52_error_t radio_set_base_address_1(uint8_t const * p_addr) { | ||
1074 | if (RFD1.state != NRF52_STATE_IDLE) | ||
1075 | return NRF52_ERROR_BUSY; | ||
1076 | if (p_addr == NULL) | ||
1077 | return NRF52_ERROR_NULL; | ||
1078 | |||
1079 | memcpy(RFD1.config.address.base_addr_p1, p_addr, 4); | ||
1080 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_BASE1); | ||
1081 | |||
1082 | return NRF52_SUCCESS; | ||
1083 | } | ||
1084 | |||
1085 | nrf52_error_t radio_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes) { | ||
1086 | if (RFD1.state != NRF52_STATE_IDLE) | ||
1087 | return NRF52_ERROR_BUSY; | ||
1088 | if (p_prefixes == NULL) | ||
1089 | return NRF52_ERROR_NULL; | ||
1090 | if (num_pipes > 8) | ||
1091 | return NRF52_ERROR_INVALID_PARAM; | ||
1092 | |||
1093 | memcpy(RFD1.config.address.pipe_prefixes, p_prefixes, num_pipes); | ||
1094 | RFD1.config.address.num_pipes = num_pipes; | ||
1095 | RFD1.config.address.rx_pipes = BIT_MASK_UINT_8(num_pipes); | ||
1096 | |||
1097 | set_addresses(&RFD1, NRF52_ADDR_UPDATE_MASK_PREFIX); | ||
1098 | |||
1099 | return NRF52_SUCCESS; | ||
1100 | } | ||
1101 | |||
1102 | nrf52_error_t radio_set_prefix(uint8_t pipe, uint8_t prefix) { | ||
1103 | if (RFD1.state != NRF52_STATE_IDLE) | ||
1104 | return NRF52_ERROR_BUSY; | ||
1105 | if (pipe > 8) | ||
1106 | return NRF52_ERROR_INVALID_PARAM; | ||
1107 | |||
1108 | RFD1.config.address.pipe_prefixes[pipe] = prefix; | ||
1109 | |||
1110 | NRF_RADIO->PREFIX0 = bytewise_bit_swap(&RFD1.config.address.pipe_prefixes[0]); | ||
1111 | NRF_RADIO->PREFIX1 = bytewise_bit_swap(&RFD1.config.address.pipe_prefixes[4]); | ||
1112 | |||
1113 | return NRF52_SUCCESS; | ||
1114 | } | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.h b/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.h new file mode 100644 index 000000000..9cdea6fc2 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.h | |||
@@ -0,0 +1,256 @@ | |||
1 | /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. | ||
2 | * | ||
3 | * The information contained herein is property of Nordic Semiconductor ASA. | ||
4 | * Terms and conditions of usage are described in detail in NORDIC | ||
5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. | ||
6 | * | ||
7 | * Licensees are granted free, non-transferable use of the information. NO | ||
8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from | ||
9 | * the file. | ||
10 | * | ||
11 | * @brief Enhanced ShockBurst (ESB) is a basic protocol supporting two-way data | ||
12 | * packet communication including packet buffering, packet acknowledgment | ||
13 | * and automatic retransmission of lost packets. | ||
14 | * | ||
15 | * ported on: 25/10/2018, by andru | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef NRF52_RADIO_H_ | ||
20 | #define NRF52_RADIO_H_ | ||
21 | |||
22 | // Hard coded parameters - change if necessary | ||
23 | #ifndef NRF52_MAX_PAYLOAD_LENGTH | ||
24 | #define NRF52_MAX_PAYLOAD_LENGTH 32 /**< The max size of the payload. Valid values are 1 to 252 */ | ||
25 | #endif | ||
26 | |||
27 | #define NRF52_CRC_RESET_VALUE 0xFFFF /**< CRC reset value*/ | ||
28 | |||
29 | #define NRF52_TX_FIFO_SIZE 8 /**< The size of the transmission first in first out buffer. */ | ||
30 | #define NRF52_RX_FIFO_SIZE 8 /**< The size of the reception first in first out buffer. */ | ||
31 | |||
32 | #define NRF52_RADIO_USE_TIMER0 FALSE /**< TIMER0 will be used by the module. */ | ||
33 | #define NRF52_RADIO_USE_TIMER1 TRUE /**< TIMER1 will be used by the module. */ | ||
34 | #define NRF52_RADIO_USE_TIMER2 FALSE /**< TIMER2 will be used by the module. */ | ||
35 | #define NRF52_RADIO_USE_TIMER3 FALSE /**< TIMER3 will be used by the module. */ | ||
36 | #define NRF52_RADIO_USE_TIMER4 FALSE /**< TIMER4 will be used by the module. */ | ||
37 | |||
38 | #define NRF52_RADIO_IRQ_PRIORITY 3 /**< RADIO interrupt priority. */ | ||
39 | #define NRF52_RADIO_INTTHD_PRIORITY (NORMALPRIO+4) /**< Interrupts handle thread priority. */ | ||
40 | #define NRF52_RADIO_EVTTHD_PRIORITY (NORMALPRIO+3) /**< Events handle thread priority */ | ||
41 | |||
42 | #define NRF52_RADIO_PPI_TIMER_START 10 /**< The PPI channel used for timer start. */ | ||
43 | #define NRF52_RADIO_PPI_TIMER_STOP 11 /**< The PPI channel used for timer stop. */ | ||
44 | #define NRF52_RADIO_PPI_RX_TIMEOUT 12 /**< The PPI channel used for RX timeout. */ | ||
45 | #define NRF52_RADIO_PPI_TX_START 13 /**< The PPI channel used for starting TX. */ | ||
46 | |||
47 | |||
48 | typedef enum { | ||
49 | NRF52_SUCCESS, /* Call was successful. */ | ||
50 | NRF52_INVALID_STATE, /* Module is not initialized. */ | ||
51 | NRF52_ERROR_BUSY, /* Module was not in idle state. */ | ||
52 | NRF52_ERROR_NULL, /* Required parameter was NULL. */ | ||
53 | NRF52_ERROR_INVALID_PARAM, /* Required parameter is invalid */ | ||
54 | NRF52_ERROR_NOT_SUPPORTED, /* p_payload->noack was false while selective ack was not enabled. */ | ||
55 | NRF52_ERROR_INVALID_LENGTH, /* Payload length was invalid (zero or larger than max allowed). */ | ||
56 | } nrf52_error_t; | ||
57 | |||
58 | // Internal radio module state. | ||
59 | typedef enum { | ||
60 | NRF52_STATE_UNINIT, /**< Module not initialized. */ | ||
61 | NRF52_STATE_IDLE, /**< Module idle. */ | ||
62 | NRF52_STATE_PTX_TX, /**< Module transmitting without ack. */ | ||
63 | NRF52_STATE_PTX_TX_ACK, /**< Module transmitting with ack. */ | ||
64 | NRF52_STATE_PTX_RX_ACK, /**< Module transmitting with ack and reception of payload with the ack response. */ | ||
65 | NRF52_STATE_PRX, /**< Module receiving packets without ack. */ | ||
66 | NRF52_STATE_PRX_SEND_ACK, /**< Module transmitting ack in RX mode. */ | ||
67 | } nrf52_state_t; | ||
68 | |||
69 | /**@brief Events to indicate the last transmission/receiving status. */ | ||
70 | typedef enum { | ||
71 | NRF52_EVENT_TX_SUCCESS = 0x01, /**< Event triggered on TX success. */ | ||
72 | NRF52_EVENT_TX_FAILED = 0x02, /**< Event triggered on TX failed. */ | ||
73 | NRF52_EVENT_RX_RECEIVED = 0x04, /**< Event triggered on RX Received. */ | ||
74 | } nrf52_event_t; | ||
75 | |||
76 | // Interrupt flags | ||
77 | typedef enum { | ||
78 | NRF52_INT_TX_SUCCESS_MSK = 0x01, /**< The flag used to indicate a success since last event. */ | ||
79 | NRF52_INT_TX_FAILED_MSK = 0x02, /**< The flag used to indicate a failiure since last event. */ | ||
80 | NRF52_INT_RX_DR_MSK = 0x04, /**< The flag used to indicate a received packet since last event. */ | ||
81 | } nrf52_int_flags_t; | ||
82 | |||
83 | /**Macro to create initializer for a TX data packet. | ||
84 | * | ||
85 | * @details This macro generates an initializer. It is more efficient | ||
86 | * than setting the individual parameters dynamically. | ||
87 | * | ||
88 | * @param[in] _pipe The pipe to use for the data packet. | ||
89 | * @param[in] ... Comma separated list of character data to put in the TX buffer. | ||
90 | * Supported values are from 1 to 63 characters. | ||
91 | * | ||
92 | * @return Initializer that sets up pipe, length and the byte array for content of the TX data. | ||
93 | */ | ||
94 | #define NRF52_CREATE_PAYLOAD(_pipe, ...) \ | ||
95 | {.pipe = _pipe, .length = NUM_VA_ARGS(__VA_ARGS__), .data = {__VA_ARGS__}}; \ | ||
96 | STATIC_ASSERT(NUM_VA_ARGS(__VA_ARGS__) > 0 && NUM_VA_ARGS(__VA_ARGS__) <= 63) | ||
97 | |||
98 | /**@brief Enhanced ShockBurst protocol. */ | ||
99 | typedef enum { | ||
100 | NRF52_PROTOCOL_ESB, /*< Enhanced ShockBurst with fixed payload length. */ | ||
101 | NRF52_PROTOCOL_ESB_DPL /*< Enhanced ShockBurst with dynamic payload length. */ | ||
102 | } nrf52_protocol_t; | ||
103 | |||
104 | /**@brief Enhanced ShockBurst mode. */ | ||
105 | typedef enum { | ||
106 | NRF52_MODE_PTX, /*< Primary transmitter mode. */ | ||
107 | NRF52_MODE_PRX /*< Primary receiver mode. */ | ||
108 | } nrf52_mode_t; | ||
109 | |||
110 | /**@brief Enhanced ShockBurst bitrate mode. */ | ||
111 | typedef enum { | ||
112 | NRF52_BITRATE_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, /**< 2Mbit radio mode. */ | ||
113 | NRF52_BITRATE_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, /**< 1Mbit radio mode. */ | ||
114 | } nrf52_bitrate_t; | ||
115 | |||
116 | /**@brief Enhanced ShockBurst CRC modes. */ | ||
117 | typedef enum { | ||
118 | NRF52_CRC_16BIT = RADIO_CRCCNF_LEN_Two, /**< Use two byte CRC. */ | ||
119 | NRF52_CRC_8BIT = RADIO_CRCCNF_LEN_One, /**< Use one byte CRC. */ | ||
120 | NRF52_CRC_OFF = RADIO_CRCCNF_LEN_Disabled /**< Disable CRC. */ | ||
121 | } nrf52_crc_t; | ||
122 | |||
123 | /**@brief Enhanced ShockBurst radio transmission power modes. */ | ||
124 | typedef enum { | ||
125 | NRF52_TX_POWER_4DBM = RADIO_TXPOWER_TXPOWER_Pos4dBm, /**< 4 dBm radio transmit power. */ | ||
126 | NRF52_TX_POWER_0DBM = RADIO_TXPOWER_TXPOWER_0dBm, /**< 0 dBm radio transmit power. */ | ||
127 | NRF52_TX_POWER_NEG4DBM = RADIO_TXPOWER_TXPOWER_Neg4dBm, /**< -4 dBm radio transmit power. */ | ||
128 | NRF52_TX_POWER_NEG8DBM = RADIO_TXPOWER_TXPOWER_Neg8dBm, /**< -8 dBm radio transmit power. */ | ||
129 | NRF52_TX_POWER_NEG12DBM = RADIO_TXPOWER_TXPOWER_Neg12dBm, /**< -12 dBm radio transmit power. */ | ||
130 | NRF52_TX_POWER_NEG16DBM = RADIO_TXPOWER_TXPOWER_Neg16dBm, /**< -16 dBm radio transmit power. */ | ||
131 | NRF52_TX_POWER_NEG20DBM = RADIO_TXPOWER_TXPOWER_Neg20dBm, /**< -20 dBm radio transmit power. */ | ||
132 | NRF52_TX_POWER_NEG30DBM = RADIO_TXPOWER_TXPOWER_Neg30dBm /**< -30 dBm radio transmit power. */ | ||
133 | } nrf52_tx_power_t; | ||
134 | |||
135 | /**@brief Enhanced ShockBurst transmission modes. */ | ||
136 | typedef enum { | ||
137 | NRF52_TXMODE_AUTO, /*< Automatic TX mode - When the TX fifo is non-empty and the radio is idle packets will be sent automatically. */ | ||
138 | NRF52_TXMODE_MANUAL, /*< Manual TX mode - Packets will not be sent until radio_start_tx() is called. Can be used to ensure consistent packet timing. */ | ||
139 | NRF52_TXMODE_MANUAL_START /*< Manual start TX mode - Packets will not be sent until radio_start_tx() is called, but transmission will continue automatically until the TX fifo is empty. */ | ||
140 | } nrf52_tx_mode_t; | ||
141 | |||
142 | /**@brief Enhanced ShockBurst addresses. | ||
143 | * | ||
144 | * @details The module is able to transmit packets with the TX address stored in tx_address. | ||
145 | The module can also receive packets from peers with up to eight different tx_addresses | ||
146 | stored in esb_addr_p0 - esb_addr_p7. esb_addr_p0 can have 5 arbitrary bytes | ||
147 | independent of the other addresses. esb_addr_p1 - esb_addr_p7 will share the | ||
148 | same four byte base address found in the last four bytes of esb_addr_p1. | ||
149 | They have an independent prefix byte found in esb_addr_p1[0] and esb_addr_p2 - | ||
150 | esb_addr_p7. | ||
151 | */ | ||
152 | typedef struct { | ||
153 | uint8_t base_addr_p0[4]; /**< Base address for pipe 0 encoded in big endian. */ | ||
154 | uint8_t base_addr_p1[4]; /**< Base address for pipe 1-7 encoded in big endian. */ | ||
155 | uint8_t pipe_prefixes[8]; /**< Address prefix for pipe P0 to P7. */ | ||
156 | uint8_t num_pipes; /**< Number of pipes available. */ | ||
157 | uint8_t addr_length; /**< Length of address including prefix */ | ||
158 | uint8_t rx_pipes; /**< Bitfield for enabled RX pipes. */ | ||
159 | uint8_t rf_channel; /**< Which channel is to be used. Must be in range 0 and 125 to be valid. */ | ||
160 | } nrf52_address_t; | ||
161 | |||
162 | /**@brief Enhanced ShockBurst payload. | ||
163 | * | ||
164 | * @note The payload is used both for transmission and receive with ack and payload. | ||
165 | */ | ||
166 | typedef struct | ||
167 | { | ||
168 | uint8_t length; /**< Length of the packet. Should be equal or less than NRF_ESB_MAX_PAYLOAD_LENGTH. */ | ||
169 | uint8_t pipe; /**< Pipe used for this payload. */ | ||
170 | int8_t rssi; /**< RSSI for received packet. */ | ||
171 | uint8_t noack; /**< Flag indicating that this packet will not be acknowledged. */ | ||
172 | uint8_t pid; /**< PID assigned during communication. */ | ||
173 | uint8_t data[NRF52_MAX_PAYLOAD_LENGTH]; /**< The payload data. */ | ||
174 | } nrf52_payload_t; | ||
175 | |||
176 | /**@brief Retransmit attempts delay and counter. */ | ||
177 | typedef struct { | ||
178 | uint16_t delay; /**< The delay between each retransmission of unacked packets. */ | ||
179 | uint16_t count; /**< The number of retransmissions attempts before transmission fail. */ | ||
180 | } nrf52_retransmit_t; | ||
181 | |||
182 | /**@brief Main nrf_esb configuration struct. */ | ||
183 | typedef struct { | ||
184 | nrf52_protocol_t protocol; /**< Enhanced ShockBurst protocol. */ | ||
185 | nrf52_mode_t mode; /**< Enhanced ShockBurst default RX or TX mode. */ | ||
186 | |||
187 | // General RF parameters | ||
188 | nrf52_bitrate_t bitrate; /**< Enhanced ShockBurst bitrate mode. */ | ||
189 | nrf52_crc_t crc; /**< Enhanced ShockBurst CRC mode. */ | ||
190 | nrf52_tx_power_t tx_power; /**< Enhanced ShockBurst radio transmission power mode.*/ | ||
191 | |||
192 | // Control settings | ||
193 | nrf52_tx_mode_t tx_mode; /**< Enhanced ShockBurst transmit mode. */ | ||
194 | |||
195 | bool selective_auto_ack; /**< Enable or disable selective auto acknowledgement. */ | ||
196 | |||
197 | nrf52_retransmit_t retransmit; /**< Packet retransmit parameters */ | ||
198 | |||
199 | uint8_t payload_length; /**< Enhanced ShockBurst static payload length */ | ||
200 | |||
201 | nrf52_address_t address; /**< Address parameters structure */ | ||
202 | } nrf52_config_t; | ||
203 | |||
204 | typedef struct { | ||
205 | /** | ||
206 | * @brief NRF52 radio peripheral. | ||
207 | */ | ||
208 | NRF_RADIO_Type *radio; | ||
209 | /** | ||
210 | * @brief NRF52 timer peripheral. | ||
211 | */ | ||
212 | NRF_TIMER_Type *timer; | ||
213 | /** | ||
214 | * @brief Driver state. | ||
215 | */ | ||
216 | nrf52_state_t state; | ||
217 | /** | ||
218 | * @brief RF parameters. | ||
219 | */ | ||
220 | nrf52_config_t config; | ||
221 | /** | ||
222 | * @brief Interrupts flag. | ||
223 | */ | ||
224 | nrf52_int_flags_t flags; | ||
225 | /** | ||
226 | * @brief TX attempt number. | ||
227 | */ | ||
228 | uint16_t tx_attempt; | ||
229 | /** | ||
230 | * @brief TX retransmits remaining. | ||
231 | */ | ||
232 | uint16_t tx_remaining; | ||
233 | /** | ||
234 | * @brief Radio events source. | ||
235 | */ | ||
236 | event_source_t eventsrc; | ||
237 | } RFDriver; | ||
238 | |||
239 | extern RFDriver RFD1; | ||
240 | |||
241 | nrf52_error_t radio_init(nrf52_config_t const *config); | ||
242 | nrf52_error_t radio_disable(void); | ||
243 | nrf52_error_t radio_write_payload(nrf52_payload_t const * p_payload); | ||
244 | nrf52_error_t radio_read_rx_payload(nrf52_payload_t * p_payload); | ||
245 | nrf52_error_t radio_start_tx(void); | ||
246 | nrf52_error_t radio_start_rx(void); | ||
247 | nrf52_error_t radio_stop_rx(void); | ||
248 | nrf52_error_t radio_flush_tx(void); | ||
249 | nrf52_error_t radio_flush_rx(void); | ||
250 | nrf52_error_t radio_pop_tx(void); | ||
251 | nrf52_error_t radio_set_base_address_0(uint8_t const * p_addr); | ||
252 | nrf52_error_t radio_set_base_address_1(uint8_t const * p_addr); | ||
253 | nrf52_error_t radio_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes); | ||
254 | nrf52_error_t radio_set_prefix(uint8_t pipe, uint8_t prefix); | ||
255 | |||
256 | #endif /* NRF52_RADIO_H_ */ | ||
diff --git a/lib/chibios-contrib/os/various/devices_lib/sensors/hdc1000.c b/lib/chibios-contrib/os/various/devices_lib/sensors/hdc1000.c new file mode 100644 index 000000000..39e47ecb9 --- /dev/null +++ b/lib/chibios-contrib/os/various/devices_lib/sensors/hdc1000.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | HDC100x for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file HDC1000.c | ||
19 | * @brief HDC1000 interface module code. | ||
20 | * | ||
21 | * @addtogroup hdc1000 | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #define I2C_HELPERS_AUTOMATIC_DRV TRUE | ||
26 | |||
27 | #include "hal.h" | ||
28 | #include "i2c_helpers.h" | ||
29 | #include "hdc1000.h" | ||