aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/various
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/os/various')
-rw-r--r--lib/chibios-contrib/os/various/bitmap.c158
-rw-r--r--lib/chibios-contrib/os/various/bitmap.h77
-rw-r--r--lib/chibios-contrib/os/various/bmp.mk57
-rw-r--r--lib/chibios-contrib/os/various/bswap.h201
-rw-r--r--lib/chibios-contrib/os/various/crcsw.c338
-rw-r--r--lib/chibios-contrib/os/various/crcsw.h215
-rw-r--r--lib/chibios-contrib/os/various/dbgtrace.h41
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.c418
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/lcd/ili9341.h593
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.c123
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/l3gd20.h243
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.c151
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lis3mdl.h258
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.c205
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lsm303dlhc.h352
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.c184
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/mems/lsm6ds0.h482
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/others/max7219.c94
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/others/max7219.h187
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.c440
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/rf/nrf24l01.h575
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.c1114
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/rf/nrf52_radio.h256
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/hdc1000.c265
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/hdc1000.h240
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.c207
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/mcp9808.h204
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/sensor.h81
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/tsl2561.c386
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/tsl2561.h241
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.c272
-rw-r--r--lib/chibios-contrib/os/various/devices_lib/sensors/tsl2591.h238
-rw-r--r--lib/chibios-contrib/os/various/fatfs_bindings/fatfs.mk11
-rw-r--r--lib/chibios-contrib/os/various/fatfs_bindings/fatfs_devices.h41
-rw-r--r--lib/chibios-contrib/os/various/fatfs_bindings/fatfs_diskio.c340
-rw-r--r--lib/chibios-contrib/os/various/fault_handlers/fault_handlers.h22
-rw-r--r--lib/chibios-contrib/os/various/gdb.mk13
-rw-r--r--lib/chibios-contrib/os/various/i2c_helpers.h283
-rw-r--r--lib/chibios-contrib/os/various/jlink.mk37
-rw-r--r--lib/chibios-contrib/os/various/lib_scsi.c548
-rw-r--r--lib/chibios-contrib/os/various/lib_scsi.h293
-rw-r--r--lib/chibios-contrib/os/various/median.c129
-rw-r--r--lib/chibios-contrib/os/various/median.h42
-rw-r--r--lib/chibios-contrib/os/various/memtest.cpp310
-rw-r--r--lib/chibios-contrib/os/various/memtest.h90
-rw-r--r--lib/chibios-contrib/os/various/pid.c194
-rw-r--r--lib/chibios-contrib/os/various/pid.h78
-rw-r--r--lib/chibios-contrib/os/various/ramdisk.c220
-rw-r--r--lib/chibios-contrib/os/various/ramdisk.h86
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/RTT/SEGGER_RTT_streams.c116
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/RTT/SEGGER_RTT_streams.h107
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/SYSTEMVIEW/SEGGER_SYSVIEW_ChibiOS.c114
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/SYSTEMVIEW/SEGGER_SYSVIEW_ChibiOS.h286
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/SYSTEMVIEW/SYSVIEW_ChibiOS.txt8
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/example_configurations/SEGGER_RTT_Conf.h123
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/example_configurations/SEGGER_SYSVIEW_Conf.h174
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/segger_rtt.mk14
-rw-r--r--lib/chibios-contrib/os/various/segger_bindings/segger_systemview.mk13
-rw-r--r--lib/chibios-contrib/os/various/tinyusb_bindings/tinyusb.mk9
-rw-r--r--lib/chibios-contrib/os/various/tinyusb_bindings/tusb_os_custom.h195
-rw-r--r--lib/chibios-contrib/os/various/tribuf.c214
-rw-r--r--lib/chibios-contrib/os/various/tribuf.h225
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 */
57static 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 */
68static 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 */
81void 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 */
100void 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 */
113void 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 */
126void 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 */
141bitmap_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 */
155size_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
44typedef unsigned int bitmap_word_t;
45
46/**
47 * @brief Type of a event timer structure.
48 */
49typedef 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
63extern "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
14GDB ?= arm-none-eabi-gdb # Path to the arm-none-eabi-gdb binary
15GDB_PROGRAM ?= $(BUILDDIR)/$(PROJECT).elf # Path to the elf binary
16GDB_BREAK ?= main # Function to break at when starting the debugger
17
18BMP_GDB ?= /dev/ttyBmpGdb # Device file for the Black Magic GDB devic
19
20all: $(GDB_PROGRAM)
21
22flash: $(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
31debug: $(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
42debug-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)
21extern "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
108static inline uint16_t bswap_16(const uint16_t x)
109 __attribute__ ((warn_unused_result))
110 __attribute__ ((const))
111 __attribute__ ((always_inline));
112
113static 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
128static inline uint32_t bswap_32(const uint32_t x)
129 __attribute__ ((warn_unused_result))
130 __attribute__ ((const))
131 __attribute__ ((always_inline));
132
133
134static 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
152static inline uint64_t bswap_64(const uint64_t x)
153 __attribute__ ((warn_unused_result))
154 __attribute__ ((const))
155 __attribute__ ((always_inline));
156
157
158static 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
182static inline void bswap_n(void* const data, uint8_t len)
183 __attribute__ ((nonnull (1)));
184
185static 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__)
42static 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__)
111static 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__)
153CRCDriver CRCD1;
154#endif
155
156#if CRCSW_CRC32_TABLE || defined(__DOXYGEN__)
157const 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__)
169const 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)
189static 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 */
220void 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 */
232void 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 */
258void 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 */
269void 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 */
282uint32_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 */
81typedef struct CRCDriver CRCDriver;
82
83/**
84 * @brief Driver configuration structure.
85 */
86typedef 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 */
122struct 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
189extern CRCDriver CRCD1;
190
191#if CRCSW_CRC32_TABLE
192extern const CRCConfig crcsw_crc32_config;
193#endif
194
195#if CRCSW_CRC16_TABLE
196extern const CRCConfig crcsw_crc16_config;
197#endif
198
199#ifdef __cplusplus
200extern "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
20extern 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.*/
70ILI9341Driver 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 */
91void 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 */
115void 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 */
138void 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 */
162void 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 */
187void 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 */
204void 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 */
227void 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 */
246void 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 */
264void 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 */
280void 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 */
299void 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 */
315void 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 */
334void 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 */
354uint8_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 */
377void 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 */
401void 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.*/
188typedef struct ILI9341Config ILI9341Config;
189typedef enum ili9341state_t ili9341state_t;
190typedef struct ILI9341Driver ILI9341Driver;
191
192/**
193 * @brief ILI9341 driver configuration.
194 */
195typedef 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 */
206typedef 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 */
216typedef 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
239typedef 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
249typedef 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
278typedef 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
291typedef 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
304typedef 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
314typedef 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
322typedef 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
335typedef 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
344typedef 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
351typedef 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
361typedef 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
371typedef 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
381typedef 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
393typedef 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
401typedef 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
414typedef 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
422typedef 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
432typedef 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
440typedef 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
448typedef 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
455typedef 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
462typedef 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
474typedef 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
486typedef 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
494typedef 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
502typedef 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
509typedef 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
518typedef 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
532typedef 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
560extern ILI9341Driver ILI9341D1;
561
562#ifdef __cplusplus
563extern "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 */
70uint8_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
80void 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 */
127typedef 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 */
147typedef 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 */
155typedef 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 */
164typedef 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 */
178typedef 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 */
186typedef 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 */
195typedef 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
231extern "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 */
72uint8_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 */
109void 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 */
108typedef 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 */
116typedef 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 */
126typedef 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 */
140typedef 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 */
150typedef 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 */
158typedef 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 */
168typedef 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 */
178typedef 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 */
186typedef 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 */
197typedef 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
245extern "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 */
73uint8_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 */
112void 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 */
159typedef 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 */
176typedef 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 */
185typedef 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 */
196typedef 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 */
210typedef 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 */
219typedef 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 */
228typedef 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 */
237typedef 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 */
274typedef 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 */
290typedef 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 */
305typedef 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 */
315typedef 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
339extern "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 */
72uint8_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 */
109void 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 */
144typedef 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 */
152typedef 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 */
161typedef 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 */
176typedef 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 */
186typedef 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 */
200typedef 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 */
213typedef 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 */
223typedef 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 */
234typedef 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 */
246typedef 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 */
255typedef 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 */
308typedef 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 */
331typedef 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 */
340typedef 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 */
348typedef 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 */
356typedef 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 */
364typedef 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 */
382typedef 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 */
396typedef 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 */
406typedef 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 */
413typedef 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
469extern "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 */
70void 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 */
112typedef 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 */
120typedef 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 */
135typedef 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 */
157typedef 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
177extern "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 */
71NRF24L01_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 */
92NRF24L01_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 */
115NRF24L01_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 */
177NRF24L01_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 */
247NRF24L01_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 */
274NRF24L01_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 */
299NRF24L01_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 */
320NRF24L01_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 */
349NRF24L01_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 */
371NRF24L01_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 */
396NRF24L01_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 */
424NRF24L01_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 */
298typedef 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 */
308typedef 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 */
331typedef 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 */
359typedef uint8_t NRF24L01_RF_CH_t;
360
361/**
362 * @brief RF Transceiver Air Data Rate
363 */
364typedef 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 */
373typedef 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 */
387typedef 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 */
398typedef 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 */
406typedef 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 */
416typedef 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 */
426typedef 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 */
435typedef 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 */
518typedef 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
546extern "C" {
547#endif
548NRF24L01_status_t nrf24l01GetStatus(SPIDriver *spip);
549NRF24L01_status_t nrf24l01ReadRegister(SPIDriver *spip, uint8_t reg,
550 uint8_t* pvalue);
551NRF24L01_status_t nrf24l01WriteRegister(SPIDriver *spip, uint8_t reg,
552 uint8_t value);
553NRF24L01_status_t nrf24l01WriteAddress(SPIDriver *spip, uint8_t reg,
554 uint8_t *pvalue, uint8_t addlen);
555NRF24L01_status_t nrf24l01GetRxPl(SPIDriver *spip, uint8_t paylen,
556 uint8_t* rxbuf);
557NRF24L01_status_t nrf24l01WriteTxPl(SPIDriver *spip, uint8_t paylen,
558 uint8_t* txbuf);
559NRF24L01_status_t nrf24l01FlushTx(SPIDriver *spip);
560NRF24L01_status_t nrf24l01FlushRx(SPIDriver *spip);
561#if NRF24L01_USE_FEATURE || defined(__DOXYGEN__)
562NRF24L01_status_t nrf24l01Activate(SPIDriver *spip);
563NRF24L01_status_t nrf24l01ReadRxPlWid(SPIDriver *spip, uint8_t* ppaylen);
564NRF24L01_status_t nrf24l01WriteAckPl(SPIDriver *spip, uint8_t ppp, uint8_t paylen,
565 uint8_t* payload);
566NRF24L01_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) \
99do \
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.
111typedef 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.
119typedef 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.
128typedef 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;
138static void (*set_rf_payload_format)(RFDriver *rfp, uint32_t payload_length) = NULL;
139
140// The following functions are assigned to the function pointers above.
141static void on_radio_disabled_tx_noack(RFDriver *rfp);
142static void on_radio_disabled_tx(RFDriver *rfp);
143static void on_radio_disabled_tx_wait_for_ack(RFDriver *rfp);
144static void on_radio_disabled_rx(RFDriver *rfp);
145static void on_radio_disabled_rx_ack(RFDriver *rfp);
146
147static volatile uint16_t wait_for_ack_timeout_us;
148static nrf52_payload_t * p_current_payload;
149
150// TX FIFO
151static nrf52_payload_t tx_fifo_payload[NRF52_TX_FIFO_SIZE];
152static nrf52_payload_tx_fifo_t tx_fifo;
153
154// RX FIFO
155static nrf52_payload_t rx_fifo_payload[NRF52_RX_FIFO_SIZE];
156static nrf52_payload_rx_fifo_t rx_fifo;
157
158// Payload buffers
159static uint8_t tx_payload_buffer[NRF52_MAX_PAYLOAD_LENGTH + 2];
160static uint8_t rx_payload_buffer[NRF52_MAX_PAYLOAD_LENGTH + 2];
161
162static uint8_t pids[NRF52_PIPE_COUNT];
163static pipe_info_t rx_pipe_info[NRF52_PIPE_COUNT];
164
165 // disable and events semaphores.
166static binary_semaphore_t disable_sem;
167static binary_semaphore_t events_sem;
168
169RFDriver RFD1;
170
171// Function to do bytewise bit-swap on a unsigned 32 bit value
172static 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
179static 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
183static thread_t *rfEvtThread_p;
184static THD_WORKING_AREA(waRFEvtThread, 128);
185static 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
209static thread_t *rfIntThread_p;
210static THD_WORKING_AREA(waRFIntThread, 128);
211static 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
241static 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 */
260OSAL_IRQ_HANDLER(Vector44) {
261
262 OSAL_IRQ_PROLOGUE();
263
264 serve_radio_interrupt(&RFD1);
265
266 OSAL_IRQ_EPILOGUE();
267}
268
269static 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
288static 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 */
304static 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
323static void set_tx_power(RFDriver *rfp) {
324 NRF_RADIO->TXPOWER = rfp->config.tx_power << RADIO_TXPOWER_TXPOWER_Pos;
325}
326
327static 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
340static 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
351static 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
366static 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
380static 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
388static 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
398static 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
410static 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 */
435static 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
469static 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
476static 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
542static 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
556static 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
588static 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
647static 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
667static 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
766static 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
775nrf52_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//
817nrf52_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
882nrf52_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
922nrf52_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
951nrf52_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
964nrf52_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
995nrf52_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
1011nrf52_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
1026nrf52_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
1044nrf52_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
1061nrf52_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
1073nrf52_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
1085nrf52_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
1102nrf52_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
48typedef 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.
59typedef 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. */
70typedef 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
77typedef 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. */
99typedef 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. */
105typedef 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. */
111typedef 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. */
117typedef 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. */
124typedef 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. */
136typedef 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*/
152typedef 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*/
166typedef 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. */
177typedef 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. */
183typedef 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
204typedef 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
239extern RFDriver RFD1;
240
241nrf52_error_t radio_init(nrf52_config_t const *config);
242nrf52_error_t radio_disable(void);
243nrf52_error_t radio_write_payload(nrf52_payload_t const * p_payload);
244nrf52_error_t radio_read_rx_payload(nrf52_payload_t * p_payload);
245nrf52_error_t radio_start_tx(void);
246nrf52_error_t radio_start_rx(void);
247nrf52_error_t radio_stop_rx(void);
248nrf52_error_t radio_flush_tx(void);
249nrf52_error_t radio_flush_rx(void);
250nrf52_error_t radio_pop_tx(void);
251nrf52_error_t radio_set_base_address_0(uint8_t const * p_addr);
252nrf52_error_t radio_set_base_address_1(uint8_t const * p_addr);
253nrf52_error_t radio_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes);
254nrf52_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"