aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/boards/NRF51-DK/board.h30
-rw-r--r--os/hal/boards/PJRC_TEENSY_LC/board.c1
-rw-r--r--os/hal/boards/WVSHARE_BLE400/board.h30
-rw-r--r--os/hal/hal.mk2
-rw-r--r--os/hal/include/hal_community.h50
-rw-r--r--os/hal/include/hal_eeprom.h6
-rw-r--r--os/hal/include/hal_onewire.h4
-rw-r--r--os/hal/include/hal_qei.h130
-rw-r--r--os/hal/include/hal_timcap.h6
-rw-r--r--os/hal/include/hal_usb_hid.h510
-rw-r--r--os/hal/include/hal_usbh.h5
-rw-r--r--os/hal/ports/KINETIS/LLD/hal_i2c_lld.h4
-rw-r--r--os/hal/ports/KINETIS/LLD/hal_pal_lld.c4
-rw-r--r--os/hal/ports/KINETIS/LLD/hal_usb_lld.c2
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_gpt_lld.h8
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_i2c_lld.h14
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_pal_lld.h2
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_pwm_lld.c77
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_pwm_lld.h71
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_rng_lld.h6
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_serial_lld.h7
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_spi_lld.h14
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_st_lld.h6
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c293
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h347
-rw-r--r--os/hal/ports/STM32/STM32F0xx/platform.mk1
-rw-r--r--os/hal/ports/STM32/STM32F1xx/platform.mk1
-rw-r--r--os/hal/ports/STM32/STM32F3xx/platform.mk3
-rw-r--r--os/hal/ports/STM32/STM32F4xx/platform.mk1
-rw-r--r--os/hal/src/hal_community.c4
-rw-r--r--os/hal/src/hal_onewire.c20
-rw-r--r--os/hal/src/hal_qei.c214
-rw-r--r--os/hal/src/hal_usb_hid.c581
33 files changed, 2387 insertions, 67 deletions
diff --git a/os/hal/boards/NRF51-DK/board.h b/os/hal/boards/NRF51-DK/board.h
index e47240b..67e1724 100644
--- a/os/hal/boards/NRF51-DK/board.h
+++ b/os/hal/boards/NRF51-DK/board.h
@@ -44,6 +44,16 @@
#define SPI_SS 24
#define I2C_SCL 7
#define I2C_SDA 30
+#define AIN0 26
+#define AIN1 27
+#define AIN2 1
+#define AIN3 2
+#define AIN4 3
+#define AIN5 4
+#define AIN6 5
+#define AIN7 6
+#define AREF0 0
+#define AREF1 6
/*
* IO pins assignments.
@@ -72,6 +82,16 @@
#define IOPORT1_A3 4U
#define IOPORT1_A4 5U
#define IOPORT1_A5 6U
+#define IOPORT1_AIN0 26U
+#define IOPORT1_AIN1 27U
+#define IOPORT1_AIN2 1U
+#define IOPORT1_AIN3 2U
+#define IOPORT1_AIN4 3U
+#define IOPORT1_AIN5 4U
+#define IOPORT1_AIN6 5U
+#define IOPORT1_AIN7 6U
+#define IOPORT1_AREF0 0U
+#define IOPORT1_AREF1 6U
/*
* IO lines assignments.
@@ -100,6 +120,16 @@
#define LINE_A3 PAL_LINE(IOPORT1, IOPORT1_A3)
#define LINE_A4 PAL_LINE(IOPORT1, IOPORT1_A4)
#define LINE_A5 PAL_LINE(IOPORT1, IOPORT1_A5)
+#define LINE_AIN0 PAL_LINE(IOPORT1, IOPORT1_AIN0)
+#define LINE_AIN1 PAL_LINE(IOPORT1, IOPORT1_AIN1)
+#define LINE_AIN2 PAL_LINE(IOPORT1, IOPORT1_AIN2)
+#define LINE_AIN3 PAL_LINE(IOPORT1, IOPORT1_AIN3)
+#define LINE_AIN4 PAL_LINE(IOPORT1, IOPORT1_AIN4)
+#define LINE_AIN5 PAL_LINE(IOPORT1, IOPORT1_AIN5)
+#define LINE_AIN6 PAL_LINE(IOPORT1, IOPORT1_AIN6)
+#define LINE_AIN7 PAL_LINE(IOPORT1, IOPORT1_AIN7)
+#define LINE_AREF0 PAL_LINE(IOPORT1, IOPORT1_AREF0)
+#define LINE_AREF1 PAL_LINE(IOPORT1, IOPORT1_AREF1)
#if !defined(_FROM_ASM_)
diff --git a/os/hal/boards/PJRC_TEENSY_LC/board.c b/os/hal/boards/PJRC_TEENSY_LC/board.c
index 31c3ca4..ab321b8 100644
--- a/os/hal/boards/PJRC_TEENSY_LC/board.c
+++ b/os/hal/boards/PJRC_TEENSY_LC/board.c
@@ -14,7 +14,6 @@
limitations under the License.
*/
-#include "ch.h"
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
diff --git a/os/hal/boards/WVSHARE_BLE400/board.h b/os/hal/boards/WVSHARE_BLE400/board.h
index fd52467..5a4e8f0 100644
--- a/os/hal/boards/WVSHARE_BLE400/board.h
+++ b/os/hal/boards/WVSHARE_BLE400/board.h
@@ -42,6 +42,16 @@
#define SPI_SS 30
#define I2C_SCL 1
#define I2C_SDA 0
+#define AIN0 26
+#define AIN1 27
+#define AIN2 1
+#define AIN3 2
+#define AIN4 3
+#define AIN5 4
+#define AIN6 5
+#define AIN7 6
+#define AREF0 0
+#define AREF1 6
/*
* IO pins assignments.
@@ -63,6 +73,16 @@
#define IOPORT1_SPI_SS 30U
#define IOPORT1_I2C_SCL 1U
#define IOPORT1_I2C_SDA 0U
+#define IOPORT1_AIN0 26U
+#define IOPORT1_AIN1 27U
+#define IOPORT1_AIN2 1U
+#define IOPORT1_AIN3 2U
+#define IOPORT1_AIN4 3U
+#define IOPORT1_AIN5 4U
+#define IOPORT1_AIN6 5U
+#define IOPORT1_AIN7 6U
+#define IOPORT1_AREF0 0U
+#define IOPORT1_AREF1 6U
/*
* IO lines assignments.
@@ -84,6 +104,16 @@
#define LINE_SPI_SS PAL_LINE(IOPORT1, IOPORT1_SPI_SS)
#define LINE_I2C_SCL PAL_LINE(IOPORT1, IOPORT1_I2C_SCL)
#define LINE_I2C_SDA PAL_LINE(IOPORT1, IOPORT1_I2C_SDA)
+#define LINE_AIN0 PAL_LINE(IOPORT1, IOPORT1_AIN0)
+#define LINE_AIN1 PAL_LINE(IOPORT1, IOPORT1_AIN1)
+#define LINE_AIN2 PAL_LINE(IOPORT1, IOPORT1_AIN2)
+#define LINE_AIN3 PAL_LINE(IOPORT1, IOPORT1_AIN3)
+#define LINE_AIN4 PAL_LINE(IOPORT1, IOPORT1_AIN4)
+#define LINE_AIN5 PAL_LINE(IOPORT1, IOPORT1_AIN5)
+#define LINE_AIN6 PAL_LINE(IOPORT1, IOPORT1_AIN6)
+#define LINE_AIN7 PAL_LINE(IOPORT1, IOPORT1_AIN7)
+#define LINE_AREF0 PAL_LINE(IOPORT1, IOPORT1_AREF0)
+#define LINE_AREF1 PAL_LINE(IOPORT1, IOPORT1_AREF1)
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
diff --git a/os/hal/hal.mk b/os/hal/hal.mk
index 54414a0..ce74620 100644
--- a/os/hal/hal.mk
+++ b/os/hal/hal.mk
@@ -17,5 +17,7 @@ HALSRC += ${CHIBIOS_CONTRIB}/os/hal/src/hal_community.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_ee25xx.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_eeprom.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_timcap.c \
+ ${CHIBIOS_CONTRIB}/os/hal/src/hal_qei.c \
+ ${CHIBIOS_CONTRIB}/os/hal/src/hal_usb_hid.c
HALINC += ${CHIBIOS_CONTRIB}/os/hal/include
diff --git a/os/hal/include/hal_community.h b/os/hal/include/hal_community.h
index 6420964..1518c7e 100644
--- a/os/hal/include/hal_community.h
+++ b/os/hal/include/hal_community.h
@@ -22,8 +22,50 @@
* @{
*/
-#ifndef _HAL_COMMUNITY_H_
-#define _HAL_COMMUNITY_H_
+#ifndef HAL_COMMUNITY_H
+#define HAL_COMMUNITY_H
+
+
+/* Error checks on the configuration header file.*/
+#if !defined(HAL_USE_CRC)
+#define HAL_USE_CRC FALSE
+#endif
+
+#if !defined(HAL_USE_EEPROM)
+#define HAL_USE_EEPROM FALSE
+#endif
+
+#if !defined(HAL_USE_EICU)
+#define HAL_USE_EICU FALSE
+#endif
+
+#if !defined(HAL_USE_NAND)
+#define HAL_USE_NAND FALSE
+#endif
+
+#if !defined(HAL_USE_ONEWIRE)
+#define HAL_USE_ONEWIRE FALSE
+#endif
+
+#if !defined(HAL_USE_QEI)
+#define HAL_USE_QEI FALSE
+#endif
+
+#if !defined(HAL_USE_RNG)
+#define HAL_USE_RNG FALSE
+#endif
+
+#if !defined(HAL_USE_TIMCAP)
+#define HAL_USE_TIMCAP FALSE
+#endif
+
+#if !defined(HAL_USE_USBH)
+#define HAL_USE_USBH FALSE
+#endif
+
+#if !defined(HAL_USE_USB_HID)
+#define HAL_USE_USB_HID FALSE
+#endif
/* Abstract interfaces.*/
@@ -35,11 +77,13 @@
#include "hal_rng.h"
#include "hal_usbh.h"
#include "hal_timcap.h"
+#include "hal_qei.h"
/* Complex drivers.*/
#include "hal_onewire.h"
#include "hal_crc.h"
#include "hal_eeprom.h"
+#include "hal_usb_hid.h"
/*===========================================================================*/
/* Driver constants. */
@@ -73,6 +117,6 @@ extern "C" {
}
#endif
-#endif /* _HAL_COMMUNITY_H_ */
+#endif /* HAL_COMMUNITY_H */
/** @} */
diff --git a/os/hal/include/hal_eeprom.h b/os/hal/include/hal_eeprom.h
index c3ac3c6..cd05e14 100644
--- a/os/hal/include/hal_eeprom.h
+++ b/os/hal/include/hal_eeprom.h
@@ -32,10 +32,6 @@
#include "ch.h"
#include "hal.h"
-#ifndef HAL_USE_EEPROM
-#define HAL_USE_EEPROM FALSE
-#endif
-
#ifndef EEPROM_USE_EE25XX
#define EEPROM_USE_EE25XX FALSE
#endif
@@ -44,7 +40,7 @@
#define EEPROM_USE_EE24XX FALSE
#endif
-#if HAL_USE_EEPROM
+#if (HAL_USE_EEPROM == TRUE) || defined(__DOXYGEN__)
#if EEPROM_USE_EE25XX && EEPROM_USE_EE24XX
#define EEPROM_TABLE_SIZE 2
diff --git a/os/hal/include/hal_onewire.h b/os/hal/include/hal_onewire.h
index 2d27f48..9fb5be2 100644
--- a/os/hal/include/hal_onewire.h
+++ b/os/hal/include/hal_onewire.h
@@ -342,8 +342,8 @@ extern "C" {
uint8_t *result, size_t max_rom_cnt);
#endif /* ONEWIRE_USE_SEARCH_ROM */
#if ONEWIRE_SYNTH_SEARCH_TEST
- void _synth_ow_write_bit(onewireDriver *owp, uint8_t bit);
- uint_fast8_t _synth_ow_read_bit(void);
+ void _synth_ow_write_bit(onewireDriver *owp, ioline_t bit);
+ ioline_t _synth_ow_read_bit(void);
void synthSearchRomTest(onewireDriver *owp);
#endif /* ONEWIRE_SYNTH_SEARCH_TEST */
#ifdef __cplusplus
diff --git a/os/hal/include/hal_qei.h b/os/hal/include/hal_qei.h
new file mode 100644
index 0000000..92f03fc
--- /dev/null
+++ b/os/hal/include/hal_qei.h
@@ -0,0 +1,130 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Martino Migliavacca
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_qei.h
+ * @brief QEI Driver macros and structures.
+ *
+ * @addtogroup QEI
+ * @{
+ */
+
+#ifndef HAL_QEI_H
+#define HAL_QEI_H
+
+#if (HAL_USE_QEI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ QEI_UNINIT = 0, /**< Not initialized. */
+ QEI_STOP = 1, /**< Stopped. */
+ QEI_READY = 2, /**< Ready. */
+ QEI_ACTIVE = 3, /**< Active. */
+} qeistate_t;
+
+/**
+ * @brief Type of a structure representing an QEI driver.
+ */
+typedef struct QEIDriver QEIDriver;
+
+/**
+ * @brief QEI notification callback type.
+ *
+ * @param[in] qeip pointer to a @p QEIDriver object
+ */
+typedef void (*qeicallback_t)(QEIDriver *qeip);
+
+#include "hal_qei_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Enables the input capture.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @iclass
+ */
+#define qeiEnableI(qeip) qei_lld_enable(qeip)
+
+/**
+ * @brief Disables the input capture.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @iclass
+ */
+#define qeiDisableI(qeip) qei_lld_disable(qeip)
+
+/**
+ * @brief Returns the counter value.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @return The current counter value.
+ *
+ * @iclass
+ */
+#define qeiGetCountI(qeip) qei_lld_get_count(qeip)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void qeiInit(void);
+ void qeiObjectInit(QEIDriver *qeip);
+ void qeiStart(QEIDriver *qeip, const QEIConfig *config);
+ void qeiStop(QEIDriver *qeip);
+ void qeiEnable(QEIDriver *qeip);
+ void qeiDisable(QEIDriver *qeip);
+ qeicnt_t qeiGetCount(QEIDriver *qeip);
+ qeidelta_t qeiUpdate(QEIDriver *qeip);
+ qeidelta_t qeiUpdateI(QEIDriver *qeip);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_QEI == TRUE */
+
+#endif /* HAL_QEI_H */
+
+/** @} */
diff --git a/os/hal/include/hal_timcap.h b/os/hal/include/hal_timcap.h
index 9629564..bd43dd1 100644
--- a/os/hal/include/hal_timcap.h
+++ b/os/hal/include/hal_timcap.h
@@ -32,11 +32,7 @@
#include "ch.h"
#include "hal.h"
-#ifndef HAL_USE_TIMCAP
-#define HAL_USE_TIMCAP FALSE
-#endif
-
-#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
+#if (HAL_USE_TIMCAP == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
diff --git a/os/hal/include/hal_usb_hid.h b/os/hal/include/hal_usb_hid.h
new file mode 100644
index 0000000..2a2d73a
--- /dev/null
+++ b/os/hal/include/hal_usb_hid.h
@@ -0,0 +1,510 @@
+/*
+ ChibiOS - Copyright (C) 2016 Jonathan Struebel
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb_hid.h
+ * @brief USB HID macros and structures.
+ *
+ * @addtogroup USB_HID
+ * @{
+ */
+
+#ifndef HAL_USB_HID_H
+#define HAL_USB_HID_H
+
+#if (HAL_USE_USB_HID == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name HID specific messages.
+ * @{
+ */
+#define HID_GET_REPORT 0x01U
+#define HID_GET_IDLE 0x02U
+#define HID_GET_PROTOCOL 0x03U
+#define HID_SET_REPORT 0x09U
+#define HID_SET_IDLE 0x0AU
+#define HID_SET_PROTOCOL 0x0BU
+/** @} */
+
+/**
+ * @name HID classes
+ * @{
+ */
+#define HID_INTERFACE_CLASS 0x03U
+/** @} */
+
+/**
+ * @name HID subclasses
+ * @{
+ */
+#define HID_BOOT_INTERFACE 0x01U
+/** @} */
+
+/**
+ * @name HID descriptors
+ * @{
+ */
+#define USB_DESCRIPTOR_HID 0x21U
+#define HID_REPORT 0x22U
+#define HID_PHYSICAL 0x23U
+/** @} */
+
+/**
+ * @name HID Report items
+ * @{
+ */
+#define HID_REPORT_USAGE_PAGE 0x04
+#define HID_REPORT_USAGE 0x08
+#define HID_REPORT_LOGICAL_MINIMUM 0x14
+#define HID_REPORT_USAGE_MINIMUM 0x18
+#define HID_REPORT_LOGICAL_MAXIMUM 0x24
+#define HID_REPORT_USAGE_MAXIMUM 0x28
+#define HID_REPORT_REPORT_SIZE 0x74
+#define HID_REPORT_INPUT 0x80
+#define HID_REPORT_REPORT_COUNT 0x94
+#define HID_REPORT_COLLECTION 0xA0
+#define HID_REPORT_END_COLLECTION 0xC0
+/** @} */
+
+/**
+ * @name HID Collection item definitions
+ * @{
+ */
+#define HID_COLLECTION_PHYSICAL 0x00
+#define HID_COLLECTION_APPLICATION 0x01
+#define HID_COLLECTION_LOGICAL 0x02
+#define HID_COLLECTION_REPORT 0x03
+#define HID_COLLECTION_NAMED_ARRAY 0x04
+#define HID_COLLECTION_USAGE_SWITCH 0x05
+#define HID_COLLECTION_USAGE_MODIFIER 0x06
+/** @} */
+
+/**
+ * @name HID Usage Page item definitions
+ * @{
+ */
+#define HID_USAGE_PAGE_GENERIC_DESKTOP 0x01
+#define HID_USAGE_PAGE_SIMULATION 0x02
+#define HID_USAGE_PAGE_VR 0x03
+#define HID_USAGE_PAGE_SPORT 0x04
+#define HID_USAGE_PAGE_GAME 0x05
+#define HID_USAGE_PAGE_GENERIC_DEVICE 0x06
+#define HID_USAGE_PAGE_KEYBOARD_KEYPAD 0x07
+#define HID_USAGE_PAGE_LEDS 0x08
+#define HID_USAGE_PAGE_BUTTON 0x09
+#define HID_USAGE_PAGE_ORDINAL 0x0A
+#define HID_USAGE_PAGE_TELEPHONY 0x0B
+#define HID_USAGE_PAGE_CONSUMER 0x0C
+#define HID_USAGE_PAGE_DIGITIZER 0x0D
+#define HID_USAGE_PAGE_PID 0x0F
+#define HID_USAGE_PAGE_UNICODE 0x10
+/** @} */
+
+/**
+ * @name HID Usage item definitions
+ * @{
+ */
+#define HID_USAGE_ALPHANUMERIC_DISPLAY 0x14
+#define HID_USAGE_MEDICAL_INSTRUMENTS 0x40
+#define HID_USAGE_MONITOR_PAGE1 0x80
+#define HID_USAGE_MONITOR_PAGE2 0x81
+#define HID_USAGE_MONITOR_PAGE3 0x82
+#define HID_USAGE_MONITOR_PAGE4 0x83
+#define HID_USAGE_POWER_PAGE1 0x84
+#define HID_USAGE_POWER_PAGE2 0x85
+#define HID_USAGE_POWER_PAGE3 0x86
+#define HID_USAGE_POWER_PAGE4 0x87
+#define HID_USAGE_BAR_CODE_SCANNER_PAGE 0x8C
+#define HID_USAGE_SCALE_PAGE 0x8D
+#define HID_USAGE_MSR_PAGE 0x8E
+#define HID_USAGE_CAMERA_PAGE 0x90
+#define HID_USAGE_ARCADE_PAGE 0x91
+
+#define HID_USAGE_POINTER 0x01
+#define HID_USAGE_MOUSE 0x02
+#define HID_USAGE_JOYSTICK 0x04
+#define HID_USAGE_GAMEPAD 0x05
+#define HID_USAGE_KEYBOARD 0x06
+#define HID_USAGE_KEYPAD 0x07
+#define HID_USAGE_MULTIAXIS_CONTROLLER 0x08
+
+#define HID_USAGE_BUTTON1 0x01
+#define HID_USAGE_BUTTON2 0x02
+#define HID_USAGE_BUTTON3 0x03
+#define HID_USAGE_BUTTON4 0x04
+#define HID_USAGE_BUTTON5 0x05
+#define HID_USAGE_BUTTON6 0x06
+#define HID_USAGE_BUTTON7 0x07
+#define HID_USAGE_BUTTON8 0x08
+
+#define HID_USAGE_X 0x30
+#define HID_USAGE_Y 0x31
+#define HID_USAGE_Z 0x32
+#define HID_USAGE_RX 0x33
+#define HID_USAGE_RY 0x34
+#define HID_USAGE_RZ 0x35
+#define HID_USAGE_VX 0x40
+#define HID_USAGE_VY 0x41
+#define HID_USAGE_VZ 0x42
+#define HID_USAGE_VBRX 0x43
+#define HID_USAGE_VBRY 0x44
+#define HID_USAGE_VBRZ 0x45
+#define HID_USAGE_VNO 0x46
+/** @} */
+
+/**
+ * @name HID Input item definitions.
+ * @{
+ */
+#define HID_INPUT_DATA_VAR_ABS 0x02
+#define HID_INPUT_CNST_VAR_ABS 0x03
+#define HID_INPUT_DATA_VAR_REL 0x06
+/** @} */
+
+/**
+ * @name Helper macros for USB HID descriptors
+ * @{
+ */
+/*
+ * @define HID Descriptor size.
+ */
+#define USB_DESC_HID_SIZE 9U
+
+/**
+ * @brief HID Descriptor helper macro.
+ * @note This macro can only be used with a single HID report descriptor
+ */
+#define USB_DESC_HID(bcdHID, bCountryCode, bNumDescriptors, \
+ bDescriptorType, wDescriptorLength) \
+ USB_DESC_BYTE(USB_DESC_HID_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_HID), \
+ USB_DESC_BCD(bcdHID), \
+ USB_DESC_BYTE(bCountryCode), \
+ USB_DESC_BYTE(bNumDescriptors), \
+ USB_DESC_BYTE(bDescriptorType), \
+ USB_DESC_WORD(wDescriptorLength)
+
+/**
+ * @brief HID Report Usage Page item helper macro (Single byte).
+ */
+#define HID_USAGE_PAGE_B(up) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_PAGE | 0x01), \
+ USB_DESC_BYTE(up)
+
+/**
+ * @brief HID Report Usage Page item helper macro (Double byte).
+ */
+#define HID_USAGE_PAGE_W(up) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_PAGE | 0x02), \
+ USB_DESC_WORD(up)
+
+/**
+ * @brief HID Report Usage item helper macro (Single byte).
+ */
+#define HID_USAGE_B(u) \
+ USB_DESC_BYTE(HID_REPORT_USAGE | 0x01), \
+ USB_DESC_BYTE(u)
+
+/**
+ * @brief HID Report Usage item helper macro (Double byte).
+ */
+#define HID_USAGE_W(u) \
+ USB_DESC_BYTE(HID_REPORT_USAGE | 0x02), \
+ USB_DESC_WORD(u)
+
+/**
+ * @brief HID Report Collection item helper macro (Single Byte).
+ */
+#define HID_COLLECTION_B(c) \
+ USB_DESC_BYTE(HID_REPORT_COLLECTION | 0x01), \
+ USB_DESC_BYTE(c)
+
+/**
+ * @brief HID Report Collection item helper macro (Double Byte).
+ */
+#define HID_COLLECTION_W(c) \
+ USB_DESC_BYTE(HID_REPORT_COLLECTION | 0x02), \
+ USB_DESC_WORD(c)
+
+/**
+ * @brief HID Report End Collection item helper macro.
+ */
+#define HID_END_COLLECTION \
+ USB_DESC_BYTE(HID_REPORT_END_COLLECTION)
+
+/**
+ * @brief HID Report Usage Minimum item helper macro (Single byte).
+ */
+#define HID_USAGE_MINIMUM_B(x) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_MINIMUM | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Usage Minimum item helper macro (Double byte).
+ */
+#define HID_USAGE_MINIMUM_W(x) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_MINIMUM | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Usage Maximum item helper macro (Single byte).
+ */
+#define HID_USAGE_MAXIMUM_B(x) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_MAXIMUM | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Usage Maximum item helper macro (Double byte).
+ */
+#define HID_USAGE_MAXIMUM_W(x) \
+ USB_DESC_BYTE(HID_REPORT_USAGE_MAXIMUM | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Logical Minimum item helper macro (Single byte).
+ */
+#define HID_LOGICAL_MINIMUM_B(x) \
+ USB_DESC_BYTE(HID_REPORT_LOGICAL_MINIMUM | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Logical Minimum item helper macro (Double byte).
+ */
+#define HID_LOGICAL_MINIMUM_W(x) \
+ USB_DESC_BYTE(HID_REPORT_LOGICAL_MINIMUM | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Logical Maximum item helper macro (Single byte).
+ */
+#define HID_LOGICAL_MAXIMUM_B(x) \
+ USB_DESC_BYTE(HID_REPORT_LOGICAL_MAXIMUM | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Logical Maximum item helper macro (Double byte).
+ */
+#define HID_LOGICAL_MAXIMUM_W(x) \
+ USB_DESC_BYTE(HID_REPORT_LOGICAL_MAXIMUM | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Count item helper macro (Single byte).
+ */
+#define HID_REPORT_COUNT_B(x) \
+ USB_DESC_BYTE(HID_REPORT_REPORT_COUNT | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Count item helper macro (Double byte).
+ */
+#define HID_REPORT_COUNT_W(x) \
+ USB_DESC_BYTE(HID_REPORT_REPORT_COUNT | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Size item helper macro (Single byte).
+ */
+#define HID_REPORT_SIZE_B(x) \
+ USB_DESC_BYTE(HID_REPORT_REPORT_SIZE | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Size item helper macro (Double byte).
+ */
+#define HID_REPORT_SIZE_W(x) \
+ USB_DESC_BYTE(HID_REPORT_REPORT_SIZE | 0x02), \
+ USB_DESC_WORD(x)
+
+/**
+ * @brief HID Report Input item helper macro (Single byte).
+ */
+#define HID_INPUT_B(x) \
+ USB_DESC_BYTE(HID_REPORT_INPUT | 0x01), \
+ USB_DESC_BYTE(x)
+
+/**
+ * @brief HID Report Input item helper macro (Double byte).
+ */
+#define HID_INPUT_W(x) \
+ USB_DESC_BYTE(HID_REPORT_INPUT | 0x02), \
+ USB_DESC_WORD(x)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name USB HID configuration options
+ * @{
+ */
+/**
+ * @brief USB HID buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(USB_HID_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define USB_HID_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief USB HID number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(USB_HID_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define USB_HID_BUFFERS_NUMBER 2
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_USE_USB == FALSE
+#error "USB HID Driver requires HAL_USE_USB"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ HID_UNINIT = 0, /**< Not initialized. */
+ HID_STOP = 1, /**< Stopped. */
+ HID_READY = 2 /**< Ready. */
+} hidstate_t;
+
+/**
+ * @brief Structure representing a USB HID driver.
+ */
+typedef struct USBHIDDriver USBHIDDriver;
+
+/**
+ * @brief USB HID Driver configuration structure.
+ * @details An instance of this structure must be passed to @p hidStart()
+ * in order to configure and start the driver operations.
+ */
+typedef struct {
+ /**
+ * @brief USB driver to use.
+ */
+ USBDriver *usbp;
+ /**
+ * @brief Interrupt IN endpoint used for outgoing data transfer.
+ */
+ usbep_t int_in;
+ /**
+ * @brief Interrupt OUT endpoint used for incoming data transfer.
+ */
+ usbep_t int_out;
+} USBHIDConfig;
+
+/**
+ * @brief @p USBHIDDriver specific data.
+ */
+#define _usb_hid_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ hidstate_t state; \
+ /* Input buffers queue.*/ \
+ input_buffers_queue_t ibqueue; \
+ /* Output queue.*/ \
+ output_buffers_queue_t obqueue; \
+ /* Input buffer.*/ \
+ uint8_t ib[BQ_BUFFER_SIZE(USB_HID_BUFFERS_NUMBER, \
+ USB_HID_BUFFERS_SIZE)]; \
+ /* Output buffer.*/ \
+ uint8_t ob[BQ_BUFFER_SIZE(USB_HID_BUFFERS_NUMBER, \
+ USB_HID_BUFFERS_SIZE)]; \
+ /* End of the mandatory fields.*/ \
+ /* Current configuration data.*/ \
+ const USBHIDConfig *config;
+
+/**
+ * @brief @p USBHIDDriver specific methods.
+ */
+#define _usb_hid_driver_methods \
+ _base_asynchronous_channel_methods \
+ /* Buffer flush method.*/ \
+ void (*flush)(void *instance);
+
+/**
+ * @extends BaseAsynchronousChannelVMT
+ *
+ * @brief @p USBHIDDriver virtual methods table.
+ */
+struct USBHIDDriverVMT {
+ _usb_hid_driver_methods
+};
+
+/**
+ * @extends BaseAsynchronousChannel
+ *
+ * @brief Full duplex USB HID driver class.
+ * @details This class extends @p BaseAsynchronousChannel by adding physical
+ * I/O queues.
+ */
+struct USBHIDDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct USBHIDDriverVMT *vmt;
+ _usb_hid_driver_data
+};
+
+#define USB_DRIVER_EXT_FIELDS \
+ USBHIDDriver hid
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hidInit(void);
+ void hidObjectInit(USBHIDDriver *uhdp);
+ void hidStart(USBHIDDriver *uhdp, const USBHIDConfig *config);
+ void hidStop(USBHIDDriver *uhdp);
+ void hidDisconnectI(USBHIDDriver *uhdp);
+ void hidConfigureHookI(USBHIDDriver *uhdp);
+ bool hidRequestsHook(USBDriver *usbp);
+ void hidDataTransmitted(USBDriver *usbp, usbep_t ep);
+ void hidDataReceived(USBDriver *usbp, usbep_t ep);
+ size_t hidWriteReport(USBHIDDriver *uhdp, uint8_t *bp, size_t n);
+ size_t hidWriteReportt(USBHIDDriver *uhdp, uint8_t *bp, size_t n, systime_t timeout);
+ size_t hidReadReport(USBHIDDriver *uhdp, uint8_t *bp, size_t n);
+ size_t hidReadReportt(USBHIDDriver *uhdp, uint8_t *bp, size_t n, systime_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB_HID */
+
+#endif /* HAL_USB_HID_H */
+
+/** @} */
diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h
index 8029be8..5fd0047 100644
--- a/os/hal/include/hal_usbh.h
+++ b/os/hal/include/hal_usbh.h
@@ -20,9 +20,6 @@
#include "hal.h"
-#ifndef HAL_USE_USBH
-#define HAL_USE_USBH FALSE
-#endif
#ifndef HAL_USBH_USE_FTDI
#define HAL_USBH_USE_FTDI FALSE
@@ -40,7 +37,7 @@
#define HAL_USBH_USE_UVC FALSE
#endif
-#if HAL_USE_USBH
+#if (HAL_USE_USBH == TRUE) || defined(__DOXYGEN__)
#include "osal.h"
#include "usbh/list.h"
diff --git a/os/hal/ports/KINETIS/LLD/hal_i2c_lld.h b/os/hal/ports/KINETIS/LLD/hal_i2c_lld.h
index 3576b60..bfc5008 100644
--- a/os/hal/ports/KINETIS/LLD/hal_i2c_lld.h
+++ b/os/hal/ports/KINETIS/LLD/hal_i2c_lld.h
@@ -157,14 +157,10 @@ struct I2CDriver {
*/
i2cflags_t errors;
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
-#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the bus.
*/
mutex_t mutex;
-#elif CH_CFG_USE_SEMAPHORES
- semaphore_t semaphore;
-#endif
#endif /* I2C_USE_MUTUAL_EXCLUSION */
#if defined(I2C_DRIVER_EXT_FIELDS)
I2C_DRIVER_EXT_FIELDS
diff --git a/os/hal/ports/KINETIS/LLD/hal_pal_lld.c b/os/hal/ports/KINETIS/LLD/hal_pal_lld.c
index b307833..51f8a2e 100644
--- a/os/hal/ports/KINETIS/LLD/hal_pal_lld.c
+++ b/os/hal/ports/KINETIS/LLD/hal_pal_lld.c
@@ -108,7 +108,7 @@ void _pal_lld_setpadmode(ioportid_t port,
PORT_TypeDef *portcfg = NULL;
- chDbgAssert(pad < PADS_PER_PORT, "pal_lld_setpadmode() #1, invalid pad");
+ osalDbgAssert(pad < PADS_PER_PORT, "pal_lld_setpadmode() #1, invalid pad");
if (mode == PAL_MODE_OUTPUT_PUSHPULL)
port->PDDR |= ((uint32_t) 1 << pad);
@@ -126,7 +126,7 @@ void _pal_lld_setpadmode(ioportid_t port,
else if (port == IOPORT5)
portcfg = PORTE;
- chDbgAssert(portcfg != NULL, "pal_lld_setpadmode() #2, invalid port");
+ osalDbgAssert(portcfg != NULL, "pal_lld_setpadmode() #2, invalid port");
switch (mode) {
case PAL_MODE_RESET:
diff --git a/os/hal/ports/KINETIS/LLD/hal_usb_lld.c b/os/hal/ports/KINETIS/LLD/hal_usb_lld.c
index 159aef9..e8d9778 100644
--- a/os/hal/ports/KINETIS/LLD/hal_usb_lld.c
+++ b/os/hal/ports/KINETIS/LLD/hal_usb_lld.c
@@ -420,7 +420,7 @@ void usb_lld_init(void) {
}
}
usbfrac_match_found:
- chDbgAssert(i<2 && j <8,"USB Init error");
+ osalDbgAssert(i<2 && j <8,"USB Init error");
#else /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */
#error USB clock setting not implemented for this KINETIS_MCG_MODE
diff --git a/os/hal/ports/NRF51/NRF51822/hal_gpt_lld.h b/os/hal/ports/NRF51/NRF51822/hal_gpt_lld.h
index 748be0a..9b4cc9b 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_gpt_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_gpt_lld.h
@@ -70,21 +70,21 @@
* @brief GPTD1 interrupt priority level setting.
*/
#if !defined(NRF51_GPT_TIMER0_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_GPT_TIMER0_IRQ_PRIORITY 7
+#define NRF51_GPT_TIMER0_IRQ_PRIORITY 3
#endif
/**
* @brief GPTD2 interrupt priority level setting.
*/
#if !defined(NRF51_GPT_TIMER1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_GPT_TIMER1_IRQ_PRIORITY 7
+#define NRF51_GPT_TIMER1_IRQ_PRIORITY 3
#endif
/**
* @brief GPTD3 interrupt priority level setting.
*/
#if !defined(NRF51_GPT_TIMER2_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_GPT_TIMER2_IRQ_PRIORITY 7
+#define NRF51_GPT_TIMER2_IRQ_PRIORITY 3
#endif
/** @} */
@@ -97,7 +97,6 @@
#error "GPT driver activated but no TIMER peripheral assigned"
#endif
-#if 0
#if NRF51_GPT_USE_TIMER0 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF51_GPT_TIMER0_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER0"
@@ -112,7 +111,6 @@
!OSAL_IRQ_IS_VALID_PRIORITY(NRF51_GPT_TIMER2_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER2"
#endif
-#endif
/*===========================================================================*/
/* Driver data structures and types. */
diff --git a/os/hal/ports/NRF51/NRF51822/hal_i2c_lld.h b/os/hal/ports/NRF51/NRF51822/hal_i2c_lld.h
index 555ced1..e2c3d07 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_i2c_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_i2c_lld.h
@@ -66,14 +66,14 @@
* @brief I2C0 interrupt priority level setting.
*/
#if !defined(NRF51_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_I2C_I2C0_IRQ_PRIORITY 10
+#define NRF51_I2C_I2C0_IRQ_PRIORITY 3
#endif
/**
* @brief I2C1 interrupt priority level setting.
*/
#if !defined(NRF51_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_I2C_I2C1_IRQ_PRIORITY 10
+#define NRF51_I2C_I2C1_IRQ_PRIORITY 3
#endif
/** @} */
@@ -81,6 +81,16 @@
/* Derived constants and error checks. */
/*===========================================================================*/
+#if NRF51_I2C_USE_I2C0 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_I2C_I2C0_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C0"
+#endif
+
+#if NRF51_I2C_USE_I2C1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_I2C_I2C1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C1"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
diff --git a/os/hal/ports/NRF51/NRF51822/hal_pal_lld.h b/os/hal/ports/NRF51/NRF51822/hal_pal_lld.h
index e5b62ee..5032916 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_pal_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_pal_lld.h
@@ -80,7 +80,7 @@
/**
* @brief Value identifying an invalid line.
*/
-#define PAL_NOLINE FFU
+#define PAL_NOLINE ((ioline_t)-1)
/** @} */
/**
diff --git a/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.c b/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.c
index 76bc572..456dcff 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.c
+++ b/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.c
@@ -68,25 +68,27 @@ PWMDriver PWMD3;
/*===========================================================================*/
static void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
- // Deal with PWM period
- if (pwmp->timer->EVENTS_COMPARE[pwmp->channels]) {
- pwmp->timer->EVENTS_COMPARE[pwmp->channels] = 0;
-
- if (pwmp->config->callback != NULL) {
- pwmp->config->callback(pwmp);
- }
- }
-
// Deal with PWM channels
uint8_t n;
for (n = 0 ; n < pwmp->channels ; n++) {
if (pwmp->timer->EVENTS_COMPARE[n]) {
pwmp->timer->EVENTS_COMPARE[n] = 0;
+
if (pwmp->config->channels[n].callback != NULL) {
pwmp->config->channels[n].callback(pwmp);
}
}
}
+
+ // Deal with PWM period
+ if (pwmp->timer->EVENTS_COMPARE[pwmp->channels]) {
+ pwmp->timer->EVENTS_COMPARE[pwmp->channels] = 0;
+
+ if (pwmp->config->callback != NULL) {
+ pwmp->config->callback(pwmp);
+ }
+ }
+
}
/*===========================================================================*/
@@ -280,6 +282,47 @@ void pwm_lld_stop(PWMDriver *pwmp) {
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width) {
+#if NRF51_PWM_USE_GPIOTE_PPI
+ const PWMChannelConfig *cfg_channel = &pwmp->config->channels[channel];
+
+ uint32_t outinit;
+ switch(cfg_channel->mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ outinit = GPIOTE_CONFIG_OUTINIT_Low;
+ break;
+ case PWM_OUTPUT_ACTIVE_HIGH:
+ outinit = GPIOTE_CONFIG_OUTINIT_High;
+ break;
+ case PWM_OUTPUT_DISABLED:
+ default:
+ goto no_output_config;
+ }
+
+ const uint32_t gpio_pin = PAL_PAD(cfg_channel->ioline);
+ const uint8_t gpiote_channel = cfg_channel->gpiote_channel;
+ const uint8_t *ppi_channel = cfg_channel->ppi_channel;
+ const uint32_t polarity = GPIOTE_CONFIG_POLARITY_Toggle;
+
+ // Create GPIO Task
+ NRF_GPIOTE->CONFIG[gpiote_channel] = GPIOTE_CONFIG_MODE_Task |
+ ((gpio_pin << GPIOTE_CONFIG_PSEL_Pos ) & GPIOTE_CONFIG_PSEL_Msk) |
+ ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) |
+ ((outinit << GPIOTE_CONFIG_OUTINIT_Pos ) & GPIOTE_CONFIG_OUTINIT_Msk);
+
+ // Program tasks (one for duty cycle, one for periode)
+ NRF_PPI->CH[ppi_channel[0]].EEP =
+ (uint32_t)&pwmp->timer->EVENTS_COMPARE[channel];
+ NRF_PPI->CH[ppi_channel[0]].TEP =
+ (uint32_t)&NRF_GPIOTE->TASKS_OUT[gpiote_channel];
+ NRF_PPI->CH[ppi_channel[1]].EEP =
+ (uint32_t)&pwmp->timer->EVENTS_COMPARE[pwmp->channels];
+ NRF_PPI->CH[ppi_channel[1]].TEP =
+ (uint32_t)&NRF_GPIOTE->TASKS_OUT[gpiote_channel];
+ NRF_PPI->CHENSET = ((1 << ppi_channel[0]) | (1 << ppi_channel[1]));
+
+ no_output_config:
+#endif
+
pwmp->timer->CC[channel] = width;
}
@@ -297,6 +340,22 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
*/
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
pwmp->timer->CC[channel] = 0;
+#if NRF51_PWM_USE_GPIOTE_PPI
+ const PWMChannelConfig *cfg_channel = &pwmp->config->channels[channel];
+ switch(cfg_channel->mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ case PWM_OUTPUT_ACTIVE_HIGH: {
+ const uint8_t gpiote_channel = cfg_channel->gpiote_channel;
+ const uint8_t *ppi_channel = cfg_channel->ppi_channel;
+ NRF_PPI->CHENCLR = ((1 << ppi_channel[0]) | (1 << ppi_channel[1]));
+ NRF_GPIOTE->CONFIG[gpiote_channel] = GPIOTE_CONFIG_MODE_Disabled;
+ break;
+ }
+ case PWM_OUTPUT_DISABLED:
+ default:
+ break;
+ }
+#endif
}
/**
diff --git a/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.h b/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.h
index 0ddd65c..e2982d8 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_pwm_lld.h
@@ -52,14 +52,28 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
+/**
+ * @name Configuration options
+ * @{
+ */
+
+/**
+ * @brief TIMER0 as driver implementation
+ */
#if !defined(NRF51_PWM_USE_TIMER0)
#define NRF51_PWM_USE_TIMER0 FALSE
#endif
+/**
+ * @brief TIMER1 as driver implementation
+ */
#if !defined(NRF51_PWM_USE_TIMER1)
#define NRF51_PWM_USE_TIMER1 FALSE
#endif
+/**
+ * @brief TIMER2 as driver implementation
+ */
#if !defined(NRF51_PWM_USE_TIMER2)
#define NRF51_PWM_USE_TIMER2 FALSE
#endif
@@ -68,29 +82,30 @@
* @brief TIMER0 interrupt priority level setting.
*/
#if !defined(NRF51_PWM_TIMER0_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_PWM_TIMER0_PRIORITY 12
+#define NRF51_PWM_TIMER0_PRIORITY 3
#endif
/**
* @brief TIMER1 interrupt priority level setting.
*/
#if !defined(NRF51_PWM_TIMER1_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_PWM_TIMER1_PRIORITY 12
+#define NRF51_PWM_TIMER1_PRIORITY 3
#endif
/**
* @brief TIMER2 interrupt priority level setting.
*/
#if !defined(NRF51_PWM_TIMER2_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_PWM_TIMER2_PRIORITY 12
+#define NRF51_PWM_TIMER2_PRIORITY 3
#endif
-/** @} */
-
/**
- * @name Configuration options
- * @{
+ * @brief Allow driver to use GPIOTE/PPI to control PAL line
*/
+#if !defined(NRF51_PWM_USE_GPIOTE_PPI)
+#define NRF51_PWM_USE_GPIOTE_PPI FALSE
+#endif
+
/** @} */
/*===========================================================================*/
@@ -105,6 +120,22 @@
#error "TIMER0 used for ST and PWM"
#endif
+#if NRF51_PWM_USE_TIMER0 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_PWM_TIMER0_PRIORITY)
+#error "Invalid IRQ priority assigned to TIMER0"
+#endif
+
+#if NRF51_PWM_USE_TIMER1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_PWM_TIMER1_PRIORITY)
+#error "Invalid IRQ priority assigned to TIMER1"
+#endif
+
+#if NRF51_PWM_USE_TIMER2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_PWM_TIMER2_PRIORITY)
+#error "Invalid IRQ priority assigned to TIMER2"
+#endif
+
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -145,6 +176,32 @@ typedef struct {
*/
pwmcallback_t callback;
/* End of the mandatory fields.*/
+
+ /**
+ * @brief PAL line to toggle.
+ * @note Only used if mode is PWM_OUTPUT_HIGH or PWM_OUTPUT_LOW.
+ * @note When NRF51_PWM_USE_GPIOTE_PPI is used and channel enabled,
+ * it wont be possible to access this PAL line using the PAL
+ * driver.
+ */
+ ioline_t ioline;
+
+#if NRF51_PWM_USE_GPIOTE_PPI || defined(__DOXYGEN__)
+ /**
+ * @brief Unique GPIOTE channel to use. (1 channel)
+ * @note Only used if mode is PWM_OUTPUT_HIGH or PWM_OUTPUT_LOW.
+ * @note Only 4 GPIOTE channels are available on nRF51.
+ */
+ uint8_t gpiote_channel;
+
+ /**
+ * @brief Unique PPI channels to use. (2 channels)
+ * @note Only used if mode is PWM_OUTPUT_HIGH or PWM_OUTPUT_LOW.
+ * @note Only 16 PPI channels are available on nRF51
+ * (When Softdevice is enabled, only channels 0-7 are available)
+ */
+ uint8_t ppi_channel[2];
+#endif
} PWMChannelConfig;
/**
diff --git a/os/hal/ports/NRF51/NRF51822/hal_rng_lld.h b/os/hal/ports/NRF51/NRF51822/hal_rng_lld.h
index 475770b..0ad0bc6 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_rng_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_rng_lld.h
@@ -61,7 +61,7 @@
* @brief RNG1 interrupt priority level setting.
*/
#if !defined(NRF51_RNG_RNG1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_RNG_RNG1_IRQ_PRIORITY 10
+#define NRF51_RNG_RNG1_IRQ_PRIORITY 3
#endif
@@ -69,6 +69,10 @@
/* Derived constants and error checks. */
/*===========================================================================*/
+#if NRF51_RNG_USE_RNG1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_RNG_RNG1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to RNG1"
+#endif
/*===========================================================================*/
/* Driver data structures and types. */
diff --git a/os/hal/ports/NRF51/NRF51822/hal_serial_lld.h b/os/hal/ports/NRF51/NRF51822/hal_serial_lld.h
index 304c07d..79955b1 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_serial_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_serial_lld.h
@@ -62,7 +62,7 @@
* @brief UART0 interrupt priority level setting.
*/
#if !defined(NRF51_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_SERIAL_UART0_PRIORITY 12
+#define NRF51_SERIAL_UART0_PRIORITY 3
#endif
/* Value indicating that no pad is connected to this UART register. */
@@ -75,6 +75,11 @@
/* Derived constants and error checks. */
/*===========================================================================*/
+#if NRF51_SERIAL_USE_UART0 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_SERIAL_UART0_PRIORITY)
+#error "Invalid IRQ priority assigned to UART0"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
diff --git a/os/hal/ports/NRF51/NRF51822/hal_spi_lld.h b/os/hal/ports/NRF51/NRF51822/hal_spi_lld.h
index d339a91..4d1c452 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_spi_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_spi_lld.h
@@ -39,14 +39,14 @@
* @brief SPI0 interrupt priority level setting.
*/
#if !defined(NRF51_SPI_SPI0_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_SPI_SPI0_IRQ_PRIORITY 10
+#define NRF51_SPI_SPI0_IRQ_PRIORITY 3
#endif
/**
* @brief SPI1 interrupt priority level setting.
*/
#if !defined(NRF51_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define NRF51_SPI_SPI1_IRQ_PRIORITY 10
+#define NRF51_SPI_SPI1_IRQ_PRIORITY 3
#endif
/**
@@ -65,6 +65,16 @@
#error "SPI driver activated but no SPI peripheral assigned"
#endif
+#if NRF51_SPI_USE_SPI0 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_SPI_SPI0_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI0"
+#endif
+
+#if NRF51_SPI_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
diff --git a/os/hal/ports/NRF51/NRF51822/hal_st_lld.h b/os/hal/ports/NRF51/NRF51822/hal_st_lld.h
index bde9950..8d12d2e 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_st_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_st_lld.h
@@ -71,7 +71,7 @@
*/
#if !defined(NRF51_ST_PRIORITY) || defined(__DOXYGEN__)
#if !defined(SOFTDEVICE_PRESENT)
-#define NRF51_ST_PRIORITY 8
+#define NRF51_ST_PRIORITY 1
#else
#define NRF51_ST_PRIORITY 1
#endif
@@ -123,6 +123,10 @@
#endif
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+#if !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_ST_PRIORITY)
+#error "Invalid IRQ priority assigned to ST driver"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
new file mode 100644
index 0000000..ea051f7
--- /dev/null
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
@@ -0,0 +1,293 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Martino Migliavacca
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_qei_lld.c
+ * @brief STM32 QEI subsystem low level driver header.
+ *
+ * @addtogroup QEI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_QEI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief QEID1 driver identifier.
+ * @note The driver QEID1 allocates the complex timer TIM1 when enabled.
+ */
+#if STM32_QEI_USE_TIM1 || defined(__DOXYGEN__)
+QEIDriver QEID1;
+#endif
+
+/**
+ * @brief QEID2 driver identifier.
+ * @note The driver QEID1 allocates the timer TIM2 when enabled.
+ */
+#if STM32_QEI_USE_TIM2 || defined(__DOXYGEN__)
+QEIDriver QEID2;
+#endif
+
+/**
+ * @brief QEID3 driver identifier.
+ * @note The driver QEID1 allocates the timer TIM3 when enabled.
+ */
+#if STM32_QEI_USE_TIM3 || defined(__DOXYGEN__)
+QEIDriver QEID3;
+#endif
+
+/**
+ * @brief QEID4 driver identifier.
+ * @note The driver QEID4 allocates the timer TIM4 when enabled.
+ */
+#if STM32_QEI_USE_TIM4 || defined(__DOXYGEN__)
+QEIDriver QEID4;
+#endif
+
+/**
+ * @brief QEID5 driver identifier.
+ * @note The driver QEID5 allocates the timer TIM5 when enabled.
+ */
+#if STM32_QEI_USE_TIM5 || defined(__DOXYGEN__)
+QEIDriver QEID5;
+#endif
+
+/**
+ * @brief QEID8 driver identifier.
+ * @note The driver QEID8 allocates the timer TIM8 when enabled.
+ */
+#if STM32_QEI_USE_TIM8 || defined(__DOXYGEN__)
+QEIDriver QEID8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level QEI driver initialization.
+ *
+ * @notapi
+ */
+void qei_lld_init(void) {
+
+#if STM32_QEI_USE_TIM1
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID1);
+ QEID1.tim = STM32_TIM1;
+#endif
+
+#if STM32_QEI_USE_TIM2
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID2);
+ QEID2.tim = STM32_TIM2;
+#endif
+
+#if STM32_QEI_USE_TIM3
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID3);
+ QEID3.tim = STM32_TIM3;
+#endif
+
+#if STM32_QEI_USE_TIM4
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID4);
+ QEID4.tim = STM32_TIM4;
+#endif
+
+#if STM32_QEI_USE_TIM5
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID5);
+ QEID5.tim = STM32_TIM5;
+#endif
+
+#if STM32_QEI_USE_TIM8
+ /* Driver initialization.*/
+ qeiObjectInit(&QEID8);
+ QEID8.tim = STM32_TIM8;
+#endif
+}
+
+/**
+ * @brief Configures and activates the QEI peripheral.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @notapi
+ */
+void qei_lld_start(QEIDriver *qeip) {
+
+ if (qeip->state == QEI_STOP) {
+ /* Clock activation and timer reset.*/
+#if STM32_QEI_USE_TIM1
+ if (&QEID1 == qeip) {
+ rccEnableTIM1(FALSE);
+ rccResetTIM1();
+ }
+#endif
+#if STM32_QEI_USE_TIM2
+ if (&QEID2 == qeip) {
+ rccEnableTIM2(FALSE);
+ rccResetTIM2();
+ }
+#endif
+#if STM32_QEI_USE_TIM3
+ if (&QEID3 == qeip) {
+ rccEnableTIM3(FALSE);
+ rccResetTIM3();
+ }
+#endif
+#if STM32_QEI_USE_TIM4
+ if (&QEID4 == qeip) {
+ rccEnableTIM4(FALSE);
+ rccResetTIM4();
+ }
+#endif
+
+#if STM32_QEI_USE_TIM5
+ if (&QEID5 == qeip) {
+ rccEnableTIM5(FALSE);
+ rccResetTIM5();
+ }
+#endif
+#if STM32_QEI_USE_TIM8
+ if (&QEID8 == qeip) {
+ rccEnableTIM8(FALSE);
+ rccResetTIM8();
+ }
+#endif
+ }
+ /* Timer configuration.*/
+ qeip->tim->CR1 = 0; /* Initially stopped. */
+ qeip->tim->CR2 = 0;
+ qeip->tim->PSC = 0;
+ qeip->tim->DIER = 0;
+ qeip->tim->ARR = 0xFFFF;
+
+ /* Set Capture Compare 1 and Capture Compare 2 as input. */
+ qeip->tim->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
+
+ if (qeip->config->mode == QEI_MODE_QUADRATURE) {
+ if (qeip->config->resolution == QEI_BOTH_EDGES)
+ qeip->tim->SMCR = TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0;
+ else
+ qeip->tim->SMCR = TIM_SMCR_SMS_0;
+ } else {
+ /* Direction/Clock mode.
+ * Direction input on TI1, Clock input on TI2. */
+ qeip->tim->SMCR = TIM_SMCR_SMS_0;
+ }
+
+ if (qeip->config->dirinv == QEI_DIRINV_TRUE)
+ qeip->tim->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC2E;
+ else
+ qeip->tim->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
+}
+
+/**
+ * @brief Deactivates the QEI peripheral.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @notapi
+ */
+void qei_lld_stop(QEIDriver *qeip) {
+
+ if (qeip->state == QEI_READY) {
+ qeip->tim->CR1 = 0; /* Timer disabled. */
+
+ /* Clock deactivation.*/
+#if STM32_QEI_USE_TIM1
+ if (&QEID1 == qeip) {
+ rccDisableTIM1(FALSE);
+ }
+#endif
+#if STM32_QEI_USE_TIM2
+ if (&QEID2 == qeip) {
+ rccDisableTIM2(FALSE);
+ }
+#endif
+#if STM32_QEI_USE_TIM3
+ if (&QEID3 == qeip) {
+ rccDisableTIM3(FALSE);
+ }
+#endif
+#if STM32_QEI_USE_TIM4
+ if (&QEID4 == qeip) {
+ rccDisableTIM4(FALSE);
+ }
+#endif
+#if STM32_QEI_USE_TIM5
+ if (&QEID5 == qeip) {
+ rccDisableTIM5(FALSE);
+ }
+#endif
+ }
+#if STM32_QEI_USE_TIM8
+ if (&QEID8 == qeip) {
+ rccDisableTIM8(FALSE);
+ }
+#endif
+}
+
+/**
+ * @brief Enables the input capture.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @notapi
+ */
+void qei_lld_enable(QEIDriver *qeip) {
+
+ qeip->tim->CR1 = TIM_CR1_CEN; /* Timer enabled. */
+}
+
+/**
+ * @brief Disables the input capture.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @notapi
+ */
+void qei_lld_disable(QEIDriver *qeip) {
+
+ qeip->tim->CR1 = 0; /* Timer disabled. */
+}
+
+#endif /* HAL_USE_QEI */
+
+/** @} */
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
new file mode 100644
index 0000000..d0cb683
--- /dev/null
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
@@ -0,0 +1,347 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Martino Migliavacca
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_qei_lld.h
+ * @brief STM32 QEI subsystem low level driver header.
+ *
+ * @addtogroup QEI
+ * @{
+ */
+
+#ifndef HAL_QEI_LLD_H
+#define HAL_QEI_LLD_H
+
+#if (HAL_USE_QEI == TRUE) || defined(__DOXYGEN__)
+
+#include "stm32_tim.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief QEID1 driver enable switch.
+ * @details If set to @p TRUE the support for QEID1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM1) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM1 FALSE
+#endif
+
+/**
+ * @brief QEID2 driver enable switch.
+ * @details If set to @p TRUE the support for QEID2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM2) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM2 FALSE
+#endif
+
+/**
+ * @brief QEID3 driver enable switch.
+ * @details If set to @p TRUE the support for QEID3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM3) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM3 FALSE
+#endif
+
+/**
+ * @brief QEID4 driver enable switch.
+ * @details If set to @p TRUE the support for QEID4 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM4) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM4 FALSE
+#endif
+
+/**
+ * @brief QEID5 driver enable switch.
+ * @details If set to @p TRUE the support for QEID5 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM5) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM5 FALSE
+#endif
+
+/**
+ * @brief QEID8 driver enable switch.
+ * @details If set to @p TRUE the support for QEID8 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_QEI_USE_TIM8) || defined(__DOXYGEN__)
+#define STM32_QEI_USE_TIM8 FALSE
+#endif
+
+/**
+ * @brief QEID1 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM1_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief QEID2 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM2_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief QEID3 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM3_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief QEID4 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM4_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief QEID5 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief QEID8 interrupt priority level setting.
+ */
+#if !defined(STM32_QEI_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_QEI_TIM8_IRQ_PRIORITY 7
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_QEI_USE_TIM1 && !STM32_HAS_TIM1
+#error "TIM1 not present in the selected device"
+#endif
+
+#if STM32_QEI_USE_TIM2 && !STM32_HAS_TIM2
+#error "TIM2 not present in the selected device"
+#endif
+
+#if STM32_QEI_USE_TIM3 && !STM32_HAS_TIM3
+#error "TIM3 not present in the selected device"
+#endif
+
+#if STM32_QEI_USE_TIM4 && !STM32_HAS_TIM4
+#error "TIM4 not present in the selected device"
+#endif
+
+#if STM32_QEI_USE_TIM5 && !STM32_HAS_TIM5
+#error "TIM5 not present in the selected device"
+#endif
+
+#if STM32_QEI_USE_TIM8 && !STM32_HAS_TIM8
+#error "TIM8 not present in the selected device"
+#endif
+
+#if !STM32_QEI_USE_TIM1 && !STM32_QEI_USE_TIM2 && \
+ !STM32_QEI_USE_TIM3 && !STM32_QEI_USE_TIM4 && \
+ !STM32_QEI_USE_TIM5 && !STM32_QEI_USE_TIM8
+#error "QEI driver activated but no TIM peripheral assigned"
+#endif
+
+#if STM32_QEI_USE_TIM1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM1"
+#endif
+
+#if STM32_QEI_USE_TIM2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM2"
+#endif
+
+#if STM32_QEI_USE_TIM3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM3"
+#endif
+
+#if STM32_QEI_USE_TIM4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM4"
+#endif
+
+#if STM32_QEI_USE_TIM5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM5"
+#endif
+
+#if STM32_QEI_USE_TIM8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_QEI_TIM8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM8"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief QEI count mode.
+ */
+typedef enum {
+ QEI_MODE_QUADRATURE = 0, /**< Quadrature encoder mode. */
+ QEI_MODE_DIRCLOCK = 1, /**< Direction/Clock mode. */
+} qeimode_t;
+
+/**
+ * @brief QEI resolution.
+ */
+typedef enum {
+ QEI_SINGLE_EDGE = 0, /**< Count only on edges from first channel. */
+ QEI_BOTH_EDGES = 1, /**< Count on both edges (resolution doubles).*/
+} qeiresolution_t;
+
+/**
+ * @brief QEI direction inversion.
+ */
+typedef enum {
+ QEI_DIRINV_FALSE = 0, /**< Do not invert counter direction. */
+ QEI_DIRINV_TRUE = 1, /**< Invert counter direction. */
+} qeidirinv_t;
+
+/**
+ * @brief QEI counter type.
+ */
+typedef uint16_t qeicnt_t;
+
+/**
+ * @brief QEI delta type.
+ */
+typedef int32_t qeidelta_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Count mode.
+ */
+ qeimode_t mode;
+ /**
+ * @brief Resolution.
+ */
+ qeiresolution_t resolution;
+ /**
+ * @brief Direction inversion.
+ */
+ qeidirinv_t dirinv;
+ /* End of the mandatory fields.*/
+} QEIConfig;
+
+/**
+ * @brief Structure representing an QEI driver.
+ */
+struct QEIDriver {
+ /**
+ * @brief Driver state.
+ */
+ qeistate_t state;
+ /**
+ * @brief Last count value.
+ */
+ qeicnt_t last;
+ /**
+ * @brief Current configuration data.
+ */
+ const QEIConfig *config;
+#if defined(QEI_DRIVER_EXT_FIELDS)
+ QEI_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the TIMx registers block.
+ */
+ stm32_tim_t *tim;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the counter value.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @return The current counter value.
+ *
+ * @notapi
+ */
+#define qei_lld_get_count(qeip) ((qeip)->tim->CNT)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_QEI_USE_TIM1 && !defined(__DOXYGEN__)
+extern QEIDriver QEID1;
+#endif
+
+#if STM32_QEI_USE_TIM2 && !defined(__DOXYGEN__)
+extern QEIDriver QEID2;
+#endif
+
+#if STM32_QEI_USE_TIM3 && !defined(__DOXYGEN__)
+extern QEIDriver QEID3;
+#endif
+
+#if STM32_QEI_USE_TIM4 && !defined(__DOXYGEN__)
+extern QEIDriver QEID4;
+#endif
+
+#if STM32_QEI_USE_TIM5 && !defined(__DOXYGEN__)
+extern QEIDriver QEID5;
+#endif
+
+#if STM32_QEI_USE_TIM8 && !defined(__DOXYGEN__)
+extern QEIDriver QEID8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void qei_lld_init(void);
+ void qei_lld_start(QEIDriver *qeip);
+ void qei_lld_stop(QEIDriver *qeip);
+ void qei_lld_enable(QEIDriver *qeip);
+ void qei_lld_disable(QEIDriver *qeip);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_QEI */
+
+#endif /* HAL_QEI_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F0xx/platform.mk b/os/hal/ports/STM32/STM32F0xx/platform.mk
index c796984..377acdf 100644
--- a/os/hal/ports/STM32/STM32F0xx/platform.mk
+++ b/os/hal/ports/STM32/STM32F0xx/platform.mk
@@ -2,6 +2,7 @@ include ${CHIBIOS}/os/hal/ports/STM32/STM32F0xx/platform.mk
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c \
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1 \
diff --git a/os/hal/ports/STM32/STM32F1xx/platform.mk b/os/hal/ports/STM32/STM32F1xx/platform.mk
index d2aeae0..a8f21bc 100644
--- a/os/hal/ports/STM32/STM32F1xx/platform.mk
+++ b/os/hal/ports/STM32/STM32F1xx/platform.mk
@@ -6,6 +6,7 @@ PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/FSMCv1/hal_fsmc_sram.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_fsmc_sdram.c
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
diff --git a/os/hal/ports/STM32/STM32F3xx/platform.mk b/os/hal/ports/STM32/STM32F3xx/platform.mk
index baa7578..92f033c 100644
--- a/os/hal/ports/STM32/STM32F3xx/platform.mk
+++ b/os/hal/ports/STM32/STM32F3xx/platform.mk
@@ -2,7 +2,8 @@ include ${CHIBIOS}/os/hal/ports/STM32/STM32F3xx/platform.mk
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.c \
- ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c
+ ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c \
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1 \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1 \
diff --git a/os/hal/ports/STM32/STM32F4xx/platform.mk b/os/hal/ports/STM32/STM32F4xx/platform.mk
index bc18dc6..c312e72 100644
--- a/os/hal/ports/STM32/STM32F4xx/platform.mk
+++ b/os/hal/ports/STM32/STM32F4xx/platform.mk
@@ -8,6 +8,7 @@ PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/LTDCv1/hal_stm32_ltdc.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_eicu_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_timcap_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c \
${CHIBIOS_CONTRIB}/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_fsmc_sdram.c
diff --git a/os/hal/src/hal_community.c b/os/hal/src/hal_community.c
index 981aa25..8a39bf1 100644
--- a/os/hal/src/hal_community.c
+++ b/os/hal/src/hal_community.c
@@ -76,6 +76,10 @@ void halCommunityInit(void) {
#if HAL_USE_TIMCAP || defined(__DOXYGEN__)
timcapInit();
#endif
+
+#if HAL_USE_QEI || defined(__DOXYGEN__)
+ qeiInit();
+#endif
}
#endif /* HAL_USE_COMMUNITY */
diff --git a/os/hal/src/hal_onewire.c b/os/hal/src/hal_onewire.c
index 85f0fdc..a93eec0 100644
--- a/os/hal/src/hal_onewire.c
+++ b/os/hal/src/hal_onewire.c
@@ -58,6 +58,7 @@ on every timer overflow event.
#if (HAL_USE_ONEWIRE == TRUE) || defined(__DOXYGEN__)
#include <string.h>
+#include <limits.h>
/*===========================================================================*/
/* Driver local definitions. */
@@ -172,7 +173,7 @@ static void ow_bus_active(onewireDriver *owp) {
* @brief Function performing read of single bit.
* @note It must be callable from any context.
*/
-static uint_fast8_t ow_read_bit(onewireDriver *owp) {
+static ioline_t ow_read_bit(onewireDriver *owp) {
#if ONEWIRE_SYNTH_SEARCH_TEST
(void)owp;
return _synth_ow_read_bit();
@@ -221,7 +222,7 @@ static void pwm_search_rom_cb(PWMDriver *pwmp) {
*
* @notapi
*/
-static void ow_write_bit_I(onewireDriver *owp, uint_fast8_t bit) {
+static void ow_write_bit_I(onewireDriver *owp, ioline_t bit) {
#if ONEWIRE_SYNTH_SEARCH_TEST
_synth_ow_write_bit(owp, bit);
#else
@@ -348,12 +349,11 @@ static void ow_write_bit_cb(PWMDriver *pwmp, onewireDriver *owp) {
* @param[in] sr pointer to the @p onewire_search_rom_t helper structure
* @param[in] bit discovered bit to be stored in helper structure
*/
-static void store_bit(onewire_search_rom_t *sr, uint_fast8_t bit) {
+static void store_bit(onewire_search_rom_t *sr, uint8_t bit) {
size_t rb = sr->reg.rombit;
- /* / 8 % 8 */
- sr->retbuf[rb >> 3] |= bit << (rb & 7);
+ sr->retbuf[rb / CHAR_BIT] |= bit << (rb % CHAR_BIT);
sr->reg.rombit++;
}
@@ -365,9 +365,9 @@ static void store_bit(onewire_search_rom_t *sr, uint_fast8_t bit) {
* 'search ROM' helper structure
* @param[in] bit number of bit [0..63]
*/
-static uint_fast8_t extract_path_bit(const uint8_t *path, uint_fast8_t bit) {
- /* / 8 % 8 */
- return (path[bit >> 3] >> (bit & 7)) & 1;
+static uint8_t extract_path_bit(const uint8_t *path, size_t bit) {
+
+ return (path[bit / CHAR_BIT] >> (bit % CHAR_BIT)) & 1;
}
/**
@@ -377,9 +377,9 @@ static uint_fast8_t extract_path_bit(const uint8_t *path, uint_fast8_t bit) {
*
* @param[in,out] sr pointer to the @p onewire_search_rom_t helper structure
*/
-static uint_fast8_t collision_handler(onewire_search_rom_t *sr) {
+static uint8_t collision_handler(onewire_search_rom_t *sr) {
- uint_fast8_t bit;
+ uint8_t bit;
switch(sr->reg.search_iter) {
case ONEWIRE_SEARCH_ROM_NEXT:
diff --git a/os/hal/src/hal_qei.c b/os/hal/src/hal_qei.c
new file mode 100644
index 0000000..a2b7303
--- /dev/null
+++ b/os/hal/src/hal_qei.c
@@ -0,0 +1,214 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Martino Migliavacca
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_qei.c
+ * @brief QEI Driver code.
+ *
+ * @addtogroup QEI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_QEI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief QEI Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void qeiInit(void) {
+
+ qei_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p QEIDriver structure.
+ *
+ * @param[out] qeip pointer to the @p QEIDriver object
+ *
+ * @init
+ */
+void qeiObjectInit(QEIDriver *qeip) {
+
+ qeip->state = QEI_STOP;
+ qeip->last = 0;
+ qeip->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the QEI peripheral.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @param[in] config pointer to the @p QEIConfig object
+ *
+ * @api
+ */
+void qeiStart(QEIDriver *qeip, const QEIConfig *config) {
+
+ osalDbgCheck((qeip != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
+ "invalid state");
+ qeip->config = config;
+ qei_lld_start(qeip);
+ qeip->state = QEI_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the QEI peripheral.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @api
+ */
+void qeiStop(QEIDriver *qeip) {
+
+ osalDbgCheck(qeip != NULL);
+
+ osalSysLock();
+ osalDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
+ "invalid state");
+ qei_lld_stop(qeip);
+ qeip->state = QEI_STOP;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables the quadrature encoder interface.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @api
+ */
+void qeiEnable(QEIDriver *qeip) {
+
+ osalDbgCheck(qeip != NULL);
+
+ osalSysLock();
+ osalDbgAssert(qeip->state == QEI_READY, "invalid state");
+ qei_lld_enable(qeip);
+ qeip->state = QEI_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Disables the quadrature encoder interface.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ *
+ * @api
+ */
+void qeiDisable(QEIDriver *qeip) {
+
+ osalDbgCheck(qeip != NULL);
+
+ osalSysLock();
+ osalDbgAssert((qeip->state == QEI_READY) || (qeip->state == QEI_ACTIVE),
+ "invalid state");
+ qei_lld_disable(qeip);
+ qeip->state = QEI_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Returns the counter value.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @return The current counter value.
+ *
+ * @api
+ */
+qeicnt_t qeiGetCount(QEIDriver *qeip) {
+ qeicnt_t cnt;
+
+ osalSysLock();
+ cnt = qeiGetCountI(qeip);
+ osalSysUnlock();
+
+ return cnt;
+}
+
+/**
+ * @brief Returns the counter delta from last reading.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @return The delta from last read.
+ *
+ * @api
+ */
+qeidelta_t qeiUpdate(QEIDriver *qeip) {
+ qeidelta_t diff;
+
+ osalSysLock();
+ diff = qeiUpdateI(qeip);
+ osalSysUnlock();
+
+ return diff;
+}
+
+/**
+ * @brief Returns the counter delta from last reading.
+ *
+ * @param[in] qeip pointer to the @p QEIDriver object
+ * @return The delta from last read.
+ *
+ * @iclass
+ */
+qeidelta_t qeiUpdateI(QEIDriver *qeip) {
+ qeicnt_t cnt;
+ qeidelta_t delta;
+
+ osalDbgCheckClassI();
+ osalDbgCheck(qeip != NULL);
+ osalDbgAssert((qeip->state == QEI_READY) || (qeip->state == QEI_ACTIVE),
+ "invalid state");
+
+ cnt = qei_lld_get_count(qeip);
+ delta = cnt - qeip->last;
+ qeip->last = cnt;
+
+ return delta;
+}
+
+#endif /* HAL_USE_QEI == TRUE */
+
+/** @} */
diff --git a/os/hal/src/hal_usb_hid.c b/os/hal/src/hal_usb_hid.c
new file mode 100644
index 0000000..56be9b7
--- /dev/null
+++ b/os/hal/src/hal_usb_hid.c
@@ -0,0 +1,581 @@
+/*
+ ChibiOS - Copyright (C) 2016 Jonathan Struebel
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb_hid.c
+ * @brief USB HID Driver code.
+ *
+ * @addtogroup USB_HID
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_USB_HID == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static uint16_t get_hword(uint8_t *p) {
+ uint16_t hw;
+
+ hw = (uint16_t)*p++;
+ hw |= (uint16_t)*p << 8U;
+ return hw;
+}
+
+/*
+ * Interface implementation.
+ */
+
+static size_t write(void *ip, const uint8_t *bp, size_t n) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return 0;
+ }
+
+ return obqWriteTimeout(&((USBHIDDriver *)ip)->obqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static size_t read(void *ip, uint8_t *bp, size_t n) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return 0;
+ }
+
+ return ibqReadTimeout(&((USBHIDDriver *)ip)->ibqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static msg_t put(void *ip, uint8_t b) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return MSG_RESET;
+ }
+
+ return obqPutTimeout(&((USBHIDDriver *)ip)->obqueue, b, TIME_INFINITE);
+}
+
+static msg_t get(void *ip) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return MSG_RESET;
+ }
+
+ return ibqGetTimeout(&((USBHIDDriver *)ip)->ibqueue, TIME_INFINITE);
+}
+
+static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return MSG_RESET;
+ }
+
+ return obqPutTimeout(&((USBHIDDriver *)ip)->obqueue, b, timeout);
+}
+
+static msg_t gett(void *ip, systime_t timeout) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return MSG_RESET;
+ }
+
+ return ibqGetTimeout(&((USBHIDDriver *)ip)->ibqueue, timeout);
+}
+
+static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return 0;
+ }
+
+ return obqWriteTimeout(&((USBHIDDriver *)ip)->obqueue, bp, n, timeout);
+}
+
+static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) {
+
+ if (usbGetDriverStateI(((USBHIDDriver *)ip)->config->usbp) != USB_ACTIVE) {
+ return 0;
+ }
+
+ return ibqReadTimeout(&((USBHIDDriver *)ip)->ibqueue, bp, n, timeout);
+}
+
+static void flush(void *ip) {
+
+ obqFlush(&((USBHIDDriver *)ip)->obqueue);
+}
+
+static const struct USBHIDDriverVMT vmt = {
+ write, read, put, get,
+ putt, gett, writet, readt,
+ flush
+};
+
+/**
+ * @brief Notification of empty buffer released into the input buffers queue.
+ *
+ * @param[in] bqp the buffers queue pointer.
+ */
+static void ibnotify(io_buffers_queue_t *bqp) {
+ USBHIDDriver *uhdp = bqGetLinkX(bqp);
+
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if ((usbGetDriverStateI(uhdp->config->usbp) != USB_ACTIVE) ||
+ (uhdp->state != HID_READY)) {
+ return;
+ }
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (!usbGetReceiveStatusI(uhdp->config->usbp, uhdp->config->int_out)) {
+ /* Trying to get a free buffer.*/
+ uint8_t *buf = ibqGetEmptyBufferI(&uhdp->ibqueue);
+ if (buf != NULL) {
+ /* Buffer found, starting a new transaction.*/
+ usbStartReceiveI(uhdp->config->usbp, uhdp->config->int_out,
+ buf, SERIAL_USB_BUFFERS_SIZE);
+ }
+ }
+}
+
+/**
+ * @brief Notification of filled buffer inserted into the output buffers queue.
+ *
+ * @param[in] bqp the buffers queue pointer.
+ */
+static void obnotify(io_buffers_queue_t *bqp) {
+ size_t n;
+ USBHIDDriver *uhdp = bqGetLinkX(bqp);
+
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if ((usbGetDriverStateI(uhdp->config->usbp) != USB_ACTIVE) ||
+ (uhdp->state != HID_READY)) {
+ return;
+ }
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (!usbGetTransmitStatusI(uhdp->config->usbp, uhdp->config->int_in)) {
+ /* Trying to get a full buffer.*/
+ uint8_t *buf = obqGetFullBufferI(&uhdp->obqueue, &n);
+ if (buf != NULL) {
+ /* Buffer found, starting a new transaction.*/
+ usbStartTransmitI(uhdp->config->usbp, uhdp->config->int_in, buf, n);
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief USB HID Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void hidInit(void) {
+}
+
+/**
+ * @brief Initializes a generic full duplex USB HID driver object.
+ * @details The HW dependent part of the initialization has to be performed
+ * outside, usually in the hardware initialization code.
+ *
+ * @param[out] uhdp pointer to a @p USBHIDDriver structure
+ *
+ * @init
+ */
+void hidObjectInit(USBHIDDriver *uhdp) {
+
+ uhdp->vmt = &vmt;
+ osalEventObjectInit(&uhdp->event);
+ uhdp->state = HID_STOP;
+ ibqObjectInit(&uhdp->ibqueue, uhdp->ib,
+ USB_HID_BUFFERS_SIZE, USB_HID_BUFFERS_NUMBER,
+ ibnotify, uhdp);
+ obqObjectInit(&uhdp->obqueue, uhdp->ob,
+ USB_HID_BUFFERS_SIZE, USB_HID_BUFFERS_NUMBER,
+ obnotify, uhdp);
+}
+
+/**
+ * @brief Configures and starts the driver.
+ *
+ * @param[in] uhdp pointer to a @p USBHIDDriver object
+ * @param[in] config the USB HID driver configuration
+ *
+ * @api
+ */
+void hidStart(USBHIDDriver *uhdp, const USBHIDConfig *config) {
+ USBDriver *usbp = config->usbp;
+
+ osalDbgCheck(uhdp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((uhdp->state == HID_STOP) || (uhdp->state == HID_READY),
+ "invalid state");
+ usbp->in_params[config->int_in - 1U] = uhdp;
+ usbp->out_params[config->int_out - 1U] = uhdp;
+ uhdp->config = config;
+ uhdp->state = HID_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the driver.
+ * @details Any thread waiting on the driver's queues will be awakened with
+ * the message @p MSG_RESET.
+ *
+ * @param[in] uhdp pointer to a @p USBHIDDriver object
+ *
+ * @api
+ */
+void hidStop(USBHIDDriver *uhdp) {
+ USBDriver *usbp = uhdp->config->usbp;
+
+ osalDbgCheck(uhdp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((uhdp->state == HID_STOP) || (uhdp->state == HID_READY),
+ "invalid state");
+
+ /* Driver in stopped state.*/
+ usbp->in_params[uhdp->config->int_in - 1U] = NULL;
+ usbp->out_params[uhdp->config->int_out - 1U] = NULL;
+ uhdp->state = HID_STOP;
+
+ /* Enforces a disconnection.*/
+ hidDisconnectI(uhdp);
+ osalOsRescheduleS();
+ osalSysUnlock();
+}
+
+/**
+ * @brief USB device disconnection handler.
+ * @note If this function is not called from an ISR then an explicit call
+ * to @p osalOsRescheduleS() in necessary afterward.
+ *
+ * @param[in] uhdp pointer to a @p USBHIDDriver object
+ *
+ * @iclass
+ */
+void hidDisconnectI(USBHIDDriver *uhdp) {
+
+ /* Queues reset in order to signal the driver stop to the application.*/
+ chnAddFlagsI(uhdp, CHN_DISCONNECTED);
+ ibqResetI(&uhdp->ibqueue);
+ obqResetI(&uhdp->obqueue);
+}
+
+/**
+ * @brief USB device configured handler.
+ *
+ * @param[in] uhdp pointer to a @p USBHIDDriver object
+ *
+ * @iclass
+ */
+void hidConfigureHookI(USBHIDDriver *uhdp) {
+ uint8_t *buf;
+
+ ibqResetI(&uhdp->ibqueue);
+ obqResetI(&uhdp->obqueue);
+ chnAddFlagsI(uhdp, CHN_CONNECTED);
+
+ /* Starts the first OUT transaction immediately.*/
+ buf = ibqGetEmptyBufferI(&uhdp->ibqueue);
+
+ osalDbgAssert(buf != NULL, "no free buffer");
+
+ usbStartReceiveI(uhdp->config->usbp, uhdp->config->int_out,
+ buf, USB_HID_BUFFERS_SIZE);
+}
+
+/**
+ * @brief Default requests hook.
+ * @details Applications wanting to use the USB HID driver can use
+ * this function at the end of the application specific
+ * requests hook. The HID_* requests handled here do not
+ * transfer any data to the application.
+ * The following requests are handled:
+ * - HID_GET_IDLE.
+ * - HID_GET_PROTOCOL.
+ * - HID_SET_REPORT.
+ * - HID_SET_IDLE.
+ * - HID_SET_PROTOCOL.
+ * - USB_REQ_GET_DESCRIPTOR.
+ * .
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The hook status.
+ * @retval true Message handled internally.
+ * @retval false Message not handled.
+ */
+bool hidRequestsHook(USBDriver *usbp) {
+ const USBDescriptor *dp;
+
+ if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
+ switch (usbp->setup[1]) {
+ case HID_GET_IDLE:
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case HID_GET_PROTOCOL:
+ return true;
+ case HID_SET_REPORT:
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case HID_SET_IDLE:
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case HID_SET_PROTOCOL:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /* GET_DESCRIPTOR from interface not handled by default so handle it here */
+ if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) &&
+ ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
+ switch (usbp->setup[1]) {
+ case USB_REQ_GET_DESCRIPTOR:
+ dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2],
+ get_hword(&usbp->setup[4]));
+ if (dp == NULL)
+ return false;
+
+ usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief Default data transmitted callback.
+ * @details The application must use this function as callback for the IN
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep IN endpoint number
+ */
+void hidDataTransmitted(USBDriver *usbp, usbep_t ep) {
+ uint8_t *buf;
+ size_t n;
+ USBHIDDriver *uhdp = usbp->in_params[ep - 1U];
+
+ if (uhdp == NULL) {
+ return;
+ }
+
+ osalSysLockFromISR();
+
+ /* Signaling that space is available in the output queue.*/
+ chnAddFlagsI(uhdp, CHN_OUTPUT_EMPTY);
+
+ /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
+ if (usbp->epc[ep]->in_state->txsize > 0U) {
+ obqReleaseEmptyBufferI(&uhdp->obqueue);
+ }
+
+ /* Checking if there is a buffer ready for transmission.*/
+ buf = obqGetFullBufferI(&uhdp->obqueue, &n);
+
+ if (buf != NULL) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ usbStartTransmitI(usbp, ep, buf, n);
+ }
+ else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
+ ((usbp->epc[ep]->in_state->txsize &
+ ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) {
+ /* Transmit zero sized packet in case the last one has maximum allowed
+ size. Otherwise the recipient may expect more data coming soon and
+ not return buffered data to app. See section 5.8.3 Bulk Transfer
+ Packet Size Constraints of the USB Specification document.*/
+ usbStartTransmitI(usbp, ep, usbp->setup, 0);
+
+ }
+ else {
+ /* Nothing to transmit.*/
+ }
+
+ osalSysUnlockFromISR();
+}
+
+/**
+ * @brief Default data received callback.
+ * @details The application must use this function as callback for the OUT
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep OUT endpoint number
+ */
+void hidDataReceived(USBDriver *usbp, usbep_t ep) {
+ uint8_t *buf;
+ USBHIDDriver *uhdp = usbp->out_params[ep - 1U];
+
+ if (uhdp == NULL) {
+ return;
+ }
+
+ osalSysLockFromISR();
+
+ /* Signaling that data is available in the input queue.*/
+ chnAddFlagsI(uhdp, CHN_INPUT_AVAILABLE);
+
+ /* Posting the filled buffer in the queue.*/
+ ibqPostFullBufferI(&uhdp->ibqueue,
+ usbGetReceiveTransactionSizeX(uhdp->config->usbp, ep));
+
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so a packet is in the buffer for sure. Trying to get a free buffer
+ for the next transaction.*/
+ buf = ibqGetEmptyBufferI(&uhdp->ibqueue);
+ if (buf != NULL) {
+ /* Buffer found, starting a new transaction.*/
+ usbStartReceiveI(uhdp->config->usbp, ep, buf, USB_HID_BUFFERS_SIZE);
+ }
+
+ osalSysUnlockFromISR();
+}
+
+/**
+ * @brief Write HID Report
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or if the queue has been reset.
+ *
+ * @param[in] uhdp pointer to the @p USBHIDDriver object
+ * @param[in] bp pointer to the report data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t hidWriteReport(USBHIDDriver *uhdp, uint8_t *bp, size_t n) {
+ size_t val;
+
+ val = uhdp->vmt->write(uhdp, bp, n);
+
+ if (val > 0)
+ uhdp->vmt->flush(uhdp);
+
+ return val;
+}
+
+/**
+ * @brief Write HID report with timeout
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ *
+ * @param[in] uhdp pointer to the @p USBHIDDriver object
+ * @param[in] bp pointer to the report data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t hidWriteReportt(USBHIDDriver *uhdp, uint8_t *bp, size_t n, systime_t timeout) {
+ size_t val;
+
+ val = uhdp->vmt->writet(uhdp, bp, n, timeout);
+
+ if (val > 0)
+ uhdp->vmt->flush(uhdp);
+
+ return val;
+}
+
+/**
+ * @brief Read HID report
+ * @details The function reads data from an input queue into a buffer.
+ * The operation completes when the specified amount of data has been
+ * transferred or if the queue has been reset.
+ *
+ * @param[in] uhdp pointer to the @p input_buffers_queue_t object
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t hidReadReport(USBHIDDriver *uhdp, uint8_t *bp, size_t n) {
+
+ return uhdp->vmt->read(uhdp, bp, n);
+}
+
+/**
+ * @brief Read HID report with timeout
+ * @details The function reads data from an input queue into a buffer.
+ * The operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ *
+ * @param[in] uhdp pointer to the @p input_buffers_queue_t object
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t hidReadReportt(USBHIDDriver *uhdp, uint8_t *bp, size_t n, systime_t timeout) {
+
+ return uhdp->vmt->readt(uhdp, bp, n, timeout);
+}
+
+#endif /* HAL_USE_USB_HID == TRUE */
+
+/** @} */