summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Townsend <microbuilder@users.noreply.github.com>2018-02-07 22:17:05 +0100
committerGitHub <noreply@github.com>2018-02-07 22:17:05 +0100
commit9d191f7f9f386bb62f32b3aa9c6534dc84f9a48a (patch)
treec73d6c26bf43f6442c0f32e3925df7941055364c
parent77c70c7e5061e5d82113ae514c0ae8e1fc005c2a (diff)
parent1de2ee68841652d4cfb586978956721c505a1882 (diff)
Merge pull request #589 from arturo182/nrf_gamepad
nrf: Implement ticks, add gamepad module and example
-rw-r--r--ports/nrf/Makefile13
-rw-r--r--ports/nrf/boards/board.h2
-rw-r--r--ports/nrf/boards/feather52/board.c42
-rw-r--r--ports/nrf/boards/pca10056/board.c43
-rw-r--r--ports/nrf/boards/pca10056/examples/buttons.py26
-rw-r--r--ports/nrf/common-hal/time/__init__.c2
-rw-r--r--ports/nrf/mpconfigport.h5
-rw-r--r--ports/nrf/supervisor/port.c8
-rw-r--r--ports/nrf/tick.c81
-rw-r--r--ports/nrf/tick.h46
-rw-r--r--shared-bindings/index.rst2
11 files changed, 176 insertions, 94 deletions
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 563578d10..9049bdb64 100644
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -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))
diff --git a/ports/nrf/boards/board.h b/ports/nrf/boards/board.h
index fecc0fb57..ec98f04fb 100644
--- a/ports/nrf/boards/board.h
+++ b/ports/nrf/boards/board.h
@@ -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);
diff --git a/ports/nrf/boards/feather52/board.c b/ports/nrf/boards/feather52/board.c
index c550e9061..c0f344597 100644
--- a/ports/nrf/boards/feather52/board.c
+++ b/ports/nrf/boards/feather52/board.c
@@ -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
diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c
index 8ca87759b..5ad81c21d 100644
--- a/ports/nrf/boards/pca10056/board.c
+++ b/ports/nrf/boards/pca10056/board.c
@@ -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) {
diff --git a/ports/nrf/boards/pca10056/examples/buttons.py b/ports/nrf/boards/pca10056/examples/buttons.py
new file mode 100644
index 000000000..9f4a7cfd4
--- /dev/null
+++ b/ports/nrf/boards/pca10056/examples/buttons.py
@@ -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)
diff --git a/ports/nrf/common-hal/time/__init__.c b/ports/nrf/common-hal/time/__init__.c
index dc29e2d6d..ec77354a9 100644
--- a/ports/nrf/common-hal/time/__init__.c
+++ b/ports/nrf/common-hal/time/__init__.c
@@ -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;
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index a02ebd3f1..63fe5e3b4 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -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) }, \
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index 4ac9c08e0..c72ed7cc3 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -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();
}
diff --git a/ports/nrf/tick.c b/ports/nrf/tick.c
new file mode 100644
index 000000000..fccc8181d
--- /dev/null
+++ b/ports/nrf/tick.c
@@ -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) {}
+}
diff --git a/ports/nrf/tick.h b/ports/nrf/tick.h
new file mode 100644
index 000000000..73f17d703
--- /dev/null
+++ b/ports/nrf/tick.h
@@ -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
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index d1261dcd2..1813d5699 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -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**