Merge pull request #589 from arturo182/nrf_gamepad

nrf: Implement ticks, add gamepad module and example
This commit is contained in:
Kevin Townsend 2018-02-07 22:17:05 +01:00 committed by GitHub
commit 9d191f7f9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 176 additions and 94 deletions

View File

@ -139,6 +139,7 @@ SRC_C += \
pin_named_pins.c \
fatfs_port.c \
fifo.c \
tick.c \
drivers/softpwm.c \
drivers/ticker.c \
drivers/bluetooth/ble_drv.c \
@ -230,22 +231,24 @@ SRC_SHARED_MODULE = \
os/__init__.c \
random/__init__.c \
storage/__init__.c \
gamepad/__init__.c \
gamepad/GamePad.c
# bitbangio/__init__.c \
bitbangio/I2C.c \
bitbangio/OneWire.c \
bitbangio/SPI.c \
busio/OneWire.c \
gamepad/__init__.c \
gamepad/GamePad.c \
struct/__init__.c \
uheap/__init__.c \
ustack/__init__.c
#SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
SRC_SHARED_BINDINGS = \
gamepad/__init__.c \
gamepad/GamePad.c
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-module/, $(SRC_SHARED_MODULE))
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_BINDINGS)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))

View File

@ -31,8 +31,6 @@
#include <stdbool.h>
extern volatile uint32_t ticks_ms;
// Initializes board related state once on start up.
void board_init(void);

View File

@ -35,52 +35,10 @@
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
uint32_t bootloaderVersion = 0;
volatile uint32_t ticks_ms = 0;
#define HAL_LFCLK_FREQ (32768UL)
#define HAL_RTC_FREQ (1024UL)
#define HAL_RTC_COUNTER_PRESCALER ((HAL_LFCLK_FREQ/HAL_RTC_FREQ)-1)
/* Maximum RTC ticks */
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
void board_init(void)
{
// Retrieve bootloader version
bootloaderVersion = BOOTLOADER_VERSION_REGISTER;
// 32Khz XTAL
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
// Set up RTC1 as tick timer
NVIC_DisableIRQ(RTC1_IRQn);
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
NRF_RTC1->TASKS_STOP = 1;
NRF_RTC1->TASKS_CLEAR = 1;
ticks_ms = 0;
NRF_RTC1->PRESCALER = HAL_RTC_COUNTER_PRESCALER;
NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk;
NRF_RTC1->TASKS_START = 1;
NRF_RTC1->EVTENSET = RTC_EVTEN_OVRFLW_Msk;
NVIC_SetPriority(RTC1_IRQn, 0xf); // lowest priority
NVIC_EnableIRQ(RTC1_IRQn);
}
void RTC1_IRQHandler(void)
{
// Clear event
NRF_RTC1->EVENTS_TICK = 0;
volatile uint32_t dummy = NRF_RTC1->EVENTS_TICK;
(void) dummy;
// Tick correction
uint32_t systick_counter = NRF_RTC1->COUNTER;
uint32_t diff = (systick_counter - ticks_ms) & portNRF_RTC_MAXTICKS;
ticks_ms += diff;
}
// Check the status of the two buttons on CircuitPlayground Express. If both are

View File

