Merge pull request #589 from arturo182/nrf_gamepad
nrf: Implement ticks, add gamepad module and example
This commit is contained in:
commit
9d191f7f9f
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
|
@ -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;
|
||||
|
|
|
@ -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) }, \
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
}
|
|
@ -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
|
|
@ -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**
|
||||
|
|
Loading…
Reference in New Issue