Requested changes, general cleanup

This commit is contained in:
Hierophect 2019-07-24 14:21:27 -04:00
parent 172ab190b5
commit a63df51893
107 changed files with 642 additions and 7187 deletions

3
.gitmodules vendored
View File

@ -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
View File

@ -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();
}

View File

@ -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 = \

View File

@ -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

View File

@ -1,217 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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****/

View 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>&copy; 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****/

View 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

View File

@ -1,217 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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****/

View 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>&copy; 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****/

View 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

View File

@ -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 */

View 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

View File

@ -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;
}

View File

@ -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

View File

@ -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) {
}

View File

@ -1 +0,0 @@
// No analogio module functions.

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -1 +0,0 @@
// No busio module functions.

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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(&current_ms, &current_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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -1 +0,0 @@
// No pulseio module functions.

View File

@ -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;
}

View File

@ -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

View File

@ -1 +0,0 @@
// No rotaryio module functions.

View File

@ -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"));
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -1 +0,0 @@
// No touchio module functions.

View File

@ -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

View File

@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
#ifndef __NRF52_HAL
#define __NRF52_HAL
#ifndef __STM32F4_HAL
#define __STM32F4_HAL
#include <stdbool.h>
#include <stdint.h>

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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__

View 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);
}

View 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
}

View File

@ -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);

View File

@ -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

View File

@ -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();
// }
}

View 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);
}

View 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);
}

View File

@ -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

View File

@ -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

View File

@ -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