@ -31,49 +31,8 @@
#include "boards/board.h"
volatile uint32_t ticks_ms = 0;
void board_init(void) {
#define HAL_LFCLK_FREQ (32768UL)
#define HAL_RTC_FREQ (1024UL)
#define HAL_RTC_COUNTER_PRESCALER ((HAL_LFCLK_FREQ/HAL_RTC_FREQ)-1)
/* Maximum RTC ticks */
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
void board_init(void)
{
// 32Khz XTAL
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
// Set up RTC1 as tick timer
NVIC_DisableIRQ(RTC1_IRQn);
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
NRF_RTC1->TASKS_STOP = 1;
NRF_RTC1->TASKS_CLEAR = 1;
ticks_ms = 0;
NRF_RTC1->PRESCALER = HAL_RTC_COUNTER_PRESCALER;
NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk;
NRF_RTC1->TASKS_START = 1;
NRF_RTC1->EVTENSET = RTC_EVTEN_OVRFLW_Msk;
NVIC_SetPriority(RTC1_IRQn, 0xf); // lowest priority
NVIC_EnableIRQ(RTC1_IRQn);
}
void RTC1_IRQHandler(void)
{
// Clear event
NRF_RTC1->EVENTS_TICK = 0;
volatile uint32_t dummy = NRF_RTC1->EVENTS_TICK;
(void) dummy;
//
//// Tick correction
uint32_t systick_counter = NRF_RTC1->COUNTER;
uint32_t diff = (systick_counter - ticks_ms) & portNRF_RTC_MAXTICKS;
ticks_ms += diff;
}
bool board_requests_safe_mode(void) {

View File

@ -0,0 +1,26 @@
import board
import digitalio
import gamepad
import time
pad = gamepad.GamePad(
digitalio.DigitalInOut(board.PA11),
digitalio.DigitalInOut(board.PA12),
digitalio.DigitalInOut(board.PA24),
digitalio.DigitalInOut(board.PA25),
)
prev_buttons = 0
while True:
buttons = pad.get_pressed()
if buttons != prev_buttons:
for i in range(0, 4):
bit = (1 << i)
if (buttons & bit) != (prev_buttons & bit):
print('Button %d %s' % (i + 1, 'pressed' if buttons & bit else 'released'))
prev_buttons = buttons
time.sleep(0.1)

View File

@ -27,7 +27,7 @@
#include "py/mphal.h"
#include "shared-bindings/time/__init__.h"
#include "boards/board.h"
#include "tick.h"
inline uint64_t common_hal_time_monotonic() {
return ticks_ms;

View File

@ -181,6 +181,9 @@
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
// Scan gamepad every 32ms
#define CIRCUITPY_GAMEPAD_TICKS 0x1f
// if sdk is in use, import configuration
#if BLUETOOTH_SD
#include "bluetooth_conf.h"
@ -223,6 +226,7 @@ extern const struct _mp_obj_module_t random_module;
extern const struct _mp_obj_module_t storage_module;
extern const struct _mp_obj_module_t time_module;
extern const struct _mp_obj_module_t supervisor_module;
extern const struct _mp_obj_module_t gamepad_module;
extern const struct _mp_obj_module_t pyb_module;
extern const struct _mp_obj_module_t machine_module;
@ -269,6 +273,7 @@ extern const struct _mp_obj_module_t ble_module;
{ MP_OBJ_NEW_QSTR (MP_QSTR_random ), (mp_obj_t)&random_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_storage ), (mp_obj_t)&storage_module },\
{ MP_OBJ_NEW_QSTR (MP_QSTR_supervisor ), (mp_obj_t)&supervisor_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_gamepad ), (mp_obj_t)&gamepad_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \
{ MP_ROM_QSTR (MP_QSTR_pyb ), MP_ROM_PTR(&pyb_module) }, \
{ MP_ROM_QSTR (MP_QSTR_utime ), MP_ROM_PTR(&mp_module_utime) }, \

View File

@ -28,16 +28,18 @@
#include "supervisor/port.h"
#include "boards/board.h"
#include "shared-module/gamepad/__init__.h"
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/pulseio/PWMOut.h"
#include "tick.h"
safe_mode_t port_init(void) {
board_init();
#if 0
// Configure millisecond timer initialization.
tick_init();
#if 0
#ifdef CIRCUITPY_CANARY_WORD
// Run in safe mode if the canary is corrupt.
if (_ezero != CIRCUITPY_CANARY_WORD) {
@ -54,6 +56,10 @@ safe_mode_t port_init(void) {
}
void reset_port(void) {
#ifdef CIRCUITPY_GAMEPAD_TICKS
gamepad_reset();
#endif
pwmout_reset();
reset_all_pins();
}

81
ports/nrf/tick.c Normal file
View File

@ -0,0 +1,81 @@
/*
* 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 "tick.h"
#include "supervisor/shared/autoreload.h"
#include "shared-module/gamepad/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "nrf.h"
// Global millisecond tick count
volatile uint64_t ticks_ms = 0;
void SysTick_Handler(void) {
// SysTick interrupt handler called when the SysTick timer reaches zero
// (every millisecond).
ticks_ms += 1;
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
gamepad_tick();
}
#endif
}
void tick_init() {
uint32_t ticks_per_ms = common_hal_mcu_processor_get_frequency() / 1000;
SysTick_Config(ticks_per_ms);
// NVIC_EnableIRQ(SysTick_IRQn);
}
void tick_delay(uint32_t us) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
uint64_t start_ms = ticks_ms;
while (us > 1000) {
while (ticks_ms == start_ms) {}
us -= us_between_ticks;
start_ms = ticks_ms;
us_between_ticks = 1000;
}
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
}
// us counts down!
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
*ms = ticks_ms;
*us_until_ms = SysTick->VAL / ticks_per_us;
}
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}

46
ports/nrf/tick.h Normal file
View File

@ -0,0 +1,46 @@
/*
* 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_TICK_H
#define MICROPY_INCLUDED_NRF_TICK_H
#include "mpconfigport.h"
#include <stdint.h>
extern volatile uint64_t ticks_ms;
extern struct timer_descriptor ms_timer;
void tick_init(void);
void tick_delay(uint32_t us);
void current_tick(uint64_t* ms, uint32_t* us_until_ms);
// Do not call this with interrupts disabled because it may be waiting for
// ticks_ms to increment.
void wait_until(uint64_t ms, uint32_t us_until_ms);
#endif // MICROPY_INCLUDED_NRF_TICK_H

View File

@ -27,7 +27,7 @@ Module Supported Ports
`board` **All Supported**
`busio` **All Supported**
`digitalio` **All Supported**
`gamepad` **SAMD Express**
`gamepad` **SAMD Express, nRF**
`math` **All Supported**
`microcontroller` **All Supported**
`multiterminal` **ESP8266**