Requested changes, general cleanup
This commit is contained in:
parent
172ab190b5
commit
a63df51893
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -77,7 +77,6 @@
|
||||
path = lib/tinyusb
|
||||
url = https://github.com/hathach/tinyusb.git
|
||||
branch = develop
|
||||
ignore = dirty
|
||||
[submodule "tools/huffman"]
|
||||
path = tools/huffman
|
||||
url = https://github.com/tannewt/huffman.git
|
||||
@ -98,4 +97,4 @@
|
||||
url = https://github.com/python-ugame/circuitpython-stage.git
|
||||
[submodule "ports/stm32f4/stm32f4"]
|
||||
path = ports/stm32f4/stm32f4
|
||||
url = https://github.com/hierophect/stm32f4.git
|
||||
url = https://github.com/adafruit/stm32f4.git
|
||||
|
2
main.c
2
main.c
@ -190,7 +190,9 @@ void cleanup_after_vm(supervisor_allocation* heap) {
|
||||
supervisor_move_memory();
|
||||
|
||||
reset_port();
|
||||
#if CIRCUITPY_BOARD
|
||||
reset_board_busses();
|
||||
#endif
|
||||
reset_board();
|
||||
reset_status_led();
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ include ../../py/mkenv.mk
|
||||
include boards/$(BOARD)/mpconfigboard.mk
|
||||
# Port-specific
|
||||
include mpconfigport.mk
|
||||
|
||||
# CircuitPython-specific
|
||||
include $(TOP)/py/circuitpy_mpconfig.mk
|
||||
|
||||
@ -99,9 +100,6 @@ ifeq ($(MCU_SUB_VARIANT), stm32f411xe)
|
||||
C_DEFS = \
|
||||
-DUSE_HAL_DRIVER \
|
||||
-DSTM32F411xE
|
||||
CIRCUITPY_BOARD = 0
|
||||
CIRCUITPY_DIGITALIO = 0
|
||||
CIRCUITPY_MICROCONTROLLER = 0
|
||||
endif
|
||||
|
||||
#TODO: Add ASM Flags? -Werror
|
||||
@ -185,7 +183,8 @@ SRC_C += \
|
||||
mphalport.c \
|
||||
tick.c \
|
||||
boards/$(BOARD)/board.c \
|
||||
boards/$(BOARD)/pins.c \
|
||||
peripherals/stm32f4/$(MCU_SUB_VARIANT)/clocks.c \
|
||||
peripherals/stm32f4/$(MCU_SUB_VARIANT)/gpio.c \
|
||||
lib/libc/string0.c \
|
||||
lib/mp-readline/readline.c \
|
||||
lib/oofatfs/ff.c \
|
||||
@ -204,7 +203,8 @@ SRC_C += lib/tinyusb/src/portable/st/stm32f4/dcd_stm32f4.c
|
||||
endif
|
||||
|
||||
ifeq ($(MCU_SUB_VARIANT), stm32f412zx)
|
||||
SRC_C += peripherals/stm32f4/stm32f412zg/pins.c
|
||||
SRC_C += peripherals/stm32f4/stm32f412zx/pins.c
|
||||
SRC_C += boards/$(BOARD)/pins.c
|
||||
endif
|
||||
|
||||
SRC_S = \
|
||||
|
@ -32,4 +32,4 @@
|
||||
void background_tasks_reset(void);
|
||||
void run_background_tasks(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_BACKGROUND_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_BACKGROUND_H
|
||||
|
@ -1,217 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_it.c
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "stm32f4xx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief This function handles Non maskable interrupt.
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 0 */
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Hard fault interrupt.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN HardFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END HardFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
|
||||
/* USER CODE END W1_HardFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Memory management fault.
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
|
||||
|
||||
/* USER CODE END MemoryManagement_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
|
||||
/* USER CODE END W1_MemoryManagement_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pre-fetch fault, memory access fault.
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN BusFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END BusFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
|
||||
/* USER CODE END W1_BusFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Undefined instruction or illegal state.
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN UsageFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END UsageFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
|
||||
/* USER CODE END W1_UsageFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System service call via SWI instruction.
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SVCall_IRQn 0 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 0 */
|
||||
/* USER CODE BEGIN SVCall_IRQn 1 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Debug monitor.
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 0 */
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pendable request for system service.
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN PendSV_IRQn 0 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 0 */
|
||||
/* USER CODE BEGIN PendSV_IRQn 1 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System tick timer.
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SysTick_IRQn 0 */
|
||||
|
||||
/* USER CODE END SysTick_IRQn 0 */
|
||||
HAL_IncTick();
|
||||
/* USER CODE BEGIN SysTick_IRQn 1 */
|
||||
|
||||
/* USER CODE END SysTick_IRQn 1 */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32F4xx Peripheral Interrupt Handlers */
|
||||
/* Add here the Interrupt Handlers for the used peripherals. */
|
||||
/* For the available peripheral interrupt handler names, */
|
||||
/* please refer to the startup file (startup_stm32f4xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles USB On The Go FS global interrupt.
|
||||
*/
|
||||
void OTG_FS_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN OTG_FS_IRQn 0 */
|
||||
|
||||
/* USER CODE END OTG_FS_IRQn 0 */
|
||||
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
|
||||
/* USER CODE BEGIN OTG_FS_IRQn 1 */
|
||||
|
||||
/* USER CODE END OTG_FS_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -1,70 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_it.h
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F4xx_IT_H
|
||||
#define __STM32F4xx_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
void OTG_FS_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F4xx_IT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -1,18 +0,0 @@
|
||||
USB_VID = 0x239A
|
||||
USB_PID = 0x802A
|
||||
USB_PRODUCT = "A glorious potato"
|
||||
USB_MANUFACTURER = "Adafruit Industries LLC"
|
||||
|
||||
#USB_VID = 0x483
|
||||
#USB_PID = 0x572B
|
||||
#USB_PRODUCT = "STM32 Human Interface Potato"
|
||||
#USB_MANUFACTURER = "STMicroelectronics"
|
||||
|
||||
MCU_SERIES = m4
|
||||
MCU_VARIANT = stm32f4
|
||||
MCU_SUB_VARIANT = stm32f412zx
|
||||
CMSIS_MCU = STM32F412xG
|
||||
LD_FILE = boards/STM32F412ZGTx_FLASH.ld
|
||||
TEXT0_ADDR = 0x08000000
|
||||
TEXT1_ADDR = 0x08020000
|
||||
|
@ -1,217 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_it.c
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "stm32f4xx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief This function handles Non maskable interrupt.
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 0 */
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Hard fault interrupt.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN HardFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END HardFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
|
||||
/* USER CODE END W1_HardFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Memory management fault.
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
|
||||
|
||||
/* USER CODE END MemoryManagement_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
|
||||
/* USER CODE END W1_MemoryManagement_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pre-fetch fault, memory access fault.
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN BusFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END BusFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
|
||||
/* USER CODE END W1_BusFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Undefined instruction or illegal state.
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN UsageFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END UsageFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
|
||||
/* USER CODE END W1_UsageFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System service call via SWI instruction.
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SVCall_IRQn 0 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 0 */
|
||||
/* USER CODE BEGIN SVCall_IRQn 1 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Debug monitor.
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 0 */
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pendable request for system service.
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN PendSV_IRQn 0 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 0 */
|
||||
/* USER CODE BEGIN PendSV_IRQn 1 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 1 */
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @brief This function handles System tick timer.
|
||||
// */
|
||||
// void SysTick_Handler(void)
|
||||
// {
|
||||
// /* USER CODE BEGIN SysTick_IRQn 0 */
|
||||
|
||||
// /* USER CODE END SysTick_IRQn 0 */
|
||||
// HAL_IncTick();
|
||||
// /* USER CODE BEGIN SysTick_IRQn 1 */
|
||||
|
||||
// /* USER CODE END SysTick_IRQn 1 */
|
||||
// }
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32F4xx Peripheral Interrupt Handlers */
|
||||
/* Add here the Interrupt Handlers for the used peripherals. */
|
||||
/* For the available peripheral interrupt handler names, */
|
||||
/* please refer to the startup file (startup_stm32f4xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles USB On The Go FS global interrupt.
|
||||
*/
|
||||
// void OTG_FS_IRQHandler(void)
|
||||
// {
|
||||
// /* USER CODE BEGIN OTG_FS_IRQn 0 */
|
||||
|
||||
// /* USER CODE END OTG_FS_IRQn 0 */
|
||||
// // HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
|
||||
// /* USER CODE BEGIN OTG_FS_IRQn 1 */
|
||||
|
||||
// /* USER CODE END OTG_FS_IRQn 1 */
|
||||
// }
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -1,70 +0,0 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_it.h
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F4xx_IT_H
|
||||
#define __STM32F4xx_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
//void SysTick_Handler(void);
|
||||
//void OTG_FS_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F4xx_IT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -1,6 +1,6 @@
|
||||
USB_VID = 0x239A
|
||||
USB_PID = 0x802A
|
||||
USB_PRODUCT = "A glorious potato"
|
||||
USB_PRODUCT = "STM32F411RE Discovery Board - CPy"
|
||||
USB_MANUFACTURER = "Adafruit Industries LLC"
|
||||
|
||||
MCU_SERIES = m4
|
@ -62,7 +62,7 @@
|
||||
/* #define HAL_MMC_MODULE_ENABLED */
|
||||
#define HAL_SPI_MODULE_ENABLED
|
||||
/* #define HAL_TIM_MODULE_ENABLED */
|
||||
/* #define HAL_UART_MODULE_ENABLED */
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
/* #define HAL_USART_MODULE_ENABLED */
|
||||
/* #define HAL_IRDA_MODULE_ENABLED */
|
||||
/* #define HAL_SMARTCARD_MODULE_ENABLED */
|
13
ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk
Normal file
13
ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk
Normal file
@ -0,0 +1,13 @@
|
||||
USB_VID = 0x483
|
||||
USB_PID = 0x572B
|
||||
USB_PRODUCT = "STM32F412ZG Discovery Board - CPy"
|
||||
USB_MANUFACTURER = "STMicroelectronics"
|
||||
|
||||
MCU_SERIES = m4
|
||||
MCU_VARIANT = stm32f4
|
||||
MCU_SUB_VARIANT = stm32f412zx
|
||||
CMSIS_MCU = STM32F412xG
|
||||
LD_FILE = boards/STM32F412ZGTx_FLASH.ld
|
||||
TEXT0_ADDR = 0x08000000
|
||||
TEXT1_ADDR = 0x08020000
|
||||
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/analogio/AnalogIn.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#include "nrfx_saadc.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#define CHANNEL_NO 0
|
||||
|
||||
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin) {
|
||||
if (pin->adc_channel == 0)
|
||||
mp_raise_ValueError(translate("Pin does not have ADC capabilities"));
|
||||
|
||||
nrf_gpio_cfg_default(pin->number);
|
||||
|
||||
claim_pin(pin);
|
||||
self->pin = pin;
|
||||
}
|
||||
|
||||
bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) {
|
||||
return self->pin == mp_const_none;
|
||||
}
|
||||
|
||||
void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
|
||||
if (common_hal_analogio_analogin_deinited(self))
|
||||
return;
|
||||
|
||||
nrf_gpio_cfg_default(self->pin->number);
|
||||
|
||||
reset_pin_number(self->pin->number);
|
||||
self->pin = mp_const_none;
|
||||
}
|
||||
|
||||
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
|
||||
// Something else might have used the ADC in a different way,
|
||||
// so we completely re-initialize it.
|
||||
|
||||
nrf_saadc_value_t value;
|
||||
|
||||
const nrf_saadc_channel_config_t config = {
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED,
|
||||
.gain = NRF_SAADC_GAIN1_6,
|
||||
.reference = NRF_SAADC_REFERENCE_INTERNAL,
|
||||
.acq_time = NRF_SAADC_ACQTIME_3US,
|
||||
.mode = NRF_SAADC_MODE_SINGLE_ENDED,
|
||||
.burst = NRF_SAADC_BURST_DISABLED,
|
||||
.pin_p = self->pin->adc_channel,
|
||||
.pin_n = self->pin->adc_channel,
|
||||
};
|
||||
|
||||
nrf_saadc_resolution_set(NRF_SAADC_RESOLUTION_14BIT);
|
||||
nrf_saadc_oversample_set(NRF_SAADC_OVERSAMPLE_DISABLED);
|
||||
nrf_saadc_enable();
|
||||
|
||||
for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; i++)
|
||||
nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
|
||||
|
||||
nrf_saadc_channel_init(CHANNEL_NO, &config);
|
||||
nrf_saadc_buffer_init(&value, 1);
|
||||
|
||||
nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
|
||||
while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
|
||||
nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
|
||||
|
||||
nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
|
||||
while (nrf_saadc_event_check(NRF_SAADC_EVENT_END) == 0);
|
||||
nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
|
||||
|
||||
nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
|
||||
while (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED) == 0);
|
||||
nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
|
||||
|
||||
nrf_saadc_disable();
|
||||
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
|
||||
// Map value to from 14 to 16 bits
|
||||
return (value << 2);
|
||||
}
|
||||
|
||||
float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
|
||||
return 3.3f;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGIN_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGIN_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t * pin;
|
||||
} analogio_analogin_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGIN_H
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/analogio/AnalogOut.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, const mcu_pin_obj_t *pin) {
|
||||
mp_raise_RuntimeError(translate("AnalogOut functionality not supported"));
|
||||
}
|
||||
|
||||
bool common_hal_analogio_analogout_deinited(analogio_analogout_obj_t *self) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {
|
||||
}
|
||||
|
||||
void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self, uint16_t value) {
|
||||
}
|
@ -1 +0,0 @@
|
||||
// No analogio module functions.
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble.h"
|
||||
#include "ble_drv.h"
|
||||
#include "nrfx_power.h"
|
||||
#include "nrf_nvic.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
|
||||
#include "supervisor/usb.h"
|
||||
|
||||
STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) {
|
||||
mp_raise_msg_varg(&mp_type_AssertionError,
|
||||
translate("Soft device assert, id: 0x%08lX, pc: 0x%08lX"), id, pc);
|
||||
}
|
||||
|
||||
STATIC uint32_t ble_stack_enable(void) {
|
||||
nrf_clock_lf_cfg_t clock_config = {
|
||||
.source = NRF_CLOCK_LF_SRC_XTAL,
|
||||
.accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM
|
||||
};
|
||||
|
||||
uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
return err_code;
|
||||
|
||||
err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
return err_code;
|
||||
|
||||
// Start with no event handlers, etc.
|
||||
ble_drv_reset();
|
||||
|
||||
uint32_t app_ram_start;
|
||||
app_ram_start = 0x20004000;
|
||||
|
||||
ble_cfg_t ble_conf;
|
||||
ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM;
|
||||
ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLE_GAP_CONN_COUNT_DEFAULT;
|
||||
ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT;
|
||||
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
return err_code;
|
||||
|
||||
memset(&ble_conf, 0, sizeof(ble_conf));
|
||||
ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1;
|
||||
ble_conf.gap_cfg.role_count_cfg.central_role_count = 1;
|
||||
err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
return err_code;
|
||||
|
||||
memset(&ble_conf, 0, sizeof(ble_conf));
|
||||
ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM;
|
||||
ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS;
|
||||
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
return err_code;
|
||||
|
||||
err_code = sd_ble_enable(&app_ram_start);
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
void common_hal_bleio_adapter_set_enabled(bool enabled) {
|
||||
const bool is_enabled = common_hal_bleio_adapter_get_enabled();
|
||||
|
||||
// Don't enable or disable twice
|
||||
if ((is_enabled && enabled) || (!is_enabled && !enabled)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t err_code;
|
||||
if (enabled) {
|
||||
// The SD takes over the POWER module and will fail if the module is already in use.
|
||||
// Occurs when USB is initialized previously
|
||||
nrfx_power_uninit();
|
||||
|
||||
err_code = ble_stack_enable();
|
||||
|
||||
// Re-init USB hardware
|
||||
init_usb_hardware();
|
||||
} else {
|
||||
err_code = sd_softdevice_disable();
|
||||
|
||||
// Re-init USB hardware
|
||||
init_usb_hardware();
|
||||
}
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to change softdevice state"));
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_bleio_adapter_get_enabled(void) {
|
||||
uint8_t is_enabled;
|
||||
|
||||
const uint32_t err_code = sd_softdevice_is_enabled(&is_enabled);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to get softdevice state"));
|
||||
}
|
||||
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) {
|
||||
ble_gap_addr_t local_address;
|
||||
uint32_t err_code;
|
||||
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
#if (BLE_API_VERSION == 2)
|
||||
err_code = sd_ble_gap_address_get(&local_address);
|
||||
#else
|
||||
err_code = sd_ble_gap_addr_get(&local_address);
|
||||
#endif
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to get local address"));
|
||||
}
|
||||
|
||||
address->type = local_address.addr_type;
|
||||
memcpy(address->value, local_address.addr, BLEIO_ADDRESS_BYTES);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} super_adapter_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ble.h"
|
||||
#include "ble_drv.h"
|
||||
#include "ble_hci.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "common-hal/bleio/Broadcaster.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
#include "shared-bindings/bleio/Broadcaster.h"
|
||||
|
||||
static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
|
||||
|
||||
void common_hal_bleio_broadcaster_construct(bleio_broadcaster_obj_t *self, mp_float_t interval) {
|
||||
common_hal_bleio_adapter_set_enabled(true); // TODO -- Do this somewhere else maybe bleio __init__
|
||||
const mp_float_t min = BLE_GAP_ADV_INTERVAL_MIN * ADV_INTERVAL_UNIT_FLOAT_SECS;
|
||||
const mp_float_t max = BLE_GAP_ADV_INTERVAL_MAX * ADV_INTERVAL_UNIT_FLOAT_SECS;
|
||||
|
||||
if (interval < min || interval > max) {
|
||||
// Would like to print range using the constants above, but vargs would convert to double.
|
||||
mp_raise_ValueError(translate("interval not in range 0.0020 to 10.24"));
|
||||
}
|
||||
self->interval = interval;
|
||||
}
|
||||
|
||||
|
||||
void common_hal_bleio_broadcaster_start_advertising(bleio_broadcaster_obj_t *self, mp_buffer_info_t *data) {
|
||||
uint32_t err_code;
|
||||
|
||||
if (data->len >= BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
memcpy(self->adv_data, data->buf, data->len);
|
||||
|
||||
ble_gap_adv_params_t m_adv_params = {
|
||||
.interval = (uint32_t) (self->interval / ADV_INTERVAL_UNIT_FLOAT_SECS),
|
||||
.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED,
|
||||
.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
|
||||
.filter_policy = BLE_GAP_ADV_FP_ANY,
|
||||
.primary_phy = BLE_GAP_PHY_1MBPS,
|
||||
};
|
||||
|
||||
common_hal_bleio_broadcaster_stop_advertising(self);
|
||||
|
||||
const ble_gap_adv_data_t ble_gap_adv_data = {
|
||||
.adv_data.p_data = self->adv_data,
|
||||
.adv_data.len = data->len,
|
||||
};
|
||||
|
||||
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params);
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
|
||||
}
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_broadcaster_stop_advertising(bleio_broadcaster_obj_t *self) {
|
||||
|
||||
if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t err_code = sd_ble_gap_adv_stop(m_adv_handle);
|
||||
|
||||
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
|
||||
|
||||
#include "ble.h"
|
||||
|
||||
#include "shared-module/bleio/__init__.h"
|
||||
#include "shared-module/bleio/Address.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
// In seconds.
|
||||
mp_float_t interval;
|
||||
// The advertising data buffer is held by us, not by the SD, so we must
|
||||
// maintain it and not change it. If we need to change its contents during advertising,
|
||||
// there are tricks to get the SD to notice (see DevZone - TBS).
|
||||
uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
|
||||
|
||||
} bleio_broadcaster_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ble_drv.h"
|
||||
#include "ble_gatts.h"
|
||||
#include "nrf_soc.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/bleio/__init__.h"
|
||||
#include "common-hal/bleio/Characteristic.h"
|
||||
#include "shared-module/bleio/Characteristic.h"
|
||||
|
||||
STATIC volatile bleio_characteristic_obj_t *m_read_characteristic;
|
||||
STATIC volatile uint8_t m_tx_in_progress;
|
||||
// Serialize gattc writes that send a response. This might be done per object?
|
||||
STATIC nrf_mutex_t *m_write_mutex;
|
||||
|
||||
STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
uint16_t cccd;
|
||||
ble_gatts_value_t value = {
|
||||
.p_value = (uint8_t*) &cccd,
|
||||
.len = 2,
|
||||
};
|
||||
|
||||
const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value);
|
||||
|
||||
|
||||
if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
|
||||
// CCCD is not set, so say that neither Notify nor Indicate is enabled.
|
||||
cccd = 0;
|
||||
} else if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to read CCCD value, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
return cccd;
|
||||
}
|
||||
|
||||
STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) {
|
||||
// This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
|
||||
// we can still read and write the local value.
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
ble_gatts_value_t gatts_value = {
|
||||
.p_value = NULL,
|
||||
.len = 0,
|
||||
};
|
||||
|
||||
// Read once to find out what size buffer we need, then read again to fill buffer.
|
||||
|
||||
uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len);
|
||||
mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE);
|
||||
gatts_value.p_value = bufinfo.buf;
|
||||
|
||||
// Read again, with the correct size of buffer.
|
||||
err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
|
||||
}
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
|
||||
// This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
|
||||
// we can still read and write the local value.
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
|
||||
ble_gatts_value_t gatts_value = {
|
||||
.p_value = bufinfo->buf,
|
||||
.len = bufinfo->len,
|
||||
};
|
||||
|
||||
const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
|
||||
uint16_t hvx_len = bufinfo->len;
|
||||
|
||||
ble_gatts_hvx_params_t hvx_params = {
|
||||
.handle = characteristic->handle,
|
||||
.type = hvx_type,
|
||||
.offset = 0,
|
||||
.p_len = &hvx_len,
|
||||
.p_data = bufinfo->buf,
|
||||
};
|
||||
|
||||
while (m_tx_in_progress >= MAX_TX_IN_PROGRESS) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
m_tx_in_progress++;
|
||||
const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
m_tx_in_progress--;
|
||||
mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) {
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
|
||||
m_read_characteristic = characteristic;
|
||||
|
||||
const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
//
|
||||
while (m_read_characteristic != NULL) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
|
||||
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
|
||||
uint32_t err_code;
|
||||
|
||||
ble_gattc_write_params_t write_params = {
|
||||
.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL,
|
||||
.write_op = BLE_GATT_OP_WRITE_REQ,
|
||||
.handle = characteristic->handle,
|
||||
.p_value = bufinfo->buf,
|
||||
.len = bufinfo->len,
|
||||
};
|
||||
|
||||
if (characteristic->props.write_no_response) {
|
||||
write_params.write_op = BLE_GATT_OP_WRITE_CMD;
|
||||
|
||||
err_code = sd_mutex_acquire(m_write_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to acquire mutex, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
while (sd_mutex_acquire(m_write_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
err_code = sd_mutex_release(m_write_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to release mutex, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) {
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
|
||||
{
|
||||
uint8_t count = ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;
|
||||
// Don't underflow the count.
|
||||
if (count >= m_tx_in_progress) {
|
||||
m_tx_in_progress = 0;
|
||||
} else {
|
||||
m_tx_in_progress -= count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP:
|
||||
{
|
||||
ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data);
|
||||
// Flag to busy-wait loop that we've read the characteristic.
|
||||
m_read_characteristic = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GATTC_EVT_WRITE_RSP:
|
||||
// Someone else can write now.
|
||||
sd_mutex_release(m_write_mutex);
|
||||
break;
|
||||
|
||||
// For debugging.
|
||||
default:
|
||||
// mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props) {
|
||||
self->service = NULL;
|
||||
self->uuid = uuid;
|
||||
self->value_data = NULL;
|
||||
self->props = props;
|
||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||
|
||||
ble_drv_add_event_handler(characteristic_on_ble_evt, self);
|
||||
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
|
||||
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
|
||||
case GATT_ROLE_CLIENT:
|
||||
gattc_read(self);
|
||||
break;
|
||||
|
||||
case GATT_ROLE_SERVER:
|
||||
gatts_read(self);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_RuntimeError(translate("bad GATT role"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||
bool sent = false;
|
||||
uint16_t cccd = 0;
|
||||
|
||||
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
|
||||
case GATT_ROLE_SERVER:
|
||||
if (self->props.notify || self->props.indicate) {
|
||||
cccd = get_cccd(self);
|
||||
}
|
||||
// It's possible that both notify and indicate are set.
|
||||
if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
|
||||
gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
|
||||
sent = true;
|
||||
}
|
||||
if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
|
||||
gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
|
||||
sent = true;
|
||||
}
|
||||
if (!sent) {
|
||||
gatts_write(self, bufinfo);
|
||||
}
|
||||
break;
|
||||
|
||||
case GATT_ROLE_CLIENT:
|
||||
gattc_write(self, bufinfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_RuntimeError(translate("bad GATT role"));
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
|
||||
|
||||
#include "shared-module/bleio/Characteristic.h"
|
||||
#include "shared-module/bleio/Service.h"
|
||||
#include "common-hal/bleio/UUID.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
bleio_service_obj_t *service;
|
||||
bleio_uuid_obj_t *uuid;
|
||||
mp_obj_t value_data;
|
||||
uint16_t handle;
|
||||
bleio_characteristic_properties_t props;
|
||||
uint16_t user_desc_handle;
|
||||
uint16_t cccd_handle;
|
||||
uint16_t sccd_handle;
|
||||
} bleio_characteristic_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ble_drv.h"
|
||||
#include "ble_gatts.h"
|
||||
#include "nrf_nvic.h"
|
||||
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
#include "common-hal/bleio/__init__.h"
|
||||
#include "common-hal/bleio/CharacteristicBuffer.h"
|
||||
|
||||
STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
|
||||
bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param;
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GATTS_EVT_WRITE: {
|
||||
ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
|
||||
// Event handle must match the handle for my characteristic.
|
||||
if (evt_write->handle == self->characteristic->handle) {
|
||||
// Push all the data onto the ring buffer.
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
for (size_t i = 0; i < evt_write->len; i++) {
|
||||
ringbuf_put(&self->ringbuf, evt_write->data[i]);
|
||||
}
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Assumes that timeout and buffer_size have been validated before call.
|
||||
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
|
||||
bleio_characteristic_obj_t *characteristic,
|
||||
mp_float_t timeout,
|
||||
size_t buffer_size) {
|
||||
|
||||
self->characteristic = characteristic;
|
||||
self->timeout_ms = timeout * 1000;
|
||||
// This is a macro.
|
||||
// true means long-lived, so it won't be moved.
|
||||
ringbuf_alloc(&self->ringbuf, buffer_size, true);
|
||||
|
||||
ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self);
|
||||
|
||||
}
|
||||
|
||||
int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
||||
uint64_t start_ticks = ticks_ms;
|
||||
|
||||
// Wait for all bytes received or timeout
|
||||
while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP ;
|
||||
// Allow user to break out of a timeout with a KeyboardInterrupt.
|
||||
if ( mp_hal_is_interrupted() ) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Copy received data. Lock out write interrupt handler while copying.
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
|
||||
size_t rx_bytes = MIN(ringbuf_count(&self->ringbuf), len);
|
||||
for ( size_t i = 0; i < rx_bytes; i++ ) {
|
||||
data[i] = ringbuf_get(&self->ringbuf);
|
||||
}
|
||||
|
||||
// Writes now OK.
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
|
||||
return rx_bytes;
|
||||
}
|
||||
|
||||
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
uint16_t count = ringbuf_count(&self->ringbuf);
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
return count;
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
|
||||
// prevent conflict with uart irq
|
||||
uint8_t is_nested_critical_region;
|
||||
sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
ringbuf_clear(&self->ringbuf);
|
||||
sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
}
|
||||
|
||||
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
|
||||
return self->characteristic == NULL;
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
|
||||
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
|
||||
ble_drv_remove_event_handler(characteristic_buffer_on_ble_evt, self);
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) {
|
||||
return self->characteristic != NULL &&
|
||||
self->characteristic->service != NULL &&
|
||||
self->characteristic->service->device != NULL &&
|
||||
common_hal_bleio_device_get_conn_handle(self->characteristic->service->device) != BLE_CONN_HANDLE_INVALID;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
|
||||
|
||||
#include "nrf_soc.h"
|
||||
|
||||
#include "py/ringbuf.h"
|
||||
#include "shared-bindings/bleio/Characteristic.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
bleio_characteristic_obj_t *characteristic;
|
||||
uint32_t timeout_ms;
|
||||
// Ring buffer storing consecutive incoming values.
|
||||
ringbuf_t ringbuf;
|
||||
} bleio_characteristic_buffer_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/bleio/Descriptor.h"
|
||||
#include "shared-bindings/bleio/UUID.h"
|
||||
|
||||
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) {
|
||||
// TODO: set handle ???
|
||||
self->uuid = uuid;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) {
|
||||
return self->handle;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
|
||||
return MP_OBJ_FROM_PTR(self->uuid);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "common-hal/bleio/UUID.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint16_t handle;
|
||||
bleio_uuid_obj_t *uuid;
|
||||
} bleio_descriptor_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
|
@ -1,601 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ble.h"
|
||||
#include "ble_drv.h"
|
||||
#include "ble_hci.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
#include "shared-bindings/bleio/Characteristic.h"
|
||||
#include "shared-bindings/bleio/Device.h"
|
||||
#include "shared-bindings/bleio/Service.h"
|
||||
#include "shared-bindings/bleio/UUID.h"
|
||||
|
||||
#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
|
||||
#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS)
|
||||
#define BLE_SLAVE_LATENCY 0
|
||||
#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
|
||||
|
||||
#define BLE_ADV_LENGTH_FIELD_SIZE 1
|
||||
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
|
||||
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
|
||||
|
||||
#ifndef BLE_GAP_ADV_MAX_SIZE
|
||||
#define BLE_GAP_ADV_MAX_SIZE 31
|
||||
#endif
|
||||
|
||||
static bleio_service_obj_t *m_char_discovery_service;
|
||||
static volatile bool m_discovery_successful;
|
||||
static nrf_mutex_t *m_discovery_mutex;
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
|
||||
|
||||
static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN];
|
||||
|
||||
static ble_data_t m_scan_buffer = {
|
||||
.p_data = m_scan_buffer_data,
|
||||
.len = BLE_GAP_SCAN_BUFFER_MIN
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC uint32_t set_advertisement_data(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) {
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE];
|
||||
uint8_t byte_pos = 0;
|
||||
uint32_t err_code;
|
||||
|
||||
#define ADD_FIELD(field, len) \
|
||||
do { \
|
||||
if (byte_pos + (len) > BLE_GAP_ADV_MAX_SIZE) { \
|
||||
mp_raise_ValueError(translate("Data too large for the advertisement packet")); \
|
||||
} \
|
||||
adv_data[byte_pos] = (field); \
|
||||
byte_pos += (len); \
|
||||
} while (0)
|
||||
|
||||
GET_STR_DATA_LEN(device->name, name_data, name_len);
|
||||
if (name_len > 0) {
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
|
||||
|
||||
err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// TODO: Shorten if too long
|
||||
|
||||
ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + name_len, BLE_ADV_LENGTH_FIELD_SIZE);
|
||||
ADD_FIELD(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, BLE_ADV_AD_TYPE_FIELD_SIZE);
|
||||
|
||||
memcpy(&adv_data[byte_pos], name_data, name_len);
|
||||
byte_pos += name_len;
|
||||
}
|
||||
|
||||
// set flags, default to disc mode
|
||||
if (raw_data->len == 0) {
|
||||
ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE, BLE_ADV_LENGTH_FIELD_SIZE);
|
||||
ADD_FIELD(BLE_GAP_AD_TYPE_FLAGS, BLE_AD_TYPE_FLAGS_DATA_SIZE);
|
||||
ADD_FIELD(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, BLE_AD_TYPE_FLAGS_DATA_SIZE);
|
||||
} else {
|
||||
if (byte_pos + raw_data->len > BLE_GAP_ADV_MAX_SIZE) {
|
||||
mp_raise_ValueError(translate("Data too large for the advertisement packet"));
|
||||
}
|
||||
|
||||
memcpy(&adv_data[byte_pos], raw_data->buf, raw_data->len);
|
||||
byte_pos += raw_data->len;
|
||||
}
|
||||
|
||||
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list);
|
||||
if (service_list->len > 0) {
|
||||
bool has_128bit_services = false;
|
||||
bool has_16bit_services = false;
|
||||
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]);
|
||||
|
||||
if (service->is_secondary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (common_hal_bleio_uuid_get_size(service->uuid)) {
|
||||
case 16:
|
||||
has_16bit_services = true;
|
||||
break;
|
||||
case 128:
|
||||
has_128bit_services = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_16bit_services) {
|
||||
const uint8_t size_byte_pos = byte_pos;
|
||||
uint8_t uuid_total_size = 0;
|
||||
|
||||
// skip length byte for now, apply total length post calculation
|
||||
byte_pos += BLE_ADV_LENGTH_FIELD_SIZE;
|
||||
|
||||
ADD_FIELD(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE);
|
||||
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]);
|
||||
uint8_t encoded_size = 0;
|
||||
|
||||
if (common_hal_bleio_uuid_get_size(service->uuid) != 16 || service->is_secondary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||
|
||||
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
uuid_total_size += encoded_size;
|
||||
byte_pos += encoded_size;
|
||||
}
|
||||
|
||||
adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size);
|
||||
}
|
||||
|
||||
if (has_128bit_services) {
|
||||
const uint8_t size_byte_pos = byte_pos;
|
||||
uint8_t uuid_total_size = 0;
|
||||
|
||||
// skip length byte for now, apply total length post calculation
|
||||
byte_pos += BLE_ADV_LENGTH_FIELD_SIZE;
|
||||
|
||||
ADD_FIELD(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE);
|
||||
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]);
|
||||
uint8_t encoded_size = 0;
|
||||
|
||||
if (common_hal_bleio_uuid_get_size(service->uuid) != 16 || service->is_secondary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||
|
||||
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
uuid_total_size += encoded_size;
|
||||
byte_pos += encoded_size;
|
||||
}
|
||||
|
||||
adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size);
|
||||
}
|
||||
}
|
||||
|
||||
#if (BLUETOOTH_SD == 132)
|
||||
err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ble_gap_adv_params_t m_adv_params = {
|
||||
.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED,
|
||||
.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
|
||||
.filter_policy = BLE_GAP_ADV_FP_ANY,
|
||||
.primary_phy = BLE_GAP_PHY_1MBPS,
|
||||
#else
|
||||
.type = BLE_GAP_ADV_TYPE_ADV_IND,
|
||||
.fp = BLE_GAP_ADV_FP_ANY,
|
||||
#endif
|
||||
};
|
||||
|
||||
if (!connectable) {
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
|
||||
#else
|
||||
m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
|
||||
#endif
|
||||
}
|
||||
|
||||
common_hal_bleio_device_stop_advertising(device);
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
const ble_gap_adv_data_t ble_gap_adv_data = {
|
||||
.adv_data.p_data = adv_data,
|
||||
.adv_data.len = byte_pos,
|
||||
};
|
||||
|
||||
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
|
||||
#elif (BLUETOOTH_SD == 132 && BLE_API_VERSION == 4)
|
||||
err_code = sd_ble_gap_adv_start(&m_adv_params, BLE_CONN_CFG_TAG_CUSTOM);
|
||||
#else
|
||||
err_code = sd_ble_gap_adv_start(&m_adv_params);
|
||||
#endif
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
STATIC bool discover_services(bleio_device_obj_t *device, uint16_t start_handle) {
|
||||
m_discovery_successful = false;
|
||||
|
||||
uint32_t err_code = sd_ble_gattc_primary_services_discover(device->conn_handle, start_handle, NULL);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to discover services"));
|
||||
}
|
||||
|
||||
// Serialize discovery.
|
||||
err_code = sd_mutex_acquire(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to acquire mutex"));
|
||||
}
|
||||
|
||||
// Wait for someone else to release m_discovery_mutex.
|
||||
while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
err_code = sd_mutex_release(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to release mutex"));
|
||||
}
|
||||
|
||||
return m_discovery_successful;
|
||||
}
|
||||
|
||||
STATIC bool discover_characteristics(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle) {
|
||||
m_char_discovery_service = service;
|
||||
|
||||
ble_gattc_handle_range_t handle_range;
|
||||
handle_range.start_handle = start_handle;
|
||||
handle_range.end_handle = service->end_handle;
|
||||
|
||||
m_discovery_successful = false;
|
||||
|
||||
uint32_t err_code = sd_ble_gattc_characteristics_discover(device->conn_handle, &handle_range);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
err_code = sd_mutex_acquire(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to acquire mutex"));
|
||||
}
|
||||
|
||||
while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
err_code = sd_mutex_release(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to release mutex"));
|
||||
}
|
||||
|
||||
return m_discovery_successful;
|
||||
}
|
||||
|
||||
STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_device_obj_t *device) {
|
||||
for (size_t i = 0; i < response->count; ++i) {
|
||||
ble_gattc_service_t *gattc_service = &response->services[i];
|
||||
|
||||
bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
|
||||
service->base.type = &bleio_service_type;
|
||||
service->device = device;
|
||||
service->char_list = mp_obj_new_list(0, NULL);
|
||||
service->start_handle = gattc_service->handle_range.start_handle;
|
||||
service->end_handle = gattc_service->handle_range.end_handle;
|
||||
service->handle = gattc_service->handle_range.start_handle;
|
||||
|
||||
bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
|
||||
service->uuid = uuid;
|
||||
|
||||
mp_obj_list_append(device->service_list, service);
|
||||
}
|
||||
|
||||
if (response->count > 0) {
|
||||
m_discovery_successful = true;
|
||||
}
|
||||
|
||||
const uint32_t err_code = sd_mutex_release(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to release mutex"));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_device_obj_t *device) {
|
||||
for (size_t i = 0; i < response->count; ++i) {
|
||||
ble_gattc_char_t *gattc_char = &response->chars[i];
|
||||
|
||||
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
uuid->base.type = &bleio_uuid_type;
|
||||
bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
|
||||
characteristic->uuid = uuid;
|
||||
|
||||
characteristic->props.broadcast = gattc_char->char_props.broadcast;
|
||||
characteristic->props.indicate = gattc_char->char_props.indicate;
|
||||
characteristic->props.notify = gattc_char->char_props.notify;
|
||||
characteristic->props.read = gattc_char->char_props.read;
|
||||
characteristic->props.write = gattc_char->char_props.write;
|
||||
characteristic->props.write_no_response = gattc_char->char_props.write_wo_resp;
|
||||
characteristic->handle = gattc_char->handle_value;
|
||||
characteristic->service = m_char_discovery_service;
|
||||
|
||||
mp_obj_list_append(m_char_discovery_service->char_list, MP_OBJ_FROM_PTR(characteristic));
|
||||
}
|
||||
|
||||
if (response->count > 0) {
|
||||
m_discovery_successful = true;
|
||||
}
|
||||
|
||||
const uint32_t err_code = sd_mutex_release(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to release mutex"));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void on_adv_report(ble_gap_evt_adv_report_t *report, bleio_device_obj_t *device) {
|
||||
uint32_t err_code;
|
||||
|
||||
if (memcmp(report->peer_addr.addr, device->address.value, BLEIO_ADDRESS_BYTES) != 0) {
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to continue scanning"));
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
ble_gap_scan_params_t scan_params = {
|
||||
.active = 1,
|
||||
.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||
.window = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||
};
|
||||
|
||||
ble_gap_addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.addr_type = report->peer_addr.addr_type;
|
||||
memcpy(addr.addr, report->peer_addr.addr, BLEIO_ADDRESS_BYTES);
|
||||
|
||||
ble_gap_conn_params_t conn_params = {
|
||||
.min_conn_interval = BLE_MIN_CONN_INTERVAL,
|
||||
.max_conn_interval = BLE_MAX_CONN_INTERVAL,
|
||||
.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT,
|
||||
.slave_latency = BLE_SLAVE_LATENCY,
|
||||
};
|
||||
|
||||
#if (BLE_API_VERSION == 2)
|
||||
err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params);
|
||||
#else
|
||||
err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
|
||||
#endif
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to connect:"));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void on_ble_evt(ble_evt_t *ble_evt, void *device_in) {
|
||||
bleio_device_obj_t *device = (bleio_device_obj_t*)device_in;
|
||||
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
{
|
||||
ble_gap_conn_params_t conn_params;
|
||||
device->conn_handle = ble_evt->evt.gap_evt.conn_handle;
|
||||
|
||||
sd_ble_gap_ppcp_get(&conn_params);
|
||||
sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
device->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_ADV_REPORT:
|
||||
on_adv_report(&ble_evt->evt.gap_evt.params.adv_report, device);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
sd_ble_gatts_sys_attr_set(ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0);
|
||||
break;
|
||||
|
||||
#if (BLE_API_VERSION == 4)
|
||||
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
|
||||
sd_ble_gatts_exchange_mtu_reply(device->conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
|
||||
sd_ble_gap_sec_params_reply(device->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
|
||||
{
|
||||
ble_gap_evt_conn_param_update_request_t *request = &ble_evt->evt.gap_evt.params.conn_param_update_request;
|
||||
sd_ble_gap_conn_param_update(device->conn_handle, &request->conn_params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_device_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service) {
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||
|
||||
uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
|
||||
if (service->is_secondary) {
|
||||
service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
|
||||
}
|
||||
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to add service"));
|
||||
}
|
||||
|
||||
const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list);
|
||||
for (size_t i = 0; i < char_list->len; ++i) {
|
||||
bleio_characteristic_obj_t *characteristic = char_list->items[i];
|
||||
common_hal_bleio_service_add_characteristic(service, characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) {
|
||||
if (connectable) {
|
||||
ble_drv_add_event_handler(on_ble_evt, device);
|
||||
}
|
||||
|
||||
const uint32_t err_code = set_advertisement_data(device, connectable, raw_data);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to start advertising"));
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device) {
|
||||
uint32_t err_code;
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
|
||||
return;
|
||||
|
||||
err_code = sd_ble_gap_adv_stop(m_adv_handle);
|
||||
#else
|
||||
err_code = sd_ble_gap_adv_stop();
|
||||
#endif
|
||||
|
||||
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) {
|
||||
mp_raise_OSError_msg(translate("Failed to stop advertising"));
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_device_connect(bleio_device_obj_t *device) {
|
||||
ble_drv_add_event_handler(on_ble_evt, device);
|
||||
|
||||
ble_gap_scan_params_t scan_params = {
|
||||
.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||
.window = MSEC_TO_UNITS(100, UNIT_0_625_MS),
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
.scan_phys = BLE_GAP_PHY_1MBPS,
|
||||
#endif
|
||||
};
|
||||
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
uint32_t err_code;
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer);
|
||||
#else
|
||||
err_code = sd_ble_gap_scan_start(&scan_params);
|
||||
#endif
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to start scanning"));
|
||||
}
|
||||
|
||||
while (device->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: read name
|
||||
|
||||
if (m_discovery_mutex == NULL) {
|
||||
m_discovery_mutex = m_new_ll(nrf_mutex_t, 1);
|
||||
|
||||
err_code = sd_mutex_new(m_discovery_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg(translate("Failed to create mutex"));
|
||||
}
|
||||
}
|
||||
|
||||
// find services
|
||||
bool found_service = discover_services(device, BLE_GATT_HANDLE_START);
|
||||
while (found_service) {
|
||||
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list);
|
||||
const bleio_service_obj_t *service = service_list->items[service_list->len - 1];
|
||||
|
||||
found_service = discover_services(device, service->end_handle + 1);
|
||||
}
|
||||
|
||||
// find characteristics in each service
|
||||
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list);
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
bleio_service_obj_t *service = service_list->items[i];
|
||||
|
||||
bool found_char = discover_characteristics(device, service, service->start_handle);
|
||||
while (found_char) {
|
||||
const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list);
|
||||
const bleio_characteristic_obj_t *characteristic = char_list->items[char_list->len - 1];
|
||||
|
||||
const uint16_t next_handle = characteristic->handle + 1;
|
||||
if (next_handle >= service->end_handle) {
|
||||
break;
|
||||
}
|
||||
|
||||
found_char = discover_characteristics(device, service, next_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_device_disconnect(bleio_device_obj_t *device) {
|
||||
sd_ble_gap_disconnect(device->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
}
|
@ -1,346 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ble.h"
|
||||
#include "ble_drv.h"
|
||||
#include "ble_hci.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
#include "shared-bindings/bleio/Characteristic.h"
|
||||
#include "shared-bindings/bleio/Peripheral.h"
|
||||
#include "shared-bindings/bleio/Service.h"
|
||||
#include "shared-bindings/bleio/UUID.h"
|
||||
|
||||
#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
|
||||
#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS)
|
||||
#define BLE_SLAVE_LATENCY 0
|
||||
#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
|
||||
|
||||
#define BLE_ADV_LENGTH_FIELD_SIZE 1
|
||||
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
|
||||
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
|
||||
|
||||
static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
|
||||
|
||||
STATIC void check_data_fit(size_t pos, size_t data_len) {
|
||||
if (pos + data_len >= BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC uint32_t add_services_to_advertisement(bleio_peripheral_obj_t *self, size_t* adv_data_pos_p, size_t uuid_len) {
|
||||
uint32_t uuids_total_size = 0;
|
||||
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
check_data_fit(*adv_data_pos_p, 1 + 1);
|
||||
|
||||
// Remember where length byte is; fill in later when we know the size.
|
||||
const size_t length_pos = *adv_data_pos_p;
|
||||
(*adv_data_pos_p)++;
|
||||
|
||||
self->adv_data[(*adv_data_pos_p)++] = (uuid_len == 16)
|
||||
? BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE
|
||||
: BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE;
|
||||
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]);
|
||||
uint8_t encoded_size = 0;
|
||||
|
||||
// Skip services of the wrong length and secondary services.
|
||||
if (common_hal_bleio_uuid_get_size(service->uuid) != uuid_len || service->is_secondary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||
|
||||
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &(self->adv_data[*adv_data_pos_p]));
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
check_data_fit(*adv_data_pos_p, encoded_size);
|
||||
uuids_total_size += encoded_size;
|
||||
(*adv_data_pos_p) += encoded_size;
|
||||
}
|
||||
|
||||
self->adv_data[length_pos] = 1 + uuids_total_size; // 1 for the field type.
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if raw_data is a zero-length buffer, generate an advertising packet that advertises the
|
||||
// services passed in when this Peripheral was created.
|
||||
// If raw_data contains some bytes, use those bytes as the advertising packet.
|
||||
// TODO: Generate the advertising packet in Python, not here.
|
||||
STATIC uint32_t set_advertisement_data(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
size_t adv_data_pos = 0;
|
||||
uint32_t err_code;
|
||||
|
||||
GET_STR_DATA_LEN(self->name, name_data, name_len);
|
||||
if (name_len > 0) {
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
|
||||
|
||||
// We'll add the name after everything else, shortening it if necessary.
|
||||
err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
if (raw_data->len != 0) {
|
||||
// User-supplied advertising packet.
|
||||
check_data_fit(adv_data_pos, raw_data->len);
|
||||
memcpy(&(self->adv_data[adv_data_pos]), raw_data->buf, raw_data->len);
|
||||
adv_data_pos += raw_data->len;
|
||||
} else {
|
||||
// Build up advertising packet.
|
||||
check_data_fit(adv_data_pos, 1 + 1 + 1);
|
||||
self->adv_data[adv_data_pos++] = 2;
|
||||
self->adv_data[adv_data_pos++] = BLE_GAP_AD_TYPE_FLAGS;
|
||||
self->adv_data[adv_data_pos++] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
|
||||
|
||||
// The 16-bit ids and 128-bit ids are grouped together by length, so find it whether we have
|
||||
// 16 and/or 128-bit service UUIDs.
|
||||
|
||||
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
|
||||
if (service_list->len > 0) {
|
||||
bool has_128bit_services = false;
|
||||
bool has_16bit_services = false;
|
||||
|
||||
for (size_t i = 0; i < service_list->len; ++i) {
|
||||
const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]);
|
||||
|
||||
if (service->is_secondary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (common_hal_bleio_uuid_get_size(service->uuid)) {
|
||||
case 16:
|
||||
has_16bit_services = true;
|
||||
break;
|
||||
case 128:
|
||||
has_128bit_services = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add 16-bit service UUID's in a group, then 128-bit service UUID's.
|
||||
|
||||
if (has_16bit_services) {
|
||||
err_code = add_services_to_advertisement(self, &adv_data_pos, 16);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_128bit_services) {
|
||||
err_code = add_services_to_advertisement(self, &adv_data_pos, 128);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always include TX power.
|
||||
check_data_fit(adv_data_pos, 1 + 1 + 1);
|
||||
self->adv_data[adv_data_pos++] = 1 + 1;
|
||||
self->adv_data[adv_data_pos++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
|
||||
self->adv_data[adv_data_pos++] = 0; // TODO - allow power level to be set later.
|
||||
|
||||
// We need room for at least a one-character name.
|
||||
check_data_fit(adv_data_pos, 1 + 1 + 1);
|
||||
|
||||
// How big a name can we fit?
|
||||
size_t bytes_left = BLE_GAP_ADV_SET_DATA_SIZE_MAX - adv_data_pos - 1 - 1;
|
||||
size_t partial_name_len = MIN(bytes_left, name_len);
|
||||
self->adv_data[adv_data_pos++] = 1 + partial_name_len;
|
||||
self->adv_data[adv_data_pos++] = (partial_name_len == name_len)
|
||||
? BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME
|
||||
: BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
|
||||
memcpy(&(self->adv_data[adv_data_pos]), name_data, partial_name_len);
|
||||
adv_data_pos += partial_name_len;
|
||||
} // end of advertising packet construction
|
||||
|
||||
static ble_gap_adv_params_t m_adv_params = {
|
||||
.interval = MSEC_TO_UNITS(1000, UNIT_0_625_MS),
|
||||
.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED,
|
||||
.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
|
||||
.filter_policy = BLE_GAP_ADV_FP_ANY,
|
||||
.primary_phy = BLE_GAP_PHY_1MBPS,
|
||||
};
|
||||
|
||||
if (!connectable) {
|
||||
m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
|
||||
}
|
||||
|
||||
common_hal_bleio_peripheral_stop_advertising(self);
|
||||
|
||||
const ble_gap_adv_data_t ble_gap_adv_data = {
|
||||
.adv_data.p_data = self->adv_data,
|
||||
.adv_data.len = adv_data_pos,
|
||||
};
|
||||
|
||||
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
||||
bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in;
|
||||
|
||||
switch (ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_CONNECTED: {
|
||||
// Central has connected.
|
||||
ble_gap_conn_params_t conn_params;
|
||||
self->conn_handle = ble_evt->evt.gap_evt.conn_handle;
|
||||
sd_ble_gap_ppcp_get(&conn_params);
|
||||
sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
// Central has disconnected.
|
||||
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
|
||||
ble_gap_phys_t const phys = {
|
||||
.rx_phys = BLE_GAP_PHY_AUTO,
|
||||
.tx_phys = BLE_GAP_PHY_AUTO,
|
||||
};
|
||||
sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_ADV_SET_TERMINATED:
|
||||
// Someday may handle timeouts or limit reached.
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
|
||||
sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
|
||||
ble_gap_evt_conn_param_update_request_t *request = &ble_evt->evt.gap_evt.params.conn_param_update_request;
|
||||
sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
|
||||
sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
|
||||
sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
// For debugging.
|
||||
// mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self) {
|
||||
common_hal_bleio_adapter_set_enabled(true); // TODO -- Do this somewhere else maybe bleio __init__
|
||||
|
||||
self->gatt_role = GATT_ROLE_SERVER;
|
||||
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
|
||||
// Add all the services.
|
||||
|
||||
mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
|
||||
for (size_t service_idx = 0; service_idx < service_list->len; ++service_idx) {
|
||||
bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[service_idx]);
|
||||
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
|
||||
|
||||
uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
|
||||
if (service->is_secondary) {
|
||||
service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
|
||||
}
|
||||
|
||||
const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to add service, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
// Once the service has been registered, its characteristics can be added.
|
||||
common_hal_bleio_service_add_all_characteristics(service);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) {
|
||||
return self->conn_handle != BLE_CONN_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
|
||||
if (connectable) {
|
||||
ble_drv_add_event_handler(peripheral_on_ble_evt, self);
|
||||
}
|
||||
|
||||
const uint32_t err_code = set_advertisement_data(self, connectable, raw_data);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) {
|
||||
|
||||
if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
|
||||
return;
|
||||
|
||||
const uint32_t err_code = sd_ble_gap_adv_stop(m_adv_handle);
|
||||
|
||||
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "ble.h"
|
||||
|
||||
#include "shared-module/bleio/__init__.h"
|
||||
#include "shared-module/bleio/Address.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t name;
|
||||
gatt_role_t gatt_role;
|
||||
volatile uint16_t conn_handle;
|
||||
mp_obj_t service_list;
|
||||
mp_obj_t notif_handler;
|
||||
mp_obj_t conn_handler;
|
||||
// The advertising data buffer is held by us, not by the SD, so we must
|
||||
// maintain it and not change it. If we need to change its contents during advertising,
|
||||
// there are tricks to get the SD to notice (see DevZone - TBS).
|
||||
uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
|
||||
|
||||
} bleio_peripheral_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_drv.h"
|
||||
#include "ble_gap.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
#include "shared-bindings/bleio/ScanEntry.h"
|
||||
#include "shared-bindings/bleio/Scanner.h"
|
||||
#include "shared-module/bleio/ScanEntry.h"
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN];
|
||||
|
||||
static ble_data_t m_scan_buffer = {
|
||||
m_scan_buffer_data,
|
||||
BLE_GAP_SCAN_BUFFER_MIN
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) {
|
||||
bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in;
|
||||
ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report;
|
||||
|
||||
if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Don't add new entry for each item, group by address and update
|
||||
bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t);
|
||||
entry->base.type = &bleio_scanentry_type;
|
||||
entry->rssi = report->rssi;
|
||||
|
||||
entry->address.type = report->peer_addr.addr_type;
|
||||
memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES);
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
entry->data = mp_obj_new_bytearray(report->data.len, report->data.p_data);
|
||||
#else
|
||||
entry->data = mp_obj_new_bytearray(report->dlen, report->data);
|
||||
#endif
|
||||
|
||||
mp_obj_list_append(scanner->adv_reports, entry);
|
||||
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to continue scanning, err 0x%04x"), err_code);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout) {
|
||||
ble_drv_add_event_handler(on_ble_evt, self);
|
||||
|
||||
ble_gap_scan_params_t scan_params = {
|
||||
.interval = MSEC_TO_UNITS(self->interval, UNIT_0_625_MS),
|
||||
.window = MSEC_TO_UNITS(self->window, UNIT_0_625_MS),
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
.scan_phys = BLE_GAP_PHY_1MBPS,
|
||||
#endif
|
||||
};
|
||||
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
uint32_t err_code;
|
||||
#if (BLUETOOTH_SD == 140)
|
||||
err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer);
|
||||
#else
|
||||
err_code = sd_ble_gap_scan_start(&scan_params);
|
||||
#endif
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
mp_hal_delay_ms(timeout);
|
||||
sd_ble_gap_scan_stop();
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ble_drv.h"
|
||||
#include "ble.h"
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/bleio/__init__.h"
|
||||
#include "common-hal/bleio/Characteristic.h"
|
||||
#include "shared-bindings/bleio/Service.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
|
||||
void common_hal_bleio_service_construct(bleio_service_obj_t *self) {
|
||||
}
|
||||
|
||||
// Call this after the Service has been added to the Peripheral.
|
||||
void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) {
|
||||
// Add all the characteristics.
|
||||
const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(self->char_list);
|
||||
for (size_t char_idx = 0; char_idx < char_list->len; ++char_idx) {
|
||||
bleio_characteristic_obj_t *characteristic = char_list->items[char_idx];
|
||||
|
||||
ble_gatts_char_md_t char_md = {
|
||||
.char_props.broadcast = characteristic->props.broadcast,
|
||||
.char_props.read = characteristic->props.read,
|
||||
.char_props.write_wo_resp = characteristic->props.write_no_response,
|
||||
.char_props.write = characteristic->props.write,
|
||||
.char_props.notify = characteristic->props.notify,
|
||||
.char_props.indicate = characteristic->props.indicate,
|
||||
};
|
||||
|
||||
ble_gatts_attr_md_t cccd_md = {
|
||||
.vloc = BLE_GATTS_VLOC_STACK,
|
||||
};
|
||||
|
||||
if (char_md.char_props.notify || char_md.char_props.indicate) {
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
|
||||
|
||||
char_md.p_cccd_md = &cccd_md;
|
||||
}
|
||||
|
||||
ble_uuid_t uuid;
|
||||
bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &uuid);
|
||||
|
||||
ble_gatts_attr_md_t attr_md = {
|
||||
.vloc = BLE_GATTS_VLOC_STACK,
|
||||
.vlen = 1,
|
||||
};
|
||||
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
|
||||
|
||||
ble_gatts_attr_t attr_char_value = {
|
||||
.p_uuid = &uuid,
|
||||
.p_attr_md = &attr_md,
|
||||
.init_len = sizeof(uint8_t),
|
||||
.max_len = GATT_MAX_DATA_LENGTH,
|
||||
};
|
||||
|
||||
ble_gatts_char_handles_t handles;
|
||||
|
||||
uint32_t err_code;
|
||||
err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &attr_char_value, &handles);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code);
|
||||
}
|
||||
|
||||
if (characteristic->handle != BLE_GATT_HANDLE_INVALID) {
|
||||
mp_raise_ValueError(translate("Characteristic already in use by another Service."));
|
||||
}
|
||||
|
||||
characteristic->user_desc_handle = handles.user_desc_handle;
|
||||
characteristic->cccd_handle = handles.cccd_handle;
|
||||
characteristic->sccd_handle = handles.sccd_handle;
|
||||
characteristic->handle = handles.value_handle;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/bleio/UUID.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
|
||||
#include "ble.h"
|
||||
#include "ble_drv.h"
|
||||
#include "nrf_error.h"
|
||||
|
||||
// If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID.
|
||||
// If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where
|
||||
// the 16-bit part goes. Those 16 bits are passed in uuid16.
|
||||
void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, uint8_t uuid128[]) {
|
||||
common_hal_bleio_adapter_set_enabled(true);
|
||||
|
||||
self->nrf_ble_uuid.uuid = uuid16;
|
||||
if (uuid128 == NULL) {
|
||||
self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE;
|
||||
} else {
|
||||
ble_uuid128_t vs_uuid;
|
||||
memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128));
|
||||
|
||||
// Register this vendor-specific UUID. Bytes 12 and 13 will be zero.
|
||||
const uint32_t err_code = sd_ble_uuid_vs_add(&vs_uuid, &self->nrf_ble_uuid.type);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to register Vendor-Specific UUID, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) {
|
||||
return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 16 : 128;
|
||||
}
|
||||
|
||||
uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) {
|
||||
return self->nrf_ble_uuid.uuid;
|
||||
}
|
||||
|
||||
// True if uuid128 has been successfully filled in.
|
||||
bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) {
|
||||
uint8_t length;
|
||||
const uint32_t err_code = sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128);
|
||||
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Could not decode ble_uuid, err 0x%04x"), err_code);
|
||||
}
|
||||
// If not 16 bytes, this is not a 128-bit UUID, so return.
|
||||
return length == 16;
|
||||
}
|
||||
|
||||
// Returns 0 if this is a 16-bit UUID, otherwise returns a non-zero index
|
||||
// into the 128-bit uuid registration table.
|
||||
uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self) {
|
||||
return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 0 : self->nrf_ble_uuid.type;
|
||||
}
|
||||
|
||||
|
||||
void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) {
|
||||
if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) {
|
||||
mp_raise_RuntimeError(translate("Unexpected nrfx uuid type"));
|
||||
}
|
||||
self->nrf_ble_uuid.uuid = nrf_ble_uuid->uuid;
|
||||
self->nrf_ble_uuid.type = nrf_ble_uuid->type;
|
||||
}
|
||||
|
||||
// Fill in a ble_uuid_t from my values.
|
||||
void bleio_uuid_convert_to_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) {
|
||||
nrf_ble_uuid->uuid = self->nrf_ble_uuid.uuid;
|
||||
nrf_ble_uuid->type = self->nrf_ble_uuid.type;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_UUID_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_UUID_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#include "ble.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
// Use the native way of storing UUID's:
|
||||
// - ble_uuid_t.uuid is a 16-bit uuid.
|
||||
// - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID.
|
||||
// or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered
|
||||
// 128-bit UUIDs.
|
||||
ble_uuid_t nrf_ble_uuid;
|
||||
} bleio_uuid_obj_t;
|
||||
|
||||
void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid);
|
||||
void bleio_uuid_convert_to_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_UUID_H
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Ruben Bakke
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/bleio/__init__.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
#include "shared-bindings/bleio/Peripheral.h"
|
||||
#include "common-hal/bleio/__init__.h"
|
||||
|
||||
// Turn off BLE on a reset or reload.
|
||||
void bleio_reset() {
|
||||
if (common_hal_bleio_adapter_get_enabled()) {
|
||||
common_hal_bleio_adapter_set_enabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// The singleton bleio.Adapter object, bound to bleio.adapter
|
||||
// It currently only has properties and no state
|
||||
const super_adapter_obj_t common_hal_bleio_adapter_obj = {
|
||||
.base = {
|
||||
.type = &bleio_adapter_type,
|
||||
},
|
||||
};
|
||||
|
||||
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
|
||||
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
|
||||
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
|
||||
// Does not exist yet.
|
||||
// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
|
||||
// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
|
||||
} else {
|
||||
return GATT_ROLE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
|
||||
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
|
||||
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
|
||||
// Does not exist yet.
|
||||
// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
|
||||
// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
|
||||
|
||||
#include "shared-bindings/bleio/__init__.h"
|
||||
#include "shared-bindings/bleio/Adapter.h"
|
||||
|
||||
#include "shared-module/bleio/__init__.h"
|
||||
|
||||
// We assume variable length data.
|
||||
// 20 bytes max (23 - 3).
|
||||
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
|
||||
|
||||
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device);
|
||||
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
|
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
* Copyright (c) 2017 hathach
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/busio/I2C.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#include "nrfx_twim.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#include "nrfx_spim.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
// all TWI instances have the same max size
|
||||
// 16 bits for 840, 10 bits for 810, 8 bits for 832
|
||||
#define I2C_MAX_XFER_LEN ((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1)
|
||||
|
||||
STATIC twim_peripheral_t twim_peripherals[] = {
|
||||
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
|
||||
// SPIM0 and TWIM0 share an address.
|
||||
{ .twim = NRFX_TWIM_INSTANCE(0),
|
||||
.in_use = false
|
||||
},
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
|
||||
// SPIM1 and TWIM1 share an address.
|
||||
{ .twim = NRFX_TWIM_INSTANCE(1),
|
||||
.in_use = false
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
void i2c_reset(void) {
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) {
|
||||
nrf_twim_disable(twim_peripherals[i].twim.p_twim);
|
||||
twim_peripherals[i].in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t twi_error_to_mp(const nrfx_err_t err) {
|
||||
switch (err) {
|
||||
case NRFX_ERROR_DRV_TWI_ERR_ANACK:
|
||||
return MP_ENODEV;
|
||||
case NRFX_ERROR_BUSY:
|
||||
return MP_EBUSY;
|
||||
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
|
||||
case NRFX_ERROR_INVALID_ADDR:
|
||||
return MP_EIO;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
|
||||
if (scl->number == sda->number) {
|
||||
mp_raise_ValueError(translate("Invalid pins"));
|
||||
}
|
||||
|
||||
// Find a free instance.
|
||||
self->twim_peripheral = NULL;
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) {
|
||||
if (!twim_peripherals[i].in_use) {
|
||||
self->twim_peripheral = &twim_peripherals[i];
|
||||
self->twim_peripheral->in_use = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->twim_peripheral == NULL) {
|
||||
mp_raise_ValueError(translate("All I2C peripherals are in use"));
|
||||
}
|
||||
|
||||
nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG;
|
||||
config.scl = scl->number;
|
||||
config.sda = sda->number;
|
||||
|
||||
// change freq. only if it's less than the default 400K
|
||||
if (frequency < 100000) {
|
||||
config.frequency = NRF_TWIM_FREQ_100K;
|
||||
} else if (frequency < 250000) {
|
||||
config.frequency = NRF_TWIM_FREQ_250K;
|
||||
}
|
||||
|
||||
self->scl_pin_number = scl->number;
|
||||
self->sda_pin_number = sda->number;
|
||||
claim_pin(sda);
|
||||
claim_pin(scl);
|
||||
|
||||
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
|
||||
|
||||
// A soft reset doesn't uninit the driver so we might end up with a invalid state
|
||||
if (err == NRFX_ERROR_INVALID_STATE) {
|
||||
nrfx_twim_uninit(&self->twim_peripheral->twim);
|
||||
err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
|
||||
}
|
||||
|
||||
if (err != NRFX_SUCCESS) {
|
||||
common_hal_busio_i2c_deinit(self);
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
|
||||
return self->sda_pin_number == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
|
||||
if (common_hal_busio_i2c_deinited(self))
|
||||
return;
|
||||
|
||||
nrfx_twim_uninit(&self->twim_peripheral->twim);
|
||||
|
||||
reset_pin_number(self->sda_pin_number);
|
||||
reset_pin_number(self->scl_pin_number);
|
||||
self->sda_pin_number = NO_PIN;
|
||||
self->scl_pin_number = NO_PIN;
|
||||
|
||||
self->twim_peripheral->in_use = false;
|
||||
}
|
||||
|
||||
// nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API
|
||||
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
|
||||
NRF_TWIM_Type *reg = self->twim_peripheral->twim.p_twim;
|
||||
bool found = true;
|
||||
|
||||
nrfx_twim_enable(&self->twim_peripheral->twim);
|
||||
|
||||
nrf_twim_address_set(reg, addr);
|
||||
nrf_twim_tx_buffer_set(reg, NULL, 0);
|
||||
|
||||
nrf_twim_task_trigger(reg, NRF_TWIM_TASK_RESUME);
|
||||
|
||||
nrf_twim_task_trigger(reg, NRF_TWIM_TASK_STARTTX);
|
||||
while (nrf_twim_event_check(reg, NRF_TWIM_EVENT_TXSTARTED) == 0 &&
|
||||
nrf_twim_event_check(reg, NRF_TWIM_EVENT_ERROR) == 0);
|
||||
nrf_twim_event_clear(reg, NRF_TWIM_EVENT_TXSTARTED);
|
||||
|
||||
nrf_twim_task_trigger(reg, NRF_TWIM_TASK_STOP);
|
||||
while (nrf_twim_event_check(reg, NRF_TWIM_EVENT_STOPPED) == 0);
|
||||
nrf_twim_event_clear(reg, NRF_TWIM_EVENT_STOPPED);
|
||||
|
||||
if (nrf_twim_event_check(reg, NRF_TWIM_EVENT_ERROR)) {
|
||||
nrf_twim_event_clear(reg, NRF_TWIM_EVENT_ERROR);
|
||||
|
||||
nrf_twim_errorsrc_get_and_clear(reg);
|
||||
found = false;
|
||||
}
|
||||
|
||||
nrfx_twim_disable(&self->twim_peripheral->twim);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
|
||||
bool grabbed_lock = false;
|
||||
// NRFX_CRITICAL_SECTION_ENTER();
|
||||
if (!self->has_lock) {
|
||||
grabbed_lock = true;
|
||||
self->has_lock = true;
|
||||
}
|
||||
// NRFX_CRITICAL_SECTION_EXIT();
|
||||
return grabbed_lock;
|
||||
}
|
||||
|
||||
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
|
||||
return self->has_lock;
|
||||
}
|
||||
|
||||
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
|
||||
self->has_lock = false;
|
||||
}
|
||||
|
||||
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) {
|
||||
if(len == 0) {
|
||||
return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV;
|
||||
}
|
||||
|
||||
nrfx_err_t err = NRFX_SUCCESS;
|
||||
|
||||
nrfx_twim_enable(&self->twim_peripheral->twim);
|
||||
|
||||
// break into MAX_XFER_LEN transaction
|
||||
while ( len ) {
|
||||
const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN);
|
||||
|
||||
if ( NRFX_SUCCESS != (err = nrfx_twim_tx(&self->twim_peripheral->twim, addr, data, xact_len, !stopBit)) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
len -= xact_len;
|
||||
data += xact_len;
|
||||
}
|
||||
|
||||
nrfx_twim_disable(&self->twim_peripheral->twim);
|
||||
|
||||
return twi_error_to_mp(err);
|
||||
}
|
||||
|
||||
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) {
|
||||
if(len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nrfx_err_t err = NRFX_SUCCESS;
|
||||
|
||||
nrfx_twim_enable(&self->twim_peripheral->twim);
|
||||
|
||||
// break into MAX_XFER_LEN transaction
|
||||
while ( len ) {
|
||||
const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN);
|
||||
|
||||
if ( NRFX_SUCCESS != (err = nrfx_twim_rx(&self->twim_peripheral->twim, addr, data, xact_len)) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
len -= xact_len;
|
||||
data += xact_len;
|
||||
}
|
||||
|
||||
nrfx_twim_disable(&self->twim_peripheral->twim);
|
||||
|
||||
return twi_error_to_mp(err);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_I2C_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_I2C_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
nrfx_twim_t twim;
|
||||
bool in_use;
|
||||
} twim_peripheral_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
twim_peripheral_t* twim_peripheral;
|
||||
bool has_lock;
|
||||
uint8_t scl_pin_number;
|
||||
uint8_t sda_pin_number;
|
||||
} busio_i2c_obj_t;
|
||||
|
||||
void i2c_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_I2C_H
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H
|
||||
|
||||
// Use bitbangio.
|
||||
#include "shared-module/busio/OneWire.h"
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_ONEWIRE_H
|
@ -1,337 +0,0 @@
|
||||
/*
|
||||
* SPI Master library for nRF5x.
|
||||
* Copyright (c) 2015 Arduino LLC
|
||||
* Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
* Copyright (c) 2017 hathach
|
||||
* Copyright (c) 2018 Artur Pacholec
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "nrfx_spim.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
STATIC spim_peripheral_t spim_peripherals[] = {
|
||||
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
||||
// SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max.
|
||||
// Allocate SPIM3 first.
|
||||
{ .spim = NRFX_SPIM_INSTANCE(3),
|
||||
.max_frequency_MHz = 32,
|
||||
.max_xfer_size = SPIM3_EASYDMA_MAXCNT_SIZE,
|
||||
},
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
||||
// SPIM2 is not shared with a TWIM, so allocate before the shared ones.
|
||||
{ .spim = NRFX_SPIM_INSTANCE(2),
|
||||
.max_frequency_MHz = 8,
|
||||
.max_xfer_size = SPIM2_EASYDMA_MAXCNT_SIZE,
|
||||
},
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
||||
// SPIM1 and TWIM1 share an address.
|
||||
{ .spim = NRFX_SPIM_INSTANCE(1),
|
||||
.max_frequency_MHz = 8,
|
||||
.max_xfer_size = SPIM1_EASYDMA_MAXCNT_SIZE,
|
||||
},
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
||||
// SPIM0 and TWIM0 share an address.
|
||||
{ .spim = NRFX_SPIM_INSTANCE(0),
|
||||
.max_frequency_MHz = 8,
|
||||
.max_xfer_size = SPIM0_EASYDMA_MAXCNT_SIZE,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC bool never_reset[4];
|
||||
|
||||
void spi_reset(void) {
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
|
||||
if (never_reset[i]) {
|
||||
continue;
|
||||
}
|
||||
nrf_spim_disable(spim_peripherals[i].spim.p_reg);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
|
||||
if (self->spim_peripheral == &spim_peripherals[i]) {
|
||||
never_reset[i] = true;
|
||||
|
||||
never_reset_pin_number(self->clock_pin_number);
|
||||
never_reset_pin_number(self->MOSI_pin_number);
|
||||
never_reset_pin_number(self->MISO_pin_number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert frequency to clock-speed-dependent value. Choose the next lower baudrate if in between
|
||||
// available baudrates.
|
||||
static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) {
|
||||
|
||||
static const struct {
|
||||
const uint32_t boundary;
|
||||
nrf_spim_frequency_t spim_frequency;
|
||||
} baudrate_map[] = {
|
||||
#ifdef SPIM_FREQUENCY_FREQUENCY_M32
|
||||
{ 32000000, NRF_SPIM_FREQ_32M },
|
||||
#endif
|
||||
#ifdef SPIM_FREQUENCY_FREQUENCY_M16
|
||||
{ 16000000, NRF_SPIM_FREQ_16M },
|
||||
#endif
|
||||
{ 8000000, NRF_SPIM_FREQ_8M },
|
||||
{ 4000000, NRF_SPIM_FREQ_4M },
|
||||
{ 2000000, NRF_SPIM_FREQ_2M },
|
||||
{ 1000000, NRF_SPIM_FREQ_1M },
|
||||
{ 500000, NRF_SPIM_FREQ_500K },
|
||||
{ 250000, NRF_SPIM_FREQ_250K },
|
||||
{ 0, NRF_SPIM_FREQ_125K },
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
uint32_t boundary;
|
||||
do {
|
||||
boundary = baudrate_map[i].boundary;
|
||||
if (baudrate >= boundary) {
|
||||
return baudrate_map[i].spim_frequency;
|
||||
}
|
||||
i++;
|
||||
} while (boundary != 0);
|
||||
// Should not get here.
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) {
|
||||
// Find a free instance.
|
||||
self->spim_peripheral = NULL;
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
|
||||
if ((spim_peripherals[i].spim.p_reg->ENABLE & SPIM_ENABLE_ENABLE_Msk) == 0) {
|
||||
self->spim_peripheral = &spim_peripherals[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->spim_peripheral == NULL) {
|
||||
mp_raise_ValueError(translate("All SPI peripherals are in use"));
|
||||
}
|
||||
|
||||
nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG;
|
||||
config.frequency = NRF_SPIM_FREQ_8M;
|
||||
|
||||
config.sck_pin = clock->number;
|
||||
self->clock_pin_number = clock->number;
|
||||
claim_pin(clock);
|
||||
|
||||
if (mosi != (mcu_pin_obj_t*)&mp_const_none_obj) {
|
||||
config.mosi_pin = mosi->number;
|
||||
self->MOSI_pin_number = mosi->number;
|
||||
claim_pin(mosi);
|
||||
} else {
|
||||
self->MOSI_pin_number = NO_PIN;
|
||||
}
|
||||
|
||||
if (miso != (mcu_pin_obj_t*)&mp_const_none_obj) {
|
||||
config.miso_pin = miso->number;
|
||||
self->MISO_pin_number = mosi->number;
|
||||
claim_pin(miso);
|
||||
} else {
|
||||
self->MISO_pin_number = NO_PIN;
|
||||
}
|
||||
|
||||
nrfx_err_t err = nrfx_spim_init(&self->spim_peripheral->spim, &config, NULL, NULL);
|
||||
|
||||
// A soft reset doesn't uninit the driver so we might end up with a invalid state
|
||||
if (err == NRFX_ERROR_INVALID_STATE) {
|
||||
nrfx_spim_uninit(&self->spim_peripheral->spim);
|
||||
err = nrfx_spim_init(&self->spim_peripheral->spim, &config, NULL, NULL);
|
||||
}
|
||||
|
||||
if (err != NRFX_SUCCESS) {
|
||||
common_hal_busio_spi_deinit(self);
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
|
||||
return self->clock_pin_number == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
|
||||
if (common_hal_busio_spi_deinited(self))
|
||||
return;
|
||||
|
||||
nrfx_spim_uninit(&self->spim_peripheral->spim);
|
||||
|
||||
reset_pin_number(self->clock_pin_number);
|
||||
reset_pin_number(self->MOSI_pin_number);
|
||||
reset_pin_number(self->MISO_pin_number);
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
|
||||
// nrf52 does not support 16 bit
|
||||
if (bits != 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set desired frequency, rounding down, and don't go above available frequency for this SPIM.
|
||||
nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg,
|
||||
baudrate_to_spim_frequency(MIN(baudrate,
|
||||
self->spim_peripheral->max_frequency_MHz * 1000000)));
|
||||
|
||||
nrf_spim_mode_t mode = NRF_SPIM_MODE_0;
|
||||
if (polarity) {
|
||||
mode = (phase) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2;
|
||||
} else {
|
||||
mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0;
|
||||
}
|
||||
|
||||
nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
|
||||
bool grabbed_lock = false;
|
||||
// NRFX_CRITICAL_SECTION_ENTER();
|
||||
if (!self->has_lock) {
|
||||
grabbed_lock = true;
|
||||
self->has_lock = true;
|
||||
}
|
||||
// NRFX_CRITICAL_SECTION_EXIT();
|
||||
return grabbed_lock;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
|
||||
return self->has_lock;
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
|
||||
self->has_lock = false;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size_t len) {
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
|
||||
const uint32_t parts = len / max_xfer_size;
|
||||
const uint32_t remainder = len % max_xfer_size;
|
||||
|
||||
for (uint32_t i = 0; i < parts; ++i) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + i * max_xfer_size, max_xfer_size);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remainder > 0) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + parts * max_xfer_size, remainder);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value) {
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
|
||||
const uint32_t parts = len / max_xfer_size;
|
||||
const uint32_t remainder = len % max_xfer_size;
|
||||
|
||||
for (uint32_t i = 0; i < parts; ++i) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + i * max_xfer_size, max_xfer_size);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remainder > 0) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + parts * max_xfer_size, remainder);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
|
||||
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
|
||||
const uint32_t parts = len / max_xfer_size;
|
||||
const uint32_t remainder = len % max_xfer_size;
|
||||
|
||||
for (uint32_t i = 0; i < parts; ++i) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + i * max_xfer_size, max_xfer_size,
|
||||
data_in + i * max_xfer_size, max_xfer_size);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remainder > 0) {
|
||||
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + parts * max_xfer_size, remainder,
|
||||
data_in + parts * max_xfer_size, remainder);
|
||||
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
|
||||
switch (self->spim_peripheral->spim.p_reg->FREQUENCY) {
|
||||
case NRF_SPIM_FREQ_125K:
|
||||
return 125000;
|
||||
case NRF_SPIM_FREQ_250K:
|
||||
return 250000;
|
||||
case NRF_SPIM_FREQ_500K:
|
||||
return 500000;
|
||||
case NRF_SPIM_FREQ_1M:
|
||||
return 1000000;
|
||||
case NRF_SPIM_FREQ_2M:
|
||||
return 2000000;
|
||||
case NRF_SPIM_FREQ_4M:
|
||||
return 4000000;
|
||||
case NRF_SPIM_FREQ_8M:
|
||||
return 8000000;
|
||||
#ifdef SPIM_FREQUENCY_FREQUENCY_M16
|
||||
case NRF_SPIM_FREQ_16M:
|
||||
return 16000000;
|
||||
#endif
|
||||
#ifdef SPIM_FREQUENCY_FREQUENCY_M32
|
||||
case NRF_SPIM_FREQ_32M:
|
||||
return 32000000;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t* self) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self) {
|
||||
return 0;
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_SPI_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_SPI_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
nrfx_spim_t spim;
|
||||
uint8_t max_frequency_MHz;
|
||||
uint8_t max_xfer_size;
|
||||
} spim_peripheral_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
spim_peripheral_t* spim_peripheral;
|
||||
bool has_lock;
|
||||
uint8_t clock_pin_number;
|
||||
uint8_t MOSI_pin_number;
|
||||
uint8_t MISO_pin_number;
|
||||
} busio_spi_obj_t;
|
||||
|
||||
void spi_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_SPI_H
|
@ -1,332 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Ha Thach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/busio/UART.h"
|
||||
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#include "tick.h"
|
||||
#include "nrfx_uarte.h"
|
||||
#include <string.h>
|
||||
|
||||
// expression to examine, and return value in case of failing
|
||||
#define _VERIFY_ERR(_exp) \
|
||||
do {\
|
||||
uint32_t _err = (_exp);\
|
||||
if (NRFX_SUCCESS != _err ) {\
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, translate("error = 0x%08lX"), _err);\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
static nrfx_uarte_t nrfx_uartes[] = {
|
||||
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
|
||||
NRFX_UARTE_INSTANCE(0),
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
|
||||
NRFX_UARTE_INSTANCE(1),
|
||||
#endif
|
||||
};
|
||||
|
||||
static uint32_t get_nrf_baud (uint32_t baudrate) {
|
||||
|
||||
static const struct {
|
||||
const uint32_t boundary;
|
||||
nrf_uarte_baudrate_t uarte_baudraute;
|
||||
} baudrate_map[] = {
|
||||
{ 1200, NRF_UARTE_BAUDRATE_1200 },
|
||||
{ 2400, NRF_UARTE_BAUDRATE_2400 },
|
||||
{ 4800, NRF_UARTE_BAUDRATE_4800 },
|
||||
{ 9600, NRF_UARTE_BAUDRATE_9600 },
|
||||
{ 14400, NRF_UARTE_BAUDRATE_14400 },
|
||||
{ 19200, NRF_UARTE_BAUDRATE_19200 },
|
||||
{ 28800, NRF_UARTE_BAUDRATE_28800 },
|
||||
{ 38400, NRF_UARTE_BAUDRATE_38400 },
|
||||
{ 57600, NRF_UARTE_BAUDRATE_57600 },
|
||||
{ 76800, NRF_UARTE_BAUDRATE_76800 },
|
||||
{ 115200, NRF_UARTE_BAUDRATE_115200 },
|
||||
{ 230400, NRF_UARTE_BAUDRATE_230400 },
|
||||
{ 250000, NRF_UARTE_BAUDRATE_250000 },
|
||||
{ 460800, NRF_UARTE_BAUDRATE_460800 },
|
||||
{ 921600, NRF_UARTE_BAUDRATE_921600 },
|
||||
{ 0, NRF_UARTE_BAUDRATE_1000000 },
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
uint32_t boundary;
|
||||
do {
|
||||
boundary = baudrate_map[i].boundary;
|
||||
if (baudrate <= boundary || boundary == 0) {
|
||||
return baudrate_map[i].uarte_baudraute;
|
||||
}
|
||||
i++;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static void uart_callback_irq (const nrfx_uarte_event_t * event, void * context) {
|
||||
busio_uart_obj_t* self = (busio_uart_obj_t*) context;
|
||||
|
||||
switch ( event->type ) {
|
||||
case NRFX_UARTE_EVT_RX_DONE:
|
||||
ringbuf_put_n(&self->rbuf, event->data.rxtx.p_data, event->data.rxtx.bytes);
|
||||
|
||||
// keep receiving
|
||||
(void) nrfx_uarte_rx(self->uarte, &self->rx_char, 1);
|
||||
break;
|
||||
|
||||
case NRFX_UARTE_EVT_TX_DONE:
|
||||
// nothing to do
|
||||
break;
|
||||
|
||||
case NRFX_UARTE_EVT_ERROR:
|
||||
// Possible Error source is Overrun, Parity, Framing, Break
|
||||
// uint32_t errsrc = event->data.error.error_mask;
|
||||
|
||||
ringbuf_put_n(&self->rbuf, event->data.error.rxtx.p_data, event->data.error.rxtx.bytes);
|
||||
|
||||
// Keep receiving
|
||||
(void) nrfx_uarte_rx(self->uarte, &self->rx_char, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_reset(void) {
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(nrfx_uartes); i++) {
|
||||
nrf_uarte_disable(nrfx_uartes[i].p_reg);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_busio_uart_construct (busio_uart_obj_t *self,
|
||||
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate,
|
||||
uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout,
|
||||
uint8_t receiver_buffer_size) {
|
||||
// Find a free UART peripheral.
|
||||
self->uarte = NULL;
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(nrfx_uartes); i++) {
|
||||
if ((nrfx_uartes[i].p_reg->ENABLE & UARTE_ENABLE_ENABLE_Msk) == 0) {
|
||||
self->uarte = &nrfx_uartes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->uarte == NULL) {
|
||||
mp_raise_ValueError(translate("All UART peripherals are in use"));
|
||||
}
|
||||
|
||||
if ( (tx == mp_const_none) && (rx == mp_const_none) ) {
|
||||
mp_raise_ValueError(translate("tx and rx cannot both be None"));
|
||||
}
|
||||
|
||||
if ( receiver_buffer_size == 0 ) {
|
||||
mp_raise_ValueError(translate("Invalid buffer size"));
|
||||
}
|
||||
|
||||
if ( parity == PARITY_ODD ) {
|
||||
mp_raise_ValueError(translate("Odd parity is not supported"));
|
||||
}
|
||||
|
||||
nrfx_uarte_config_t config = {
|
||||
.pseltxd = (tx == mp_const_none) ? NRF_UARTE_PSEL_DISCONNECTED : tx->number,
|
||||
.pselrxd = (rx == mp_const_none) ? NRF_UARTE_PSEL_DISCONNECTED : rx->number,
|
||||
.pselcts = NRF_UARTE_PSEL_DISCONNECTED,
|
||||
.pselrts = NRF_UARTE_PSEL_DISCONNECTED,
|
||||
.p_context = self,
|
||||
.hwfc = NRF_UARTE_HWFC_DISABLED,
|
||||
.parity = (parity == PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED,
|
||||
.baudrate = get_nrf_baud(baudrate),
|
||||
.interrupt_priority = 7
|
||||
};
|
||||
|
||||
nrfx_uarte_uninit(self->uarte);
|
||||
_VERIFY_ERR(nrfx_uarte_init(self->uarte, &config, uart_callback_irq));
|
||||
|
||||
// Init buffer for rx
|
||||
if ( rx != mp_const_none ) {
|
||||
// Initially allocate the UART's buffer in the long-lived part of the
|
||||
// heap. UARTs are generally long-lived objects, but the "make long-
|
||||
// lived" machinery is incapable of moving internal pointers like
|
||||
// self->buffer, so do it manually. (However, as long as internal
|
||||
// pointers like this are NOT moved, allocating the buffer
|
||||
// in the long-lived pool is not strictly necessary)
|
||||
// (This is a macro.)
|
||||
ringbuf_alloc(&self->rbuf, receiver_buffer_size, true);
|
||||
|
||||
if ( !self->rbuf.buf ) {
|
||||
nrfx_uarte_uninit(self->uarte);
|
||||
mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer"));
|
||||
}
|
||||
|
||||
self->rx_pin_number = rx->number;
|
||||
claim_pin(rx);
|
||||
}
|
||||
|
||||
if ( tx != mp_const_none ) {
|
||||
self->tx_pin_number = tx->number;
|
||||
claim_pin(tx);
|
||||
} else {
|
||||
self->tx_pin_number = NO_PIN;
|
||||
}
|
||||
|
||||
self->baudrate = baudrate;
|
||||
self->timeout_ms = timeout * 1000;
|
||||
|
||||
// Initial wait for incoming byte
|
||||
_VERIFY_ERR(nrfx_uarte_rx(self->uarte, &self->rx_char, 1));
|
||||
}
|
||||
|
||||
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
|
||||
return self->rx_pin_number == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
|
||||
if ( !common_hal_busio_uart_deinited(self) ) {
|
||||
nrfx_uarte_uninit(self->uarte);
|
||||
reset_pin_number(self->tx_pin_number);
|
||||
reset_pin_number(self->rx_pin_number);
|
||||
self->tx_pin_number = NO_PIN;
|
||||
self->rx_pin_number = NO_PIN;
|
||||
|
||||
gc_free(self->rbuf.buf);
|
||||
self->rbuf.size = 0;
|
||||
self->rbuf.iput = self->rbuf.iget = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Read characters.
|
||||
size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
||||
if ( nrf_uarte_rx_pin_get(self->uarte->p_reg) == NRF_UARTE_PSEL_DISCONNECTED ) {
|
||||
mp_raise_ValueError(translate("No RX pin"));
|
||||
}
|
||||
|
||||
size_t rx_bytes = 0;
|
||||
uint64_t start_ticks = ticks_ms;
|
||||
|
||||
// Wait for all bytes received or timeout
|
||||
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP ;
|
||||
// Allow user to break out of a timeout with a KeyboardInterrupt.
|
||||
if ( mp_hal_is_interrupted() ) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// prevent conflict with uart irq
|
||||
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
|
||||
|
||||
// copy received data
|
||||
rx_bytes = ringbuf_count(&self->rbuf);
|
||||
rx_bytes = MIN(rx_bytes, len);
|
||||
for ( uint16_t i = 0; i < rx_bytes; i++ ) {
|
||||
data[i] = ringbuf_get(&self->rbuf);
|
||||
}
|
||||
|
||||
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
|
||||
|
||||
return rx_bytes;
|
||||
}
|
||||
|
||||
// Write characters.
|
||||
size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
|
||||
if ( nrf_uarte_tx_pin_get(self->uarte->p_reg) == NRF_UARTE_PSEL_DISCONNECTED ) {
|
||||
mp_raise_ValueError(translate("No TX pin"));
|
||||
}
|
||||
|
||||
if ( len == 0 ) return 0;
|
||||
|
||||
uint64_t start_ticks = ticks_ms;
|
||||
|
||||
// Wait for on-going transfer to complete
|
||||
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
// Time up
|
||||
if ( !(ticks_ms - start_ticks < self->timeout_ms) ) {
|
||||
*errcode = MP_EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
// EasyDMA can only access SRAM
|
||||
uint8_t * tx_buf = (uint8_t*) data;
|
||||
if ( !nrfx_is_in_ram(data) ) {
|
||||
// TODO: If this is not too big, we could allocate it on the stack.
|
||||
tx_buf = (uint8_t *) gc_alloc(len, false, false);
|
||||
memcpy(tx_buf, data, len);
|
||||
}
|
||||
|
||||
(*errcode) = nrfx_uarte_tx(self->uarte, tx_buf, len);
|
||||
_VERIFY_ERR(*errcode);
|
||||
(*errcode) = 0;
|
||||
|
||||
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( !nrfx_is_in_ram(data) ) {
|
||||
gc_free(tx_buf);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
|
||||
return self->baudrate;
|
||||
}
|
||||
|
||||
void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) {
|
||||
self->baudrate = baudrate;
|
||||
nrf_uarte_baudrate_set(self->uarte->p_reg, get_nrf_baud(baudrate));
|
||||
}
|
||||
|
||||
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
|
||||
return ringbuf_count(&self->rbuf);
|
||||
}
|
||||
|
||||
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
|
||||
// prevent conflict with uart irq
|
||||
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
|
||||
ringbuf_clear(&self->rbuf);
|
||||
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
|
||||
}
|
||||
|
||||
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
|
||||
return !nrfx_uarte_tx_in_progress(self->uarte);
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/ringbuf.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
|
||||
nrfx_uarte_t *uarte;
|
||||
|
||||
uint32_t baudrate;
|
||||
uint32_t timeout_ms;
|
||||
|
||||
ringbuf_t rbuf;
|
||||
uint8_t rx_char; // EasyDMA buf
|
||||
|
||||
uint8_t tx_pin_number;
|
||||
uint8_t rx_pin_number;
|
||||
} busio_uart_obj_t;
|
||||
|
||||
void uart_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H
|
@ -1 +0,0 @@
|
||||
// No busio module functions.
|
@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,8 +25,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
@ -34,4 +35,4 @@ typedef struct {
|
||||
const mcu_pin_obj_t *pin;
|
||||
} digitalio_digitalinout_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
|
||||
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//#include "shared-bindings/displayio/ParallelBus.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//include "common-hal/microcontroller/Pin.h"
|
||||
#include "py/runtime.h"
|
||||
//#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
|
||||
// const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
|
||||
// const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
|
||||
|
||||
// uint8_t data_pin = data0->number;
|
||||
// if (data_pin % 8 != 0) {
|
||||
// mp_raise_ValueError(translate("Data 0 pin must be byte aligned"));
|
||||
// }
|
||||
// for (uint8_t i = 0; i < 8; i++) {
|
||||
// if (!pin_number_is_free(data_pin + i)) {
|
||||
// mp_raise_ValueError_varg(translate("Bus pin %d is already in use"), i);
|
||||
// }
|
||||
// }
|
||||
// NRF_GPIO_Type *g;
|
||||
// uint8_t num_pins_in_port;
|
||||
// if (data0->number < P0_PIN_NUM) {
|
||||
// g = NRF_P0;
|
||||
// num_pins_in_port = P0_PIN_NUM;
|
||||
// } else {
|
||||
// g = NRF_P1;
|
||||
// num_pins_in_port = P1_PIN_NUM;
|
||||
// }
|
||||
// g->DIRSET = 0xff << (data_pin % num_pins_in_port);
|
||||
// for (uint8_t i = 0; i < 8; i++) {
|
||||
// g->PIN_CNF[data_pin + i] |= NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos;
|
||||
// }
|
||||
// self->bus = ((uint8_t*) &g->OUT) + (data0->number % num_pins_in_port / 8);
|
||||
|
||||
// self->command.base.type = &digitalio_digitalinout_type;
|
||||
// common_hal_digitalio_digitalinout_construct(&self->command, command);
|
||||
// common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
// self->chip_select.base.type = &digitalio_digitalinout_type;
|
||||
// common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
|
||||
// common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
// self->reset.base.type = &digitalio_digitalinout_type;
|
||||
// common_hal_digitalio_digitalinout_construct(&self->reset, reset);
|
||||
// common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
// self->write.base.type = &digitalio_digitalinout_type;
|
||||
// common_hal_digitalio_digitalinout_construct(&self->write, write);
|
||||
// common_hal_digitalio_digitalinout_switch_to_output(&self->write, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
// self->read.base.type = &digitalio_digitalinout_type;
|
||||
// common_hal_digitalio_digitalinout_construct(&self->read, read);
|
||||
// common_hal_digitalio_digitalinout_switch_to_output(&self->read, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
// self->data0_pin = data_pin;
|
||||
// uint8_t num_pins_in_write_port;
|
||||
// if (data0->number < P0_PIN_NUM) {
|
||||
// self->write_group = NRF_P0;
|
||||
// num_pins_in_write_port = P0_PIN_NUM;
|
||||
// } else {
|
||||
// self->write_group = NRF_P1;
|
||||
// num_pins_in_write_port = P1_PIN_NUM;
|
||||
// }
|
||||
// self->write_mask = 1 << (write->number % num_pins_in_write_port);
|
||||
|
||||
// never_reset_pin_number(command->number);
|
||||
// never_reset_pin_number(chip_select->number);
|
||||
// never_reset_pin_number(write->number);
|
||||
// never_reset_pin_number(read->number);
|
||||
// never_reset_pin_number(reset->number);
|
||||
// for (uint8_t i = 0; i < 8; i++) {
|
||||
// never_reset_pin_number(data_pin + i);
|
||||
// }
|
||||
}
|
||||
|
||||
void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
|
||||
// for (uint8_t i = 0; i < 8; i++) {
|
||||
// reset_pin_number(self->data0_pin + i);
|
||||
// }
|
||||
|
||||
// reset_pin_number(self->command.pin->number);
|
||||
// reset_pin_number(self->chip_select.pin->number);
|
||||
// reset_pin_number(self->write.pin->number);
|
||||
// reset_pin_number(self->read.pin->number);
|
||||
// reset_pin_number(self->reset.pin->number);
|
||||
}
|
||||
|
||||
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
|
||||
// displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
|
||||
// common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void common_hal_displayio_parallelbus_send(mp_obj_t obj, bool command, uint8_t *data, uint32_t data_length) {
|
||||
// displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
|
||||
// common_hal_digitalio_digitalinout_set_value(&self->command, !command);
|
||||
// uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR;
|
||||
// uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET;
|
||||
// uint32_t mask = self->write_mask;
|
||||
// for (uint32_t i = 0; i < data_length; i++) {
|
||||
// *clear_write = mask;
|
||||
// *self->bus = data[i];
|
||||
// *set_write = mask;
|
||||
// }
|
||||
}
|
||||
|
||||
void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
|
||||
// displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
|
||||
// common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
|
||||
|
||||
#include "common-hal/digitalio/DigitalInOut.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint8_t* bus;
|
||||
digitalio_digitalinout_obj_t command;
|
||||
digitalio_digitalinout_obj_t chip_select;
|
||||
digitalio_digitalinout_obj_t reset;
|
||||
digitalio_digitalinout_obj_t write;
|
||||
digitalio_digitalinout_obj_t read;
|
||||
uint8_t data0_pin;
|
||||
NRF_GPIO_Type* write_group;
|
||||
uint32_t write_mask;
|
||||
} displayio_parallelbus_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
|
@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
|
||||
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 8
|
||||
|
||||
@ -36,4 +36,4 @@ typedef struct {
|
||||
// Stores no state currently.
|
||||
} mcu_processor_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
|
||||
|
@ -1,294 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 hathach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "shared-bindings/neopixel_write/__init__.h"
|
||||
#include "nrf_pwm.h"
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
|
||||
// [[[Begin of the Neopixel NRF52 EasyDMA implementation
|
||||
// by the Hackerspace San Salvador]]]
|
||||
// This technique uses the PWM peripheral on the NRF52. The PWM uses the
|
||||
// EasyDMA feature included on the chip. This technique loads the duty
|
||||
// cycle configuration for each cycle when the PWM is enabled. For this
|
||||
// to work we need to store a 16 bit configuration for each bit of the
|
||||
// RGB(W) values in the pixel buffer.
|
||||
// Comparator values for the PWM were hand picked and are guaranteed to
|
||||
// be 100% organic to preserve freshness and high accuracy. Current
|
||||
// parameters are:
|
||||
// * PWM Clock: 16Mhz
|
||||
// * Minimum step time: 62.5ns
|
||||
// * Time for zero in high (T0H): 0.31ms
|
||||
// * Time for one in high (T1H): 0.75ms
|
||||
// * Cycle time: 1.25us
|
||||
// * Frequency: 800Khz
|
||||
// For 400Khz we just double the calculated times.
|
||||
// ---------- BEGIN Constants for the EasyDMA implementation -----------
|
||||
// The PWM starts the duty cycle in LOW. To start with HIGH we
|
||||
// need to set the 15th bit on each register.
|
||||
|
||||
// WS2812 (rev A) timing is 0.35 and 0.7us
|
||||
//#define MAGIC_T0H 5UL | (0x8000) // 0.3125us
|
||||
//#define MAGIC_T1H 12UL | (0x8000) // 0.75us
|
||||
|
||||
// WS2812B (rev B) timing is 0.4 and 0.8 us
|
||||
#define MAGIC_T0H 6UL | (0x8000) // 0.375us
|
||||
#define MAGIC_T1H 13UL | (0x8000) // 0.8125us
|
||||
#define CTOPVAL 20UL // 1.25us
|
||||
|
||||
// ---------- END Constants for the EasyDMA implementation -------------
|
||||
//
|
||||
// If there is no device available an alternative cycle-counter
|
||||
// implementation is tried.
|
||||
// The nRF52840 runs with a fixed clock of 64Mhz. The alternative
|
||||
// implementation is the same as the one used for the Teensy 3.0/1/2 but
|
||||
// with the Nordic SDK HAL & registers syntax.
|
||||
// The number of cycles was hand picked and is guaranteed to be 100%
|
||||
// organic to preserve freshness and high accuracy.
|
||||
// ---------- BEGIN Constants for cycle counter implementation ---------
|
||||
#define CYCLES_800_T0H 18 // ~0.36 uS
|
||||
#define CYCLES_800_T1H 41 // ~0.76 uS
|
||||
#define CYCLES_800 71 // ~1.25 uS
|
||||
|
||||
// ---------- END of Constants for cycle counter implementation --------
|
||||
|
||||
// find a free PWM device, which is not enabled and has no connected pins
|
||||
static NRF_PWM_Type* find_free_pwm (void) {
|
||||
NRF_PWM_Type* PWM[] = {
|
||||
NRF_PWM0, NRF_PWM1, NRF_PWM2
|
||||
#ifdef NRF_PWM3
|
||||
, NRF_PWM3
|
||||
#endif
|
||||
};
|
||||
|
||||
for ( size_t device = 0; device < ARRAY_SIZE(PWM); device++ ) {
|
||||
if ( (PWM[device]->ENABLE == 0) &&
|
||||
(PWM[device]->PSEL.OUT[0] & PWM_PSEL_OUT_CONNECT_Msk) && (PWM[device]->PSEL.OUT[1] & PWM_PSEL_OUT_CONNECT_Msk) &&
|
||||
(PWM[device]->PSEL.OUT[2] & PWM_PSEL_OUT_CONNECT_Msk) && (PWM[device]->PSEL.OUT[3] & PWM_PSEL_OUT_CONNECT_Msk) ) {
|
||||
return PWM[device];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t next_start_tick_ms = 0;
|
||||
uint32_t next_start_tick_us = 1000;
|
||||
|
||||
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
|
||||
// To support both the SoftDevice + Neopixels we use the EasyDMA
|
||||
// feature from the NRF25. However this technique implies to
|
||||
// generate a pattern and store it on the memory. The actual
|
||||
// memory used in bytes corresponds to the following formula:
|
||||
// totalMem = numBytes*8*2+(2*2)
|
||||
// The two additional bytes at the end are needed to reset the
|
||||
// sequence.
|
||||
//
|
||||
// If there is not enough memory, we will fall back to cycle counter
|
||||
// using DWT
|
||||
uint32_t pattern_size = numBytes * 8 * sizeof(uint16_t) + 2 * sizeof(uint16_t);
|
||||
uint16_t* pixels_pattern = NULL;
|
||||
bool pattern_on_heap = false;
|
||||
|
||||
// Use the stack to store 1 pixels worth of PWM data for the status led. uint32_t to ensure alignment.
|
||||
uint32_t one_pixel[8 * sizeof(uint16_t) + 1];
|
||||
|
||||
NRF_PWM_Type* pwm = find_free_pwm();
|
||||
|
||||
// only malloc if there is PWM device available
|
||||
if ( pwm != NULL ) {
|
||||
if (pattern_size <= sizeof(one_pixel) * sizeof(uint32_t)) {
|
||||
pixels_pattern = (uint16_t *) one_pixel;
|
||||
} else {
|
||||
pixels_pattern = (uint16_t *) m_malloc_maybe(pattern_size, false);
|
||||
pattern_on_heap = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait to make sure we don't append onto the last transmission.
|
||||
wait_until(next_start_tick_ms, next_start_tick_us);
|
||||
|
||||
// Use the identified device to choose the implementation
|
||||
// If a PWM device is available use DMA
|
||||
if ( (pixels_pattern != NULL) && (pwm != NULL) ) {
|
||||
uint16_t pos = 0; // bit position
|
||||
|
||||
for ( uint16_t n = 0; n < numBytes; n++ ) {
|
||||
uint8_t pix = pixels[n];
|
||||
|
||||
for ( uint8_t mask = 0x80; mask > 0; mask >>= 1 ) {
|
||||
pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Zero padding to indicate the end of sequence
|
||||
pixels_pattern[pos++] = 0 | (0x8000); // Seq end
|
||||
pixels_pattern[pos++] = 0 | (0x8000); // Seq end
|
||||
|
||||
// Set the wave mode to count UP
|
||||
// Set the PWM to use the 16MHz clock
|
||||
// Setting of the maximum count
|
||||
// but keeping it on 16Mhz allows for more granularity just
|
||||
// in case someone wants to do more fine-tuning of the timing.
|
||||
nrf_pwm_configure(pwm, NRF_PWM_CLK_16MHz, NRF_PWM_MODE_UP, CTOPVAL);
|
||||
|
||||
// Disable loops, we want the sequence to repeat only once
|
||||
nrf_pwm_loop_set(pwm, 0);
|
||||
|
||||
// On the "Common" setting the PWM uses the same pattern for the
|
||||
// for supported sequences. The pattern is stored on half-word of 16bits
|
||||
nrf_pwm_decoder_set(pwm, PWM_DECODER_LOAD_Common, PWM_DECODER_MODE_RefreshCount);
|
||||
|
||||
// Pointer to the memory storing the pattern
|
||||
nrf_pwm_seq_ptr_set(pwm, 0, pixels_pattern);
|
||||
|
||||
// Calculation of the number of steps loaded from memory.
|
||||
nrf_pwm_seq_cnt_set(pwm, 0, pattern_size / sizeof(uint16_t));
|
||||
|
||||
// The following settings are ignored with the current config.
|
||||
nrf_pwm_seq_refresh_set(pwm, 0, 0);
|
||||
nrf_pwm_seq_end_delay_set(pwm, 0, 0);
|
||||
|
||||
// The Neopixel implementation is a blocking algorithm. DMA
|
||||
// allows for non-blocking operation. To "simulate" a blocking
|
||||
// operation we enable the interruption for the end of sequence
|
||||
// and block the execution thread until the event flag is set by
|
||||
// the peripheral.
|
||||
// pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos);
|
||||
|
||||
// PSEL must be configured before enabling PWM
|
||||
nrf_pwm_pins_set(pwm, (uint32_t[]) {digitalinout->pin->number, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL} );
|
||||
|
||||
// Enable the PWM
|
||||
nrf_pwm_enable(pwm);
|
||||
|
||||
// After all of this and many hours of reading the documentation
|
||||
// we are ready to start the sequence...
|
||||
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0);
|
||||
nrf_pwm_task_trigger(pwm, NRF_PWM_TASK_SEQSTART0);
|
||||
|
||||
// But we have to wait for the flag to be set.
|
||||
while ( !nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0) ) {
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
// Before leave we clear the flag for the event.
|
||||
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0);
|
||||
|
||||
// We need to disable the device and disconnect
|
||||
// all the outputs before leave or the device will not
|
||||
// be selected on the next call.
|
||||
// TODO: Check if disabling the device causes performance issues.
|
||||
nrf_pwm_disable(pwm);
|
||||
nrf_pwm_pins_set(pwm, (uint32_t[]) {0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL} );
|
||||
|
||||
if (pattern_on_heap) {
|
||||
m_free(pixels_pattern);
|
||||
}
|
||||
|
||||
} // End of DMA implementation
|
||||
// ---------------------------------------------------------------------
|
||||
else {
|
||||
// Fall back to DWT
|
||||
// If you are using the Bluetooth SoftDevice we advise you to not disable
|
||||
// the interrupts. Disabling the interrupts even for short periods of time
|
||||
// causes the SoftDevice to stop working.
|
||||
// Disable the interrupts only in cases where you need high performance for
|
||||
// the LEDs and if you are not using the EasyDMA feature.
|
||||
__disable_irq();
|
||||
|
||||
uint32_t decoded_pin = digitalinout->pin->number;
|
||||
NRF_GPIO_Type* port = nrf_gpio_pin_port_decode(&decoded_pin);
|
||||
|
||||
uint32_t pinMask = ( 1UL << decoded_pin );
|
||||
|
||||
uint32_t CYCLES_X00 = CYCLES_800;
|
||||
uint32_t CYCLES_X00_T1H = CYCLES_800_T1H;
|
||||
uint32_t CYCLES_X00_T0H = CYCLES_800_T0H;
|
||||
|
||||
// Enable DWT in debug core
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
|
||||
// Tries to re-send the frame if is interrupted by the SoftDevice.
|
||||
while ( 1 ) {
|
||||
uint8_t *p = pixels;
|
||||
|
||||
uint32_t cycStart = DWT->CYCCNT;
|
||||
uint32_t cyc = 0;
|
||||
|
||||
for ( uint16_t n = 0; n < numBytes; n++ ) {
|
||||
uint8_t pix = *p++;
|
||||
|
||||
for ( uint8_t mask = 0x80; mask; mask >>= 1 ) {
|
||||
while ( DWT->CYCCNT - cyc < CYCLES_X00 )
|
||||
;
|
||||
cyc = DWT->CYCCNT;
|
||||
|
||||
port->OUTSET |= pinMask;
|
||||
|
||||
if ( pix & mask ) {
|
||||
while ( DWT->CYCCNT - cyc < CYCLES_X00_T1H )
|
||||
;
|
||||
} else {
|
||||
while ( DWT->CYCCNT - cyc < CYCLES_X00_T0H )
|
||||
;
|
||||
}
|
||||
|
||||
port->OUTCLR |= pinMask;
|
||||
}
|
||||
}
|
||||
while ( DWT->CYCCNT - cyc < CYCLES_X00 )
|
||||
;
|
||||
|
||||
// If total time longer than 25%, resend the whole data.
|
||||
// Since we are likely to be interrupted by SoftDevice
|
||||
if ( (DWT->CYCCNT - cycStart) < (8 * numBytes * ((CYCLES_X00 * 5) / 4)) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// re-send need 300us delay
|
||||
mp_hal_delay_us(300);
|
||||
}
|
||||
|
||||
// Enable interrupts again
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
// Update the next start.
|
||||
current_tick(&next_start_tick_ms, &next_start_tick_us);
|
||||
if (next_start_tick_us < 100) {
|
||||
next_start_tick_ms += 1;
|
||||
next_start_tick_us = 100 - next_start_tick_us;
|
||||
} else {
|
||||
next_start_tick_us -= 100;
|
||||
}
|
||||
}
|
@ -24,13 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//TODO: Implement for STM32. File required by Microcontroller Init
|
||||
|
||||
#include "common-hal/nvm/ByteArray.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "peripherals/nrf/nvm.h"
|
||||
|
||||
// defined in linker
|
||||
extern uint32_t __fatfs_flash_start_addr[];
|
||||
extern uint32_t __fatfs_flash_length[];
|
||||
@ -43,34 +43,35 @@ uint32_t common_hal_nvm_bytearray_get_length(nvm_bytearray_obj_t *self) {
|
||||
}
|
||||
|
||||
static void write_page(uint32_t page_addr, uint32_t offset, uint32_t len, uint8_t *bytes) {
|
||||
//
|
||||
// Write a whole page to flash, buffering it first and then erasing and rewriting
|
||||
// it since we can only clear a whole page at a time.
|
||||
|
||||
if (offset == 0 && len == FLASH_PAGE_SIZE) {
|
||||
nrf_nvm_safe_flash_page_write(page_addr, bytes);
|
||||
} else {
|
||||
uint8_t buffer[FLASH_PAGE_SIZE];
|
||||
memcpy(buffer, (uint8_t *)page_addr, FLASH_PAGE_SIZE);
|
||||
memcpy(buffer + offset, bytes, len);
|
||||
nrf_nvm_safe_flash_page_write(page_addr, buffer);
|
||||
}
|
||||
// if (offset == 0 && len == FLASH_PAGE_SIZE) {
|
||||
// nrf_nvm_safe_flash_page_write(page_addr, bytes);
|
||||
// } else {
|
||||
// uint8_t buffer[FLASH_PAGE_SIZE];
|
||||
// memcpy(buffer, (uint8_t *)page_addr, FLASH_PAGE_SIZE);
|
||||
// memcpy(buffer + offset, bytes, len);
|
||||
// nrf_nvm_safe_flash_page_write(page_addr, buffer);
|
||||
// }
|
||||
}
|
||||
|
||||
bool common_hal_nvm_bytearray_set_bytes(nvm_bytearray_obj_t *self,
|
||||
uint32_t start_index, uint8_t* values, uint32_t len) {
|
||||
// uint32_t start_index, uint8_t* values, uint32_t len) {
|
||||
|
||||
uint32_t address = NVM_START_ADDR + start_index;
|
||||
uint32_t offset = address % FLASH_PAGE_SIZE;
|
||||
uint32_t page_addr = address - offset;
|
||||
// uint32_t address = NVM_START_ADDR + start_index;
|
||||
// uint32_t offset = address % FLASH_PAGE_SIZE;
|
||||
// uint32_t page_addr = address - offset;
|
||||
|
||||
while (len) {
|
||||
uint32_t write_len = MIN(len, FLASH_PAGE_SIZE - offset);
|
||||
write_page(page_addr, offset, write_len, values);
|
||||
len -= write_len;
|
||||
values += write_len;
|
||||
page_addr += FLASH_PAGE_SIZE;
|
||||
offset = 0;
|
||||
}
|
||||
// while (len) {
|
||||
// uint32_t write_len = MIN(len, FLASH_PAGE_SIZE - offset);
|
||||
// write_page(page_addr, offset, write_len, values);
|
||||
// len -= write_len;
|
||||
// values += write_len;
|
||||
// page_addr += FLASH_PAGE_SIZE;
|
||||
// offset = 0;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
@ -33,4 +33,4 @@ typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} nvm_bytearray_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_NVM_BYTEARRAY_H
|
||||
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "genhdr/mpversion.h"
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/objtuple.h"
|
||||
|
||||
#ifdef BLUETOOTH_SD
|
||||
#include "nrf_sdm.h"
|
||||
#endif
|
||||
|
||||
#include "nrf_rng.h"
|
||||
|
||||
STATIC const qstr os_uname_info_fields[] = {
|
||||
MP_QSTR_sysname, MP_QSTR_nodename,
|
||||
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
|
||||
};
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "nrf52");
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "nrf52");
|
||||
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||
|
||||
STATIC MP_DEFINE_ATTRTUPLE(
|
||||
os_uname_info_obj,
|
||||
os_uname_info_fields,
|
||||
5,
|
||||
(mp_obj_t)&os_uname_info_sysname_obj,
|
||||
(mp_obj_t)&os_uname_info_nodename_obj,
|
||||
(mp_obj_t)&os_uname_info_release_obj,
|
||||
(mp_obj_t)&os_uname_info_version_obj,
|
||||
(mp_obj_t)&os_uname_info_machine_obj
|
||||
);
|
||||
|
||||
mp_obj_t common_hal_os_uname(void) {
|
||||
return (mp_obj_t)&os_uname_info_obj;
|
||||
}
|
||||
|
||||
bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) {
|
||||
#ifdef BLUETOOTH_SD
|
||||
uint8_t sd_en = 0;
|
||||
(void) sd_softdevice_is_enabled(&sd_en);
|
||||
|
||||
if (sd_en)
|
||||
return NRF_SUCCESS == sd_rand_application_vector_get(buffer, length);
|
||||
#endif
|
||||
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
while (nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) == 0);
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
|
||||
buffer[i] = nrf_rng_random_value_get();
|
||||
}
|
||||
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
|
||||
|
||||
return true;
|
||||
}
|
@ -1,275 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
//#include "nrf.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/pulseio/PWMOut.h"
|
||||
#include "shared-bindings/pulseio/PWMOut.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
//#include "nrf_gpio.h"
|
||||
|
||||
#define PWM_MAX_FREQ (16000000)
|
||||
|
||||
STATIC NRF_PWM_Type* pwms[] = {
|
||||
#if NRFX_CHECK(NRFX_PWM0_ENABLED)
|
||||
NRF_PWM0,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM1_ENABLED)
|
||||
NRF_PWM1,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM2_ENABLED)
|
||||
NRF_PWM2,
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_PWM3_ENABLED)
|
||||
NRF_PWM3,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define CHANNELS_PER_PWM 4
|
||||
|
||||
STATIC uint16_t pwm_seq[MP_ARRAY_SIZE(pwms)][CHANNELS_PER_PWM];
|
||||
|
||||
static uint8_t never_reset_pwm[MP_ARRAY_SIZE(pwms)];
|
||||
|
||||
void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
|
||||
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
NRF_PWM_Type* pwm = pwms[i];
|
||||
if (pwm == self->pwm) {
|
||||
never_reset_pwm[i] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
never_reset_pin_number(self->pin_number);
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) {
|
||||
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
NRF_PWM_Type* pwm = pwms[i];
|
||||
if (pwm == self->pwm) {
|
||||
never_reset_pwm[i] -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pwmout_reset(void) {
|
||||
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
if (never_reset_pwm[i] > 0) {
|
||||
continue;
|
||||
}
|
||||
NRF_PWM_Type* pwm = pwms[i];
|
||||
|
||||
pwm->ENABLE = 0;
|
||||
pwm->MODE = PWM_MODE_UPDOWN_Up;
|
||||
pwm->DECODER = PWM_DECODER_LOAD_Individual;
|
||||
pwm->LOOP = 0;
|
||||
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; // default is 500 hz
|
||||
pwm->COUNTERTOP = (PWM_MAX_FREQ/500); // default is 500 hz
|
||||
|
||||
pwm->SEQ[0].PTR = (uint32_t) pwm_seq[i];
|
||||
pwm->SEQ[0].CNT = CHANNELS_PER_PWM; // default mode is Individual --> count must be 4
|
||||
pwm->SEQ[0].REFRESH = 0;
|
||||
pwm->SEQ[0].ENDDELAY = 0;
|
||||
|
||||
pwm->SEQ[1].PTR = 0;
|
||||
pwm->SEQ[1].CNT = 0;
|
||||
pwm->SEQ[1].REFRESH = 0;
|
||||
pwm->SEQ[1].ENDDELAY = 0;
|
||||
|
||||
for(int ch =0; ch < CHANNELS_PER_PWM; ch++) {
|
||||
pwm_seq[i][ch] = (1 << 15); // polarity = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the smallest prescaler value that will allow the divisor to be in range.
|
||||
// This allows the most accuracy.
|
||||
bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *base_clock) {
|
||||
uint32_t divisor = 1;
|
||||
// Use a 32-bit number so we don't overflow the uint16_t;
|
||||
uint32_t tentative_countertop;
|
||||
for (*base_clock = PWM_PRESCALER_PRESCALER_DIV_1;
|
||||
*base_clock <= PWM_PRESCALER_PRESCALER_DIV_128;
|
||||
(*base_clock)++) {
|
||||
tentative_countertop = PWM_MAX_FREQ / divisor / frequency;
|
||||
// COUNTERTOP must be 3..32767, according to datasheet, but 3 doesn't work. 4 does.
|
||||
if (tentative_countertop <= 32767 && tentative_countertop >= 4) {
|
||||
// In range, OK to return.
|
||||
*countertop = tentative_countertop;
|
||||
return true;
|
||||
}
|
||||
divisor *= 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
|
||||
const mcu_pin_obj_t* pin,
|
||||
uint16_t duty,
|
||||
uint32_t frequency,
|
||||
bool variable_frequency) {
|
||||
|
||||
// We don't use the nrfx driver here because we want to dynamically allocate channels
|
||||
// as needed in an already-enabled PWM.
|
||||
|
||||
uint16_t countertop;
|
||||
nrf_pwm_clk_t base_clock;
|
||||
if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
|
||||
return PWMOUT_INVALID_FREQUENCY;
|
||||
}
|
||||
|
||||
self->pwm = NULL;
|
||||
self->channel = CHANNELS_PER_PWM; // out-of-range value.
|
||||
bool pwm_already_in_use;
|
||||
NRF_PWM_Type* pwm;
|
||||
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
pwm = pwms[i];
|
||||
pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
|
||||
if (pwm_already_in_use) {
|
||||
if (variable_frequency) {
|
||||
// Variable frequency requires exclusive use of a PWM, so try the next one.
|
||||
continue;
|
||||
}
|
||||
|
||||
// PWM is in use, but see if it's set to the same frequency we need. If so,
|
||||
// look for a free channel.
|
||||
if (pwm->COUNTERTOP == countertop && pwm->PRESCALER == base_clock) {
|
||||
for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) {
|
||||
if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) {
|
||||
// Channel is free.
|
||||
self->pwm = pwm;
|
||||
self->channel = chan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Did we find a channel? If not, loop and check the next pwm.
|
||||
if (self->pwm != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// PWM not yet in use, so we can start to use it. Use channel 0.
|
||||
self->pwm = pwm;
|
||||
self->channel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->pwm == NULL) {
|
||||
return PWMOUT_ALL_TIMERS_IN_USE;
|
||||
}
|
||||
|
||||
self->pin_number = pin->number;
|
||||
claim_pin(pin);
|
||||
|
||||
self->frequency = frequency;
|
||||
self->variable_frequency = variable_frequency;
|
||||
|
||||
// Note this is standard, not strong drive.
|
||||
nrf_gpio_cfg_output(self->pin_number);
|
||||
|
||||
// disable before mapping pin channel
|
||||
nrf_pwm_disable(pwm);
|
||||
|
||||
if (!pwm_already_in_use) {
|
||||
nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop);
|
||||
}
|
||||
|
||||
// Connect channel to pin, without disturbing other channels.
|
||||
pwm->PSEL.OUT[self->channel] = pin->number;
|
||||
|
||||
nrf_pwm_enable(pwm);
|
||||
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
|
||||
return PWMOUT_OK;
|
||||
}
|
||||
|
||||
bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) {
|
||||
return self->pwm == NULL;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
|
||||
if (common_hal_pulseio_pwmout_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nrf_gpio_cfg_default(self->pin_number);
|
||||
|
||||
NRF_PWM_Type* pwm = self->pwm;
|
||||
self->pwm = NULL;
|
||||
|
||||
// Disconnect pin from channel.
|
||||
pwm->PSEL.OUT[self->channel] = 0xFFFFFFFF;
|
||||
|
||||
for(int i=0; i < CHANNELS_PER_PWM; i++) {
|
||||
if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFF) {
|
||||
// Some channel is still being used, so don't disable.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nrf_pwm_disable(pwm);
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) {
|
||||
self->duty_cycle = duty_cycle;
|
||||
|
||||
uint16_t* p_value = ((uint16_t*)self->pwm->SEQ[0].PTR) + self->channel;
|
||||
*p_value = ((duty_cycle * self->pwm->COUNTERTOP) / 0xFFFF) | (1 << 15);
|
||||
|
||||
self->pwm->TASKS_SEQSTART[0] = 1;
|
||||
}
|
||||
|
||||
uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
|
||||
return self->duty_cycle;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) {
|
||||
// COUNTERTOP is 3..32767, so highest available frequency is PWM_MAX_FREQ / 3.
|
||||
uint16_t countertop;
|
||||
nrf_pwm_clk_t base_clock;
|
||||
if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
|
||||
mp_raise_ValueError(translate("Invalid PWM frequency"));
|
||||
}
|
||||
self->frequency = frequency;
|
||||
|
||||
nrf_pwm_configure(self->pwm, base_clock, NRF_PWM_MODE_UP, countertop);
|
||||
// Set the duty cycle again, because it depends on COUNTERTOP, which probably changed.
|
||||
// Setting the duty cycle will also do a SEQSTART.
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(self, self->duty_cycle);
|
||||
}
|
||||
|
||||
uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
|
||||
return self->frequency;
|
||||
}
|
||||
|
||||
bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {
|
||||
return self->variable_frequency;
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H
|
||||
|
||||
//#include "nrfx_pwm.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
NRF_PWM_Type* pwm;
|
||||
uint8_t pin_number;
|
||||
uint8_t channel: 7;
|
||||
bool variable_frequency: 1;
|
||||
uint16_t duty_cycle;
|
||||
uint32_t frequency;
|
||||
} pulseio_pwmout_obj_t;
|
||||
|
||||
void pwmout_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H
|
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/pulseio/PulseIn.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/pulseio/PulseIn.h"
|
||||
|
||||
#include "tick.h"
|
||||
//#include "nrfx_gpiote.h"
|
||||
|
||||
// obj array to map pin -> self since nrfx hide the mapping
|
||||
static pulseio_pulsein_obj_t* _objs[GPIOTE_CH_NUM];
|
||||
|
||||
// return index of the object in array
|
||||
static int _find_pulsein_obj(pulseio_pulsein_obj_t* obj) {
|
||||
for(size_t i = 0; i < NRFX_ARRAY_SIZE(_objs); i++ ) {
|
||||
if ( _objs[i] == obj) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _pulsein_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
// Grab the current time first.
|
||||
uint32_t current_us;
|
||||
uint64_t current_ms;
|
||||
current_tick(¤t_ms, ¤t_us);
|
||||
|
||||
// current_tick gives us the remaining us until the next tick but we want the number since the last ms.
|
||||
current_us = 1000 - current_us;
|
||||
|
||||
pulseio_pulsein_obj_t* self = NULL;
|
||||
for(size_t i = 0; i < NRFX_ARRAY_SIZE(_objs); i++ ) {
|
||||
if ( _objs[i] && _objs[i]->pin == pin ) {
|
||||
self = _objs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !self ) return;
|
||||
|
||||
if (self->first_edge) {
|
||||
// first pulse is opposite state from idle
|
||||
bool state = nrf_gpio_pin_read(self->pin);
|
||||
if ( self->idle_state != state ) {
|
||||
self->first_edge = false;
|
||||
}
|
||||
}else {
|
||||
uint32_t ms_diff = current_ms - self->last_ms;
|
||||
uint16_t us_diff = current_us - self->last_us;
|
||||
uint32_t total_diff = us_diff;
|
||||
|
||||
if (self->last_us > current_us) {
|
||||
total_diff = 1000 + current_us - self->last_us;
|
||||
if (ms_diff > 1) {
|
||||
total_diff += (ms_diff - 1) * 1000;
|
||||
}
|
||||
} else {
|
||||
total_diff += ms_diff * 1000;
|
||||
}
|
||||
uint16_t duration = 0xffff;
|
||||
if (total_diff < duration) {
|
||||
duration = total_diff;
|
||||
}
|
||||
|
||||
uint16_t i = (self->start + self->len) % self->maxlen;
|
||||
self->buffer[i] = duration;
|
||||
if (self->len < self->maxlen) {
|
||||
self->len++;
|
||||
} else {
|
||||
self->start++;
|
||||
}
|
||||
}
|
||||
|
||||
self->last_ms = current_ms;
|
||||
self->last_us = current_us;
|
||||
}
|
||||
|
||||
void pulsein_reset(void) {
|
||||
if ( nrfx_gpiote_is_init() ) {
|
||||
nrfx_gpiote_uninit();
|
||||
}
|
||||
nrfx_gpiote_init();
|
||||
|
||||
memset(_objs, 0, sizeof(_objs));
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, uint16_t maxlen, bool idle_state) {
|
||||
int idx = _find_pulsein_obj(NULL);
|
||||
if ( idx < 0 ) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
}
|
||||
_objs[idx] = self;
|
||||
|
||||
self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
|
||||
if (self->buffer == NULL) {
|
||||
mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
self->pin = pin->number;
|
||||
self->maxlen = maxlen;
|
||||
self->idle_state = idle_state;
|
||||
self->start = 0;
|
||||
self->len = 0;
|
||||
self->first_edge = true;
|
||||
self->paused = false;
|
||||
self->last_us = 0;
|
||||
self->last_ms = 0;
|
||||
|
||||
claim_pin(pin);
|
||||
|
||||
nrfx_gpiote_in_config_t cfg = {
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
.pull = NRF_GPIO_PIN_NOPULL, // idle_state ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP,
|
||||
.is_watcher = false, // nrf_gpio_cfg_watcher vs nrf_gpio_cfg_input
|
||||
.hi_accuracy = true,
|
||||
.skip_gpio_setup = false
|
||||
};
|
||||
nrfx_gpiote_in_init(self->pin, &cfg, _pulsein_handler);
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
|
||||
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
|
||||
return self->pin == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
|
||||
if (common_hal_pulseio_pulsein_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nrfx_gpiote_in_event_disable(self->pin);
|
||||
nrfx_gpiote_in_uninit(self->pin);
|
||||
|
||||
// mark local array as invalid
|
||||
int idx = _find_pulsein_obj(self);
|
||||
if ( idx < 0 ) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
}
|
||||
_objs[idx] = NULL;
|
||||
|
||||
reset_pin_number(self->pin);
|
||||
self->pin = NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
|
||||
nrfx_gpiote_in_event_disable(self->pin);
|
||||
self->paused = true;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
|
||||
// Make sure we're paused.
|
||||
if ( !self->paused ) {
|
||||
common_hal_pulseio_pulsein_pause(self);
|
||||
}
|
||||
|
||||
// Send the trigger pulse.
|
||||
if (trigger_duration > 0) {
|
||||
nrfx_gpiote_in_uninit(self->pin);
|
||||
|
||||
nrf_gpio_cfg_output(self->pin);
|
||||
nrf_gpio_pin_write(self->pin, !self->idle_state);
|
||||
common_hal_mcu_delay_us((uint32_t)trigger_duration);
|
||||
nrf_gpio_pin_write(self->pin, self->idle_state);
|
||||
|
||||
nrfx_gpiote_in_config_t cfg = {
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
.pull = NRF_GPIO_PIN_NOPULL, // idle_state ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP,
|
||||
.is_watcher = false, // nrf_gpio_cfg_watcher vs nrf_gpio_cfg_input
|
||||
.hi_accuracy = true,
|
||||
.skip_gpio_setup = false
|
||||
};
|
||||
nrfx_gpiote_in_init(self->pin, &cfg, _pulsein_handler);
|
||||
}
|
||||
|
||||
self->first_edge = true;
|
||||
self->paused = false;
|
||||
self->last_ms = 0;
|
||||
self->last_us = 0;
|
||||
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_disable(self->pin);
|
||||
}
|
||||
|
||||
self->start = 0;
|
||||
self->len = 0;
|
||||
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_disable(self->pin);
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
index += self->len;
|
||||
}
|
||||
if (index < 0 || index >= self->len) {
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
mp_raise_IndexError(translate("index out of range"));
|
||||
}
|
||||
uint16_t value = self->buffer[(self->start + index) % self->maxlen];
|
||||
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
|
||||
if (self->len == 0) {
|
||||
mp_raise_IndexError(translate("pop from an empty PulseIn"));
|
||||
}
|
||||
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_disable(self->pin);
|
||||
}
|
||||
|
||||
uint16_t value = self->buffer[self->start];
|
||||
self->start = (self->start + 1) % self->maxlen;
|
||||
self->len--;
|
||||
|
||||
if ( !self->paused ) {
|
||||
nrfx_gpiote_in_event_enable(self->pin, true);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) {
|
||||
return self->maxlen;
|
||||
}
|
||||
|
||||
bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
|
||||
return self->paused;
|
||||
}
|
||||
|
||||
uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
|
||||
return self->len;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEIN_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEIN_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
|
||||
uint8_t pin;
|
||||
bool idle_state;
|
||||
bool paused;
|
||||
volatile bool first_edge;
|
||||
|
||||
uint16_t* buffer;
|
||||
uint16_t maxlen;
|
||||
|
||||
volatile uint16_t start;
|
||||
volatile uint16_t len;
|
||||
volatile uint16_t last_us;
|
||||
volatile uint64_t last_ms;
|
||||
} pulseio_pulsein_obj_t;
|
||||
|
||||
void pulsein_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEIN_H
|
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/pulseio/PulseOut.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
//#include "nrf/pins.h"
|
||||
//#include "nrf/timers.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/pulseio/PulseOut.h"
|
||||
#include "shared-bindings/pulseio/PWMOut.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
// A single timer is shared amongst all PulseOut objects under the assumption that
|
||||
// the code is single threaded.
|
||||
static uint8_t refcount = 0;
|
||||
|
||||
static nrfx_timer_t *timer = NULL;
|
||||
|
||||
static uint16_t *pulse_array = NULL;
|
||||
static volatile uint16_t pulse_array_index = 0;
|
||||
static uint16_t pulse_array_length;
|
||||
|
||||
static void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
||||
pulseout->pwmout->pwm->PSEL.OUT[0] = pulseout->pwmout->pin_number;
|
||||
}
|
||||
|
||||
static void turn_off(pulseio_pulseout_obj_t *pulseout) {
|
||||
// Disconnect pin from PWM.
|
||||
pulseout->pwmout->pwm->PSEL.OUT[0] = 0xffffffff;
|
||||
// Make sure pin is low.
|
||||
nrf_gpio_pin_clear(pulseout->pwmout->pin_number);
|
||||
}
|
||||
|
||||
static void start_timer(void) {
|
||||
nrfx_timer_clear(timer);
|
||||
// true enables interrupt.
|
||||
nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL0, pulse_array[pulse_array_index], true);
|
||||
nrfx_timer_resume(timer);
|
||||
}
|
||||
|
||||
static void pulseout_event_handler(nrf_timer_event_t event_type, void *p_context) {
|
||||
pulseio_pulseout_obj_t *pulseout = (pulseio_pulseout_obj_t*) p_context;
|
||||
if (event_type != NRF_TIMER_EVENT_COMPARE0) {
|
||||
// Spurious event.
|
||||
return;
|
||||
}
|
||||
nrfx_timer_pause(timer);
|
||||
|
||||
pulse_array_index++;
|
||||
|
||||
// No more pulses. Turn off output and don't restart.
|
||||
if (pulse_array_index >= pulse_array_length) {
|
||||
turn_off(pulseout);
|
||||
return;
|
||||
}
|
||||
|
||||
// Alternate on and off, starting with on.
|
||||
if (pulse_array_index % 2 == 0) {
|
||||
turn_on(pulseout);
|
||||
} else {
|
||||
turn_off(pulseout);
|
||||
}
|
||||
|
||||
// Count up to the next given value.
|
||||
start_timer();
|
||||
}
|
||||
|
||||
void pulseout_reset() {
|
||||
if (timer != NULL) {
|
||||
nrf_peripherals_free_timer(timer);
|
||||
}
|
||||
refcount = 0;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
||||
const pulseio_pwmout_obj_t* carrier) {
|
||||
if (refcount == 0) {
|
||||
timer = nrf_peripherals_allocate_timer();
|
||||
if (timer == NULL) {
|
||||
mp_raise_RuntimeError(translate("All timers in use"));
|
||||
}
|
||||
}
|
||||
refcount++;
|
||||
|
||||
nrfx_timer_config_t timer_config = {
|
||||
// PulseOut durations are in microseconds, so this is convenient.
|
||||
.frequency = NRF_TIMER_FREQ_1MHz,
|
||||
.mode = NRF_TIMER_MODE_TIMER,
|
||||
.bit_width = NRF_TIMER_BIT_WIDTH_32,
|
||||
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
|
||||
.p_context = self,
|
||||
};
|
||||
|
||||
self->pwmout = carrier;
|
||||
|
||||
nrfx_timer_init(timer, &timer_config, &pulseout_event_handler);
|
||||
turn_off(self);
|
||||
}
|
||||
|
||||
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
|
||||
return self->pwmout == NULL;
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
|
||||
if (common_hal_pulseio_pulseout_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
turn_on(self);
|
||||
self->pwmout = NULL;
|
||||
|
||||
refcount--;
|
||||
if (refcount == 0) {
|
||||
nrf_peripherals_free_timer(timer);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) {
|
||||
pulse_array = pulses;
|
||||
pulse_array_index = 0;
|
||||
pulse_array_length = length;
|
||||
|
||||
nrfx_timer_enable(timer);
|
||||
|
||||
turn_on(self);
|
||||
// Count up to the next given value.
|
||||
start_timer();
|
||||
|
||||
while(pulse_array_index < length) {
|
||||
// Do other things while we wait. The interrupts will handle sending the
|
||||
// signal.
|
||||
#ifdef MICROPY_VM_HOOK_LOOP
|
||||
MICROPY_VM_HOOK_LOOP
|
||||
#endif
|
||||
}
|
||||
|
||||
nrfx_timer_disable(timer);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEOUT_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEOUT_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/pulseio/PWMOut.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const pulseio_pwmout_obj_t *pwmout;
|
||||
} pulseio_pulseout_obj_t;
|
||||
|
||||
void pulseout_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEOUT_H
|
@ -1 +0,0 @@
|
||||
// No pulseio module functions.
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
#include "nrfx_gpiote.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// obj array to map pin number -> self since nrfx hide the mapping
|
||||
static rotaryio_incrementalencoder_obj_t *_objs[NUMBER_OF_PINS];
|
||||
|
||||
static void _intr_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
rotaryio_incrementalencoder_obj_t *self = _objs[pin];
|
||||
if (!self) return;
|
||||
|
||||
// reads a state 0 .. 3 *in order*.
|
||||
uint8_t new_state = nrf_gpio_pin_read(self->pin_a);
|
||||
new_state = (new_state << 1) + (new_state ^ nrf_gpio_pin_read(self->pin_b));
|
||||
|
||||
uint8_t change = (new_state - self->state) & 0x03;
|
||||
if (change == 1) self->quarter++;
|
||||
else if (change == 3) self->quarter--;
|
||||
// ignore other state transitions
|
||||
|
||||
self->state = new_state;
|
||||
|
||||
// logic from the atmel-samd port: provides some damping and scales movement
|
||||
// down by 4:1.
|
||||
if (self->quarter >= 4) {
|
||||
self->position++;
|
||||
self->quarter = 0;
|
||||
} else if (self->quarter <= -4) {
|
||||
self->position--;
|
||||
self->quarter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self,
|
||||
const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b) {
|
||||
|
||||
self->pin_a = pin_a->number;
|
||||
self->pin_b = pin_b->number;
|
||||
|
||||
_objs[self->pin_a] = self;
|
||||
_objs[self->pin_b] = self;
|
||||
|
||||
nrfx_gpiote_in_config_t cfg = {
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
.pull = NRF_GPIO_PIN_PULLUP,
|
||||
.is_watcher = false,
|
||||
.hi_accuracy = true,
|
||||
.skip_gpio_setup = false
|
||||
};
|
||||
nrfx_gpiote_in_init(self->pin_a, &cfg, _intr_handler);
|
||||
nrfx_gpiote_in_init(self->pin_b, &cfg, _intr_handler);
|
||||
nrfx_gpiote_in_event_enable(self->pin_a, true);
|
||||
nrfx_gpiote_in_event_enable(self->pin_b, true);
|
||||
|
||||
claim_pin(pin_a);
|
||||
claim_pin(pin_b);
|
||||
}
|
||||
|
||||
bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self) {
|
||||
return self->pin_a == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self) {
|
||||
if (common_hal_rotaryio_incrementalencoder_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
_objs[self->pin_a] = NULL;
|
||||
_objs[self->pin_b] = NULL;
|
||||
|
||||
nrfx_gpiote_in_event_disable(self->pin_a);
|
||||
nrfx_gpiote_in_event_disable(self->pin_b);
|
||||
nrfx_gpiote_in_uninit(self->pin_a);
|
||||
nrfx_gpiote_in_uninit(self->pin_b);
|
||||
reset_pin_number(self->pin_a);
|
||||
reset_pin_number(self->pin_b);
|
||||
self->pin_a = NO_PIN;
|
||||
self->pin_b = NO_PIN;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self) {
|
||||
return self->position;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self,
|
||||
mp_int_t new_position) {
|
||||
self->position = new_position;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint8_t pin_a;
|
||||
uint8_t pin_b;
|
||||
uint8_t state;
|
||||
int8_t quarter;
|
||||
mp_int_t position;
|
||||
} rotaryio_incrementalencoder_obj_t;
|
||||
|
||||
|
||||
void incrementalencoder_interrupt_handler(uint8_t channel);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
|
@ -1 +0,0 @@
|
||||
// No rotaryio module functions.
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "shared-bindings/rtc/__init__.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#include "nrfx_rtc.h"
|
||||
#include "nrf_clock.h"
|
||||
|
||||
// We clock the RTC very slowly (8Hz) so that it won't overflow often.
|
||||
// But the counter is only 24 bits, so overflow is about every 24 days ...
|
||||
// For testing, set this to 32768 and it'll overflow every few minutes
|
||||
|
||||
#define RTC_CLOCK_HZ (8)
|
||||
|
||||
volatile static uint32_t rtc_offset = 0;
|
||||
|
||||
const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(2);
|
||||
|
||||
const nrfx_rtc_config_t rtc_config = {
|
||||
.prescaler = RTC_FREQ_TO_PRESCALER(RTC_CLOCK_HZ),
|
||||
.reliable = 0,
|
||||
.tick_latency = 0,
|
||||
.interrupt_priority = 6
|
||||
};
|
||||
|
||||
void rtc_handler(nrfx_rtc_int_type_t int_type) {
|
||||
if (int_type == NRFX_RTC_INT_OVERFLOW) {
|
||||
rtc_offset += (1L<<24) / RTC_CLOCK_HZ;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_init(void) {
|
||||
if (!nrf_clock_lf_is_running()) {
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
|
||||
}
|
||||
nrfx_rtc_counter_clear(&rtc_instance);
|
||||
nrfx_rtc_init(&rtc_instance, &rtc_config, rtc_handler);
|
||||
nrfx_rtc_enable(&rtc_instance);
|
||||
nrfx_rtc_overflow_enable(&rtc_instance, 1);
|
||||
}
|
||||
|
||||
void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
|
||||
uint32_t t = rtc_offset + (nrfx_rtc_counter_get(&rtc_instance) / RTC_CLOCK_HZ );
|
||||
timeutils_seconds_since_2000_to_struct_time(t, tm);
|
||||
}
|
||||
|
||||
void common_hal_rtc_set_time(timeutils_struct_time_t *tm) {
|
||||
rtc_offset = timeutils_seconds_since_2000(
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec
|
||||
);
|
||||
nrfx_rtc_counter_clear(&rtc_instance);
|
||||
}
|
||||
|
||||
int common_hal_rtc_get_calibration(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_rtc_set_calibration(int calibration) {
|
||||
mp_raise_NotImplementedError(translate("RTC calibration is not supported on this board"));
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Noralf Trønnes
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H
|
||||
|
||||
extern void rtc_init(void);
|
||||
extern void rtc_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H
|
@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
@ -34,4 +34,4 @@ typedef struct {
|
||||
// Stores no state currently.
|
||||
} super_runtime_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
|
||||
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2018 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/binary.h"
|
||||
#include "py/mphal.h"
|
||||
#include "shared-bindings/touchio/TouchIn.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#include "nrf.h"
|
||||
|
||||
// This is a capacitive touch sensing routine using a single digital
|
||||
// pin. The pin should be connected to the sensing pad, and to ground
|
||||
// via a 1Mohm or thereabout drain resistor. When a reading is taken,
|
||||
// the pin's capacitance is charged by setting it to a digital output
|
||||
// 'high' for a few microseconds, and then it is changed to a high
|
||||
// impedance input. We measure how long it takes to discharge through
|
||||
// the resistor (around 50us), using a busy-waiting loop, and average
|
||||
// over N_SAMPLES cycles to reduce the effects of noise.
|
||||
|
||||
#define N_SAMPLES 10
|
||||
#define TIMEOUT_TICKS 10000
|
||||
|
||||
static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
|
||||
|
||||
uint16_t ticks = 0;
|
||||
|
||||
for (uint16_t i = 0; i < N_SAMPLES; i++) {
|
||||
// set pad to digital output high for 10us to charge it
|
||||
|
||||
nrf_gpio_cfg_output(self->pin->number);
|
||||
nrf_gpio_pin_set(self->pin->number);
|
||||
mp_hal_delay_us(10);
|
||||
|
||||
// set pad back to an input and take some samples
|
||||
|
||||
nrf_gpio_cfg_input(self->pin->number, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
while(nrf_gpio_pin_read(self->pin->number)) {
|
||||
if (ticks >= TIMEOUT_TICKS) return TIMEOUT_TICKS;
|
||||
ticks++;
|
||||
}
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
|
||||
const mcu_pin_obj_t *pin) {
|
||||
self->pin = pin;
|
||||
claim_pin(pin);
|
||||
|
||||
self->threshold = get_raw_reading(self) * 1.05 + 100;
|
||||
}
|
||||
|
||||
bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t* self) {
|
||||
return self->pin == NULL;
|
||||
}
|
||||
|
||||
void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t* self) {
|
||||
if (common_hal_touchio_touchin_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reset_pin_number(self->pin->number);
|
||||
self->pin = NULL;
|
||||
}
|
||||
|
||||
void touchin_reset() {
|
||||
}
|
||||
|
||||
bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) {
|
||||
uint16_t reading = get_raw_reading(self);
|
||||
return reading > self->threshold;
|
||||
}
|
||||
|
||||
uint16_t common_hal_touchio_touchin_get_raw_value(touchio_touchin_obj_t *self) {
|
||||
return get_raw_reading(self);
|
||||
}
|
||||
|
||||
uint16_t common_hal_touchio_touchin_get_threshold(touchio_touchin_obj_t *self) {
|
||||
return self->threshold;
|
||||
}
|
||||
|
||||
void common_hal_touchio_touchin_set_threshold(touchio_touchin_obj_t *self,
|
||||
uint16_t new_threshold) {
|
||||
self->threshold = new_threshold;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
* Copyright (c) 2018 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t *pin;
|
||||
uint16_t threshold;
|
||||
} touchio_touchin_obj_t;
|
||||
|
||||
void touchin_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
|
@ -1 +0,0 @@
|
||||
// No touchio module functions.
|
@ -3,74 +3,20 @@
|
||||
# This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h.
|
||||
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
|
||||
|
||||
# Internal math library is substantially smaller than toolchain one
|
||||
INTERNAL_LIBM = 1
|
||||
|
||||
# Chip supplied serial number, in bytes
|
||||
USB_SERIAL_NUMBER_LENGTH = 16
|
||||
|
||||
# All nRF ports have longints.
|
||||
# Longints can be implemented as mpz, as longlong, or not
|
||||
LONGINT_IMPL = MPZ
|
||||
|
||||
# No DAC, so no regular audio.
|
||||
CIRCUITPY_AUDIOIO = 0
|
||||
#Reduced feature set for early port
|
||||
CIRCUITPY_MINIMAL_BUILD = 1
|
||||
|
||||
# No I2S yet.
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
|
||||
# No I2CSlave implementation
|
||||
CIRCUITPY_I2CSLAVE = 0
|
||||
|
||||
# enable NVM
|
||||
CIRCUITPY_NVM = 1
|
||||
|
||||
# enable RTC
|
||||
CIRCUITPY_RTC = 1
|
||||
|
||||
#LUCIAN HATES FEATURES
|
||||
MICROPY_HW_LED_RX = 0
|
||||
MICROPY_HW_LED_TX = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_ANALOGIO = 0
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_AUDIOIO = 0
|
||||
CIRCUITPY_BITBANGIO = 0
|
||||
CIRCUITPY_BLEIO = 0
|
||||
CIRCUITPY_BOARD = 1
|
||||
CIRCUITPY_BUSIO = 0
|
||||
CIRCUITPY_DIGITALIO = 1
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_GAMEPADSHIFT = 0
|
||||
CIRCUITPY_I2CSLAVE = 0
|
||||
CIRCUITPY_MATH = 0
|
||||
CIRCUITPY_MICROCONTROLLER = 1
|
||||
CIRCUITPY_NEOPIXEL_WRITE = 0
|
||||
CIRCUITPY_NETWORK = 0
|
||||
CIRCUITPY_NVM = 0
|
||||
CIRCUITPY_OS = 0
|
||||
CIRCUITPY_PIXELBUF = 0
|
||||
CIRCUITPY_PULSEIO = 0
|
||||
CIRCUITPY_PS2IO = 0
|
||||
CIRCUITPY_RANDOM = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_RTC = 0
|
||||
CIRCUITPY_SAMD = 0
|
||||
CIRCUITPY_STAGE = 0
|
||||
CIRCUITPY_STORAGE = 0
|
||||
CIRCUITPY_STRUCT = 0
|
||||
CIRCUITPY_SUPERVISOR = 0
|
||||
CIRCUITPY_TIME = 0
|
||||
CIRCUITPY_TOUCHIO = 0
|
||||
CIRCUITPY_UHEAP = 0
|
||||
CIRCUITPY_USB_HID = 0
|
||||
CIRCUITPY_USB_MIDI = 0
|
||||
CIRCUITPY_USTACK = 0
|
||||
CIRCUITPY_PEW = 0
|
||||
|
||||
# frequencyio not yet implemented
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
|
||||
# CircuitPython doesn't yet support NFC so force the NFC antenna pins to be GPIO.
|
||||
# See https://github.com/adafruit/circuitpython/issues/1300
|
||||
# Defined here because system_nrf52840.c doesn't #include any of our own include files.
|
||||
CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS
|
||||
ifeq ($(MCU_SUB_VARIANT), stm32f412zx)
|
||||
CIRCUITPY_BOARD = 1
|
||||
CIRCUITPY_DIGITALIO = 1
|
||||
CIRCUITPY_MICROCONTROLLER = 1
|
||||
endif
|
||||
|
@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __NRF52_HAL
|
||||
#define __NRF52_HAL
|
||||
#ifndef __STM32F4_HAL
|
||||
#define __STM32F4_HAL
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nrfx.h"
|
||||
|
||||
// Turn off cache and invalidate all data in it.
|
||||
void nrf_peripherals_disable_and_clear_cache(void) {
|
||||
// Disabling cache also invalidates all cache entries.
|
||||
NRF_NVMC->ICACHECNF &= ~(1 << NVMC_ICACHECNF_CACHEEN_Pos);
|
||||
}
|
||||
|
||||
// Enable cache
|
||||
void nrf_peripherals_enable_cache(void) {
|
||||
NRF_NVMC->ICACHECNF |= 1 << NVMC_ICACHECNF_CACHEEN_Pos;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void nrf_peripherals_disable_and_clear_cache(void);
|
||||
void nrf_peripherals_enable_cache(void);
|
@ -1,38 +0,0 @@
|
||||
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nrfx.h"
|
||||
|
||||
void nrf_peripherals_clocks_init(void) {
|
||||
// Set low-frequency clock source to be crystal. If there's a crystalless board, this will need to be
|
||||
// generalized.
|
||||
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
|
||||
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
|
||||
|
||||
// Wait for clocks to start.
|
||||
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,4 +24,4 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void nrf_peripherals_clocks_init(void);
|
||||
void stm32f4_peripherals_clocks_init(void);
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,4 +24,4 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void nrf_peripherals_power_init(void);
|
||||
void stm32f4_peripherals_gpio_init(void);
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2019 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nrf_nvmc.h"
|
||||
|
||||
#define FLASH_PAGE_SIZE (4096)
|
||||
|
||||
#ifdef BLUETOOTH_SD
|
||||
#include "ble_drv.h"
|
||||
#include "nrf_sdm.h"
|
||||
|
||||
STATIC void sd_flash_operation_start(void) {
|
||||
sd_flash_operation_status = SD_FLASH_OPERATION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
STATIC sd_flash_operation_status_t sd_flash_operation_wait_until_done(void) {
|
||||
while (sd_flash_operation_status == SD_FLASH_OPERATION_IN_PROGRESS) {
|
||||
sd_app_evt_wait();
|
||||
}
|
||||
return sd_flash_operation_status;
|
||||
}
|
||||
#endif
|
||||
|
||||
void nrf_nvm_safe_flash_page_write(uint32_t page_addr, uint8_t *data) {
|
||||
#ifdef BLUETOOTH_SD
|
||||
uint8_t sd_en = 0;
|
||||
(void) sd_softdevice_is_enabled(&sd_en);
|
||||
if (sd_en) {
|
||||
uint32_t err_code;
|
||||
sd_flash_operation_status_t status;
|
||||
|
||||
sd_flash_operation_start();
|
||||
err_code = sd_flash_page_erase(page_addr / FLASH_PAGE_SIZE);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Flash erase failed to start, err 0x%04x"), err_code);
|
||||
}
|
||||
status = sd_flash_operation_wait_until_done();
|
||||
if (status == SD_FLASH_OPERATION_ERROR) {
|
||||
mp_raise_OSError_msg(translate("Flash erase failed"));
|
||||
}
|
||||
|
||||
// Divide a full page into parts, because writing a full page causes an assertion failure.
|
||||
// See https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert/
|
||||
const size_t BLOCK_PARTS = 2;
|
||||
size_t words_to_write = FLASH_PAGE_SIZE / sizeof(uint32_t) / BLOCK_PARTS;
|
||||
for (size_t i = 0; i < BLOCK_PARTS; i++) {
|
||||
sd_flash_operation_start();
|
||||
err_code = sd_flash_write(((uint32_t *)page_addr) + i * words_to_write,
|
||||
(uint32_t *)data + i * words_to_write,
|
||||
words_to_write);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Flash write failed to start, err 0x%04x"), err_code);
|
||||
}
|
||||
status = sd_flash_operation_wait_until_done();
|
||||
if (status == SD_FLASH_OPERATION_ERROR) {
|
||||
mp_raise_OSError_msg(translate("Flash write failed"));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
nrf_nvmc_page_erase(page_addr);
|
||||
nrf_nvmc_write_bytes(page_addr, data, FLASH_PAGE_SIZE);
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2019 Nick Moore for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define FLASH_PAGE_SIZE (4096)
|
||||
|
||||
#ifndef CIRCUITPY_INTERNAL_NVM_SIZE
|
||||
#define CIRCUITPY_INTERNAL_NVM_SIZE (0)
|
||||
#endif
|
||||
|
||||
void nrf_nvm_safe_flash_page_write(uint32_t page_addr, uint8_t *data);
|
@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -66,7 +67,7 @@ extern const mp_obj_type_t mcu_pin_type;
|
||||
|
||||
// Choose based on chip
|
||||
#ifdef STM32F412Zx
|
||||
#include "stm32f412zg/pins.h"
|
||||
#include "stm32f412zx/pins.h"
|
||||
#endif
|
||||
|
||||
#endif // __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PINS_H__
|
||||
|
63
ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
Normal file
63
ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
void stm32f4_peripherals_clocks_init(void) {
|
||||
//System clock init
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
/** Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 192;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 8;
|
||||
HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
/** Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SN = 200;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SM = 5;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
}
|
137
ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
Normal file
137
ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* GPIO PIN REFERENCE
|
||||
#define DATA_Ready_Pin GPIO_PIN_2
|
||||
#define DATA_Ready_GPIO_Port GPIOE
|
||||
#define CS_I2C_SPI_Pin GPIO_PIN_3
|
||||
#define CS_I2C_SPI_GPIO_Port GPIOE
|
||||
#define INT1_Pin GPIO_PIN_4
|
||||
#define INT1_GPIO_Port GPIOE
|
||||
#define INT2_Pin GPIO_PIN_5
|
||||
#define INT2_GPIO_Port GPIOE
|
||||
#define PC14_OSC32_IN_Pin GPIO_PIN_14
|
||||
#define PC14_OSC32_IN_GPIO_Port GPIOC
|
||||
#define PC15_OSC32_OUT_Pin GPIO_PIN_15
|
||||
#define PC15_OSC32_OUT_GPIO_Port GPIOC
|
||||
#define PH0_OSC_IN_Pin GPIO_PIN_0
|
||||
#define PH0_OSC_IN_GPIO_Port GPIOH
|
||||
#define PH1_OSC_OUT_Pin GPIO_PIN_1
|
||||
#define PH1_OSC_OUT_GPIO_Port GPIOH
|
||||
#define OTG_FS_PowerSwitchOn_Pin GPIO_PIN_0
|
||||
#define OTG_FS_PowerSwitchOn_GPIO_Port GPIOC
|
||||
#define PDM_OUT_Pin GPIO_PIN_3
|
||||
#define PDM_OUT_GPIO_Port GPIOC
|
||||
#define I2S3_WS_Pin GPIO_PIN_4
|
||||
#define I2S3_WS_GPIO_Port GPIOA
|
||||
#define SPI1_SCK_Pin GPIO_PIN_5
|
||||
#define SPI1_SCK_GPIO_Port GPIOA
|
||||
#define SPI1_MISO_Pin GPIO_PIN_6
|
||||
#define SPI1_MISO_GPIO_Port GPIOA
|
||||
#define SPI1_MOSI_Pin GPIO_PIN_7
|
||||
#define SPI1_MOSI_GPIO_Port GPIOA
|
||||
#define CLK_IN_Pin GPIO_PIN_10
|
||||
#define CLK_IN_GPIO_Port GPIOB
|
||||
#define LD4_Pin GPIO_PIN_12
|
||||
#define LD4_GPIO_Port GPIOD
|
||||
#define LD3_Pin GPIO_PIN_13
|
||||
#define LD3_GPIO_Port GPIOD
|
||||
#define LD5_Pin GPIO_PIN_14
|
||||
#define LD5_GPIO_Port GPIOD
|
||||
#define LD6_Pin GPIO_PIN_15
|
||||
#define LD6_GPIO_Port GPIOD
|
||||
#define I2S3_MCK_Pin GPIO_PIN_7
|
||||
#define I2S3_MCK_GPIO_Port GPIOC
|
||||
#define VBUS_FS_Pin GPIO_PIN_9
|
||||
#define VBUS_FS_GPIO_Port GPIOA
|
||||
#define OTG_FS_ID_Pin GPIO_PIN_10
|
||||
#define OTG_FS_ID_GPIO_Port GPIOA
|
||||
#define OTG_FS_DM_Pin GPIO_PIN_11
|
||||
#define OTG_FS_DM_GPIO_Port GPIOA
|
||||
#define OTG_FS_DP_Pin GPIO_PIN_12
|
||||
#define OTG_FS_DP_GPIO_Port GPIOA
|
||||
#define SWDIO_Pin GPIO_PIN_13
|
||||
#define SWDIO_GPIO_Port GPIOA
|
||||
#define SWCLK_Pin GPIO_PIN_14
|
||||
#define SWCLK_GPIO_Port GPIOA
|
||||
#define I2S3_SCK_Pin GPIO_PIN_10
|
||||
#define I2S3_SCK_GPIO_Port GPIOC
|
||||
#define I2S3_SD_Pin GPIO_PIN_12
|
||||
#define I2S3_SD_GPIO_Port GPIOC
|
||||
#define Audio_RST_Pin GPIO_PIN_4
|
||||
#define Audio_RST_GPIO_Port GPIOD
|
||||
#define OTG_FS_OverCurrent_Pin GPIO_PIN_5
|
||||
#define OTG_FS_OverCurrent_GPIO_Port GPIOD
|
||||
#define SWO_Pin GPIO_PIN_3
|
||||
#define SWO_GPIO_Port GPIOB
|
||||
#define Audio_SCL_Pin GPIO_PIN_6
|
||||
#define Audio_SCL_GPIO_Port GPIOB
|
||||
#define Audio_SDA_Pin GPIO_PIN_9
|
||||
#define Audio_SDA_GPIO_Port GPIOB
|
||||
#define MEMS_INT2_Pin GPIO_PIN_1
|
||||
#define MEMS_INT2_GPIO_Port GPIOE
|
||||
*/
|
||||
|
||||
#define LD4_Pin GPIO_PIN_12
|
||||
#define LD4_GPIO_Port GPIOD
|
||||
#define LD3_Pin GPIO_PIN_13
|
||||
#define LD3_GPIO_Port GPIOD
|
||||
#define LD5_Pin GPIO_PIN_14
|
||||
#define LD5_GPIO_Port GPIOD
|
||||
#define LD6_Pin GPIO_PIN_15
|
||||
#define LD6_GPIO_Port GPIOD
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
void stm32f4_peripherals_gpio_init(void) {
|
||||
//Enable all GPIO for now
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOD, LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pins : LD4_Pin LD3_Pin LD5_Pin LD6_Pin */
|
||||
GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
//Status LED chain
|
||||
HAL_GPIO_WritePin(GPIOD, LD4_Pin, GPIO_PIN_RESET); //LED 1
|
||||
HAL_GPIO_WritePin(GPIOD, LD3_Pin, GPIO_PIN_SET); //LED 2
|
||||
HAL_GPIO_WritePin(GPIOD, LD5_Pin, GPIO_PIN_SET); //LED 3
|
||||
HAL_GPIO_WritePin(GPIOD, LD6_Pin, GPIO_PIN_SET); //LED 4
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,9 +24,10 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nrfx.h"
|
||||
#include "nrfx_timer.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "stm32f4/pins.h"
|
||||
|
||||
void timers_reset(void);
|
||||
nrfx_timer_t* nrf_peripherals_allocate_timer(void);
|
||||
void nrf_peripherals_free_timer(nrfx_timer_t* timer);
|
||||
|
||||
//TODO
|
||||
//const mcu_pin_obj_t pin_PE02 = PIN(4, GPIOE, 2);
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,13 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGOUT_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGOUT_H
|
||||
#ifndef MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411RE_PINS_H
|
||||
#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411RE_PINS_H
|
||||
|
||||
#include "py/obj.h"
|
||||
//TODO
|
||||
//Pins in datasheet order: DocID028087 Rev 7 page 50. LQFP100 only
|
||||
//pg 50
|
||||
//extern const mcu_pin_obj_t pin_PE02;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} analogio_analogout_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ANALOGIO_ANALOGOUT_H
|
||||
#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411RE_PINS_H
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// #include "nrfx.h"
|
||||
// #include "nrf_nvmc.h"
|
||||
|
||||
void nrf_peripherals_power_init(void) {
|
||||
// Set GPIO reference voltage to 3.3V if it isn't already. REGOUT0 will get reset to 0xfffffff
|
||||
// if flash is erased, which sets the default to 1.8V
|
||||
// This matters only when "high voltage mode" is enabled, which is true on the PCA10059,
|
||||
// and might be true on other boards.
|
||||
// if (NRF_UICR->REGOUT0 == 0xffffffff) {
|
||||
// nrf_nvmc_write_word((uint32_t) &NRF_UICR->REGOUT0, UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);
|
||||
// // Must reset to make enable change.
|
||||
// NVIC_SystemReset();
|
||||
// }
|
||||
}
|
75
ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c
Normal file
75
ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
void stm32f4_peripherals_clocks_init(void) {
|
||||
//System clock init
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
/** Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 72;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 3;
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
/** Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
|
||||
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1|RCC_PERIPHCLK_SDIO
|
||||
|RCC_PERIPHCLK_CLK48;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SN = 50;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SM = 4;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
|
||||
PeriphClkInitStruct.PLLI2S.PLLI2SQ = 2;
|
||||
PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLQ;
|
||||
PeriphClkInitStruct.SdioClockSelection = RCC_SDIOCLKSOURCE_CLK48;
|
||||
PeriphClkInitStruct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
|
||||
PeriphClkInitStruct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
|
||||
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1);
|
||||
}
|
218
ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c
Normal file
218
ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* GPIO PIN REFERENCE
|
||||
#define LED3_Pin GPIO_PIN_2
|
||||
#define LED3_GPIO_Port GPIOE
|
||||
#define LED4_Pin GPIO_PIN_3
|
||||
#define LED4_GPIO_Port GPIOE
|
||||
#define DFSDM_DATIN3_Pin GPIO_PIN_4
|
||||
#define DFSDM_DATIN3_GPIO_Port GPIOE
|
||||
#define A0_Pin GPIO_PIN_0
|
||||
#define A0_GPIO_Port GPIOF
|
||||
#define LCD_BLCTRL_Pin GPIO_PIN_5
|
||||
#define LCD_BLCTRL_GPIO_Port GPIOF
|
||||
#define QSPI_BK1_IO3_Pin GPIO_PIN_6
|
||||
#define QSPI_BK1_IO3_GPIO_Port GPIOF
|
||||
#define QSPI_BK1_IO2_Pin GPIO_PIN_7
|
||||
#define QSPI_BK1_IO2_GPIO_Port GPIOF
|
||||
#define QSPI_BK1_IO0_Pin GPIO_PIN_8
|
||||
#define QSPI_BK1_IO0_GPIO_Port GPIOF
|
||||
#define QSPI_BK1_IO1_Pin GPIO_PIN_9
|
||||
#define QSPI_BK1_IO1_GPIO_Port GPIOF
|
||||
#define STLK_MCO_Pin GPIO_PIN_0
|
||||
#define STLK_MCO_GPIO_Port GPIOH
|
||||
#define DFSDM_CKOUT_Pin GPIO_PIN_2
|
||||
#define DFSDM_CKOUT_GPIO_Port GPIOC
|
||||
#define JOY_SEL_Pin GPIO_PIN_0
|
||||
#define JOY_SEL_GPIO_Port GPIOA
|
||||
#define STLINK_RX_Pin GPIO_PIN_2
|
||||
#define STLINK_RX_GPIO_Port GPIOA
|
||||
#define STLINK_TX_Pin GPIO_PIN_3
|
||||
#define STLINK_TX_GPIO_Port GPIOA
|
||||
#define CODEC_I2S3_WS_Pin GPIO_PIN_4
|
||||
#define CODEC_I2S3_WS_GPIO_Port GPIOA
|
||||
#define DFSDM_DATIN0_Pin GPIO_PIN_1
|
||||
#define DFSDM_DATIN0_GPIO_Port GPIOB
|
||||
#define QSPI_CLK_Pin GPIO_PIN_2
|
||||
#define QSPI_CLK_GPIO_Port GPIOB
|
||||
#define EXT_RESET_Pin GPIO_PIN_11
|
||||
#define EXT_RESET_GPIO_Port GPIOF
|
||||
#define CTP_RST_Pin GPIO_PIN_12
|
||||
#define CTP_RST_GPIO_Port GPIOF
|
||||
#define JOY_RIGHT_Pin GPIO_PIN_14
|
||||
#define JOY_RIGHT_GPIO_Port GPIOF
|
||||
#define JOY_LEFT_Pin GPIO_PIN_15
|
||||
#define JOY_LEFT_GPIO_Port GPIOF
|
||||
#define JOY_UP_Pin GPIO_PIN_0
|
||||
#define JOY_UP_GPIO_Port GPIOG
|
||||
#define JOY_DOWN_Pin GPIO_PIN_1
|
||||
#define JOY_DOWN_GPIO_Port GPIOG
|
||||
#define D4_Pin GPIO_PIN_7
|
||||
#define D4_GPIO_Port GPIOE
|
||||
#define D5_Pin GPIO_PIN_8
|
||||
#define D5_GPIO_Port GPIOE
|
||||
#define D6_Pin GPIO_PIN_9
|
||||
#define D6_GPIO_Port GPIOE
|
||||
#define D7_Pin GPIO_PIN_10
|
||||
#define D7_GPIO_Port GPIOE
|
||||
#define D8_Pin GPIO_PIN_11
|
||||
#define D8_GPIO_Port GPIOE
|
||||
#define D9_Pin GPIO_PIN_12
|
||||
#define D9_GPIO_Port GPIOE
|
||||
#define D10_Pin GPIO_PIN_13
|
||||
#define D10_GPIO_Port GPIOE
|
||||
#define D11_Pin GPIO_PIN_14
|
||||
#define D11_GPIO_Port GPIOE
|
||||
#define D12_Pin GPIO_PIN_15
|
||||
#define D12_GPIO_Port GPIOE
|
||||
#define I2C2_SCL_Pin GPIO_PIN_10
|
||||
#define I2C2_SCL_GPIO_Port GPIOB
|
||||
#define M2_CKIN_Pin GPIO_PIN_11
|
||||
#define M2_CKIN_GPIO_Port GPIOB
|
||||
#define CODEC_I2S3_SCK_Pin GPIO_PIN_12
|
||||
#define CODEC_I2S3_SCK_GPIO_Port GPIOB
|
||||
#define D13_Pin GPIO_PIN_8
|
||||
#define D13_GPIO_Port GPIOD
|
||||
#define D14_Pin GPIO_PIN_9
|
||||
#define D14_GPIO_Port GPIOD
|
||||
#define D15_Pin GPIO_PIN_10
|
||||
#define D15_GPIO_Port GPIOD
|
||||
#define LCD_RESET_Pin GPIO_PIN_11
|
||||
#define LCD_RESET_GPIO_Port GPIOD
|
||||
#define D0_Pin GPIO_PIN_14
|
||||
#define D0_GPIO_Port GPIOD
|
||||
#define D1_Pin GPIO_PIN_15
|
||||
#define D1_GPIO_Port GPIOD
|
||||
#define CODEC_INT_Pin GPIO_PIN_2
|
||||
#define CODEC_INT_GPIO_Port GPIOG
|
||||
#define LCD_TE_Pin GPIO_PIN_4
|
||||
#define LCD_TE_GPIO_Port GPIOG
|
||||
#define CTP_INT_Pin GPIO_PIN_5
|
||||
#define CTP_INT_GPIO_Port GPIOG
|
||||
#define QSPI_BK1_NCS_Pin GPIO_PIN_6
|
||||
#define QSPI_BK1_NCS_GPIO_Port GPIOG
|
||||
#define USB_OTGFS_OVRCR_Pin GPIO_PIN_7
|
||||
#define USB_OTGFS_OVRCR_GPIO_Port GPIOG
|
||||
#define USB_OTGFS_PPWR_EN_Pin GPIO_PIN_8
|
||||
#define USB_OTGFS_PPWR_EN_GPIO_Port GPIOG
|
||||
#define CODEC_I2S3_MCK_Pin GPIO_PIN_7
|
||||
#define CODEC_I2S3_MCK_GPIO_Port GPIOC
|
||||
#define uSD_D0_Pin GPIO_PIN_8
|
||||
#define uSD_D0_GPIO_Port GPIOC
|
||||
#define uSD_D1_Pin GPIO_PIN_9
|
||||
#define uSD_D1_GPIO_Port GPIOC
|
||||
#define M2_CKINA8_Pin GPIO_PIN_8
|
||||
#define M2_CKINA8_GPIO_Port GPIOA
|
||||
#define USB_OTGFS_VBUS_Pin GPIO_PIN_9
|
||||
#define USB_OTGFS_VBUS_GPIO_Port GPIOA
|
||||
#define USB_OTGFS_ID_Pin GPIO_PIN_10
|
||||
#define USB_OTGFS_ID_GPIO_Port GPIOA
|
||||
#define USB_OTGFS_DM_Pin GPIO_PIN_11
|
||||
#define USB_OTGFS_DM_GPIO_Port GPIOA
|
||||
#define USB_OTGFS_DP_Pin GPIO_PIN_12
|
||||
#define USB_OTGFS_DP_GPIO_Port GPIOA
|
||||
#define SWDIO_Pin GPIO_PIN_13
|
||||
#define SWDIO_GPIO_Port GPIOA
|
||||
#define SWCLK_Pin GPIO_PIN_14
|
||||
#define SWCLK_GPIO_Port GPIOA
|
||||
#define uSD_D2_Pin GPIO_PIN_10
|
||||
#define uSD_D2_GPIO_Port GPIOC
|
||||
#define uSD_D3_Pin GPIO_PIN_11
|
||||
#define uSD_D3_GPIO_Port GPIOC
|
||||
#define uSD_CLK_Pin GPIO_PIN_12
|
||||
#define uSD_CLK_GPIO_Port GPIOC
|
||||
#define D2_Pin GPIO_PIN_0
|
||||
#define D2_GPIO_Port GPIOD
|
||||
#define D3_Pin GPIO_PIN_1
|
||||
#define D3_GPIO_Port GPIOD
|
||||
#define uSD_CMD_Pin GPIO_PIN_2
|
||||
#define uSD_CMD_GPIO_Port GPIOD
|
||||
#define uSD_DETECT_Pin GPIO_PIN_3
|
||||
#define uSD_DETECT_GPIO_Port GPIOD
|
||||
#define FMC_NOE_Pin GPIO_PIN_4
|
||||
#define FMC_NOE_GPIO_Port GPIOD
|
||||
#define FMC_NWE_Pin GPIO_PIN_5
|
||||
#define FMC_NWE_GPIO_Port GPIOD
|
||||
#define FMC_NE1_Pin GPIO_PIN_7
|
||||
#define FMC_NE1_GPIO_Port GPIOD
|
||||
#define SWO_Pin GPIO_PIN_3
|
||||
#define SWO_GPIO_Port GPIOB
|
||||
#define CODEC_I2S3ext_SD_Pin GPIO_PIN_4
|
||||
#define CODEC_I2S3ext_SD_GPIO_Port GPIOB
|
||||
#define CODEC_I2S3_SD_Pin GPIO_PIN_5
|
||||
#define CODEC_I2S3_SD_GPIO_Port GPIOB
|
||||
#define I2C1_SCL_Pin GPIO_PIN_6
|
||||
#define I2C1_SCL_GPIO_Port GPIOB
|
||||
#define I2C1_SDA_Pin GPIO_PIN_7
|
||||
#define I2C1_SDA_GPIO_Port GPIOB
|
||||
#define I2C2_SDA_Pin GPIO_PIN_9
|
||||
#define I2C2_SDA_GPIO_Port GPIOB
|
||||
#define LED1_Pin GPIO_PIN_0
|
||||
#define LED1_GPIO_Port GPIOE
|
||||
#define LED2_Pin GPIO_PIN_1
|
||||
#define LED2_GPIO_Port GPIOE
|
||||
*/
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
void stm32f4_peripherals_gpio_init(void) {
|
||||
//Enable all GPIO for now
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
|
||||
//HAL_GPIO_WritePin(USB_OTGFS_PPWR_EN_GPIO_Port, USB_OTGFS_PPWR_EN_Pin, GPIO_PIN_SET);
|
||||
|
||||
//Configure LED pins
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
|
||||
|
||||
//Status LED chain
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_RESET); //LED 1
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET); //LED 2
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET); //LED 3
|
||||
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); //LED 4
|
||||
|
||||
//TBD, USB power
|
||||
// GPIO_InitStruct.Pin = USB_OTGFS_PPWR_EN_Pin;
|
||||
// GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
||||
// GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
// HAL_GPIO_Init(USB_OTGFS_PPWR_EN_GPIO_Port, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by Dan Halbert for Adafruit Industries
|
||||
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/pulseio/PulseOut.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nrfx.h"
|
||||
#include "nrfx_timer.h"
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
STATIC nrfx_timer_t nrfx_timers[] = {
|
||||
#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
|
||||
// Note that TIMER0 is reserved for use by the SoftDevice, so it should not usually be enabled.
|
||||
NRFX_TIMER_INSTANCE(0),
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
|
||||
NRFX_TIMER_INSTANCE(1),
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER2_ENABLED)
|
||||
NRFX_TIMER_INSTANCE(2),
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER3_ENABLED)
|
||||
NRFX_TIMER_INSTANCE(3),
|
||||
#endif
|
||||
#if NRFX_CHECK(NRFX_TIMER4_ENABLED)
|
||||
NRFX_TIMER_INSTANCE(4),
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool nrfx_timer_allocated[ARRAY_SIZE(nrfx_timers)];
|
||||
|
||||
void timers_reset(void) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) {
|
||||
nrfx_timer_uninit(&nrfx_timers[i]);
|
||||
nrfx_timer_allocated[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a free nrfx_timer instance, and marks it as allocated.
|
||||
// The caller should init as with the desired config.
|
||||
// Returns NULL if no timer is available.
|
||||
nrfx_timer_t* nrf_peripherals_allocate_timer(void) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) {
|
||||
if (!nrfx_timer_allocated[i]) {
|
||||
nrfx_timer_allocated[i] = true;
|
||||
return &nrfx_timers[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Free a timer, which may or may not have been initialized.
|
||||
void nrf_peripherals_free_timer(nrfx_timer_t* timer) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) {
|
||||
if (timer == &nrfx_timers[i]) {
|
||||
nrfx_timer_allocated[i] = false;
|
||||
// Safe to call even if not initialized.
|
||||
nrfx_timer_uninit(timer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 89a356f0b44883d55c45a5d22940777a44a2b881
|
||||
Subproject commit 12411ade32aeec4e49c969d8d095463b0c2fb1f0
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user