diff options
-rw-r--r-- | libmaple/gpio.h | 26 | ||||
-rw-r--r-- | wirish/boards.h | 30 | ||||
-rw-r--r-- | wirish/io.h | 58 | ||||
-rw-r--r-- | wirish/wirish.c | 3 | ||||
-rw-r--r-- | wirish/wirish_digital.c | 32 |
5 files changed, 133 insertions, 16 deletions
diff --git a/libmaple/gpio.h b/libmaple/gpio.h index 49360ee..53f77c4 100644 --- a/libmaple/gpio.h +++ b/libmaple/gpio.h @@ -42,15 +42,18 @@ * Alternate function open-drain * * - After reset, the alternate functions are not active and IO prts - * are set to Input Floating mode */ + * are set to Input Floating mode, EXCEPT for the Serial Wire and JTAG + * ports, which are in alternate function mode by default. */ -#define GPIOA_BASE (GPIO_Port*)0x40010800 -#define GPIOB_BASE (GPIO_Port*)0x40010C00 -#define GPIOC_BASE (GPIO_Port*)0x40011000 -#define GPIOD_BASE (GPIO_Port*)0x40011400 -#define GPIOE_BASE (GPIO_Port*)0x40011800 // High-density devices only -#define GPIOF_BASE (GPIO_Port*)0x40011C00 // High-density devices only -#define GPIOG_BASE (GPIO_Port*)0x40012000 // High-density devices only +#define AFIO_MAPR ((volatile uint32*)0x40010004) + +#define GPIOA_BASE ((GPIO_Port*)0x40010800) +#define GPIOB_BASE ((GPIO_Port*)0x40010C00) +#define GPIOC_BASE ((GPIO_Port*)0x40011000) +#define GPIOD_BASE ((GPIO_Port*)0x40011400) +#define GPIOE_BASE ((GPIO_Port*)0x40011800) // High-density devices only +#define GPIOF_BASE ((GPIO_Port*)0x40011C00) // High-density devices only +#define GPIOG_BASE ((GPIO_Port*)0x40012000) // High-density devices only #define GPIO_SPEED_50MHZ (0x3) @@ -109,6 +112,13 @@ static inline uint32 gpio_read_bit(GPIO_Port *port, uint8 gpio_pin) { return (port->IDR & BIT(gpio_pin) ? 1 : 0); } +/* For pins configured as output push-pull, reading the ODR returns + * the last value written in push-pull mode. + */ +static inline void gpio_toggle_pin(GPIO_Port *port, uint8 gpio_pin) { + port->ODR = port->ODR ^ BIT(gpio_pin); +} + #ifdef __cplusplus } // extern "C" #endif diff --git a/wirish/boards.h b/wirish/boards.h index 0625d0a..558e1c3 100644 --- a/wirish/boards.h +++ b/wirish/boards.h @@ -70,12 +70,15 @@ typedef struct PinMapping { uint32 timer_chan; } PinMapping; -/* LeafLabs Maple rev3, rev4 */ +/* LeafLabs Maple rev3, rev5 */ #ifdef BOARD_maple #define CYCLES_PER_MICROSECOND 72 #define MAPLE_RELOAD_VAL 71999 /* takes a cycle to reload */ + #define BOARD_BUTTON_PIN 38 + #define BOARD_LED_PIN 13 + static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = { /* D0/PA3 */ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4}, @@ -163,10 +166,12 @@ typedef struct PinMapping { {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID} }; -#endif + #define BOARD_INIT do { \ + } while(0) -/* LeafLabs Maple Native (prototype) */ -#ifdef BOARD_maple_native +#elif defined(BOARD_maple_native) + + /* LeafLabs Maple Native (prototype) */ #define CYCLES_PER_MICROSECOND 72 #define MAPLE_RELOAD_VAL 71999 /* takes a cycle to reload */ @@ -290,13 +295,15 @@ typedef struct PinMapping { /* D13/PA5 */ {EXTI5, EXTI_CONFIG_PORTA}, }; -#endif -#ifdef BOARD_maple_mini +#elif defined(BOARD_maple_mini) #define CYCLES_PER_MICROSECOND 72 #define MAPLE_RELOAD_VAL 71999 /* takes a cycle to reload */ + #define BOARD_BUTTON_PIN 32 + #define BOARD_LED_PIN 33 + static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = { /* D0/PC15 */ {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}, @@ -368,11 +375,18 @@ typedef struct PinMapping { {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID}, }; + /* since we want the Serial Wire/JTAG pins as GPIOs, disable both + SW and JTAG debug support */ + /* don't use __clear_bits here! */ + #define BOARD_INIT \ + do { \ + *AFIO_MAPR = (*AFIO_MAPR | BIT(26)) & ~(BIT(25) | BIT(24)); \ + } while (0) -#endif +#else -#ifndef CYCLES_PER_MICROSECOND #error "Board type has not been selected correctly." + #endif #ifdef __cplusplus diff --git a/wirish/io.h b/wirish/io.h index f82e414..66ba74d 100644 --- a/wirish/io.h +++ b/wirish/io.h @@ -33,6 +33,7 @@ #include "gpio.h" #include "adc.h" +#include "time.h" #ifdef __cplusplus extern "C"{ @@ -158,6 +159,63 @@ uint32 digitalRead(uint8); */ uint32 analogRead(uint8 pin); +/** + * Toggles the digital value at the given pin. + * + * The pin must have its mode set to OUTPUT. + * + * @param pin the pin to toggle. If the pin is HIGH, set it LOW. If + * it is LOW, set it HIGH. + * + * @see pinMode() + */ +void togglePin(uint8 pin); + +/** + * Toggle the LED. + * + * If the LED is on, turn it off. If it is off, turn it on. + * + * The LED must its mode set to OUTPUT. This can be accomplished + * portably over all LeafLabs boards by calling pinMode(BOARD_LED_PIN, + * OUTPUT) before calling this function. + * + * @see pinMode() + */ +static inline void toggleLED() { + togglePin(BOARD_LED_PIN); +} + +/** + * If the button is currently pressed, waits until the button is no + * longer being pressed, and returns true. Otherwise, returns false. + * + * The button pin must have its mode set to INPUT. This can be + * accomplished portably over all LeafLabs boards by calling + * pinMode(BOARD_BUTTON_PIN, INPUT). + * + * @see pinMode() + */ +uint8 isButtonPressed(); + +/** + * Wait until the button is pressed and released, timing out if no + * press occurs. + * + * The button pin must have its mode set to INPUT. This can be + * accomplished portably over all LeafLabs boards by calling + * pinMode(BOARD_BUTTON_PIN, INPUT). + * + * @param timeout_millis Number of milliseconds to wait until the + * button is pressed. If timeout_millis is 0, wait forever. + * + * @return true, if the button was pressed; false, if the timeout was + * reached. + * + * @see pinMode() + */ +uint8 waitForButtonPress(uint32 timeout_millis); + #ifdef __cplusplus } // extern "C" #endif diff --git a/wirish/wirish.c b/wirish/wirish.c index 0abec41..3239838 100644 --- a/wirish/wirish.c +++ b/wirish/wirish.c @@ -74,4 +74,7 @@ void init(void) { timer_init(TIMER8, 1); #endif setupUSB(); + + /* include the board-specific init macro */ + BOARD_INIT; } diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.c index aa22196..cdd04bf 100644 --- a/wirish/wirish_digital.c +++ b/wirish/wirish_digital.c @@ -103,3 +103,35 @@ void digitalWrite(uint8 pin, uint8 val) { gpio_write_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin, val); } + +void togglePin(uint8 pin) { + gpio_toggle_pin(PIN_MAP[pin].port, PIN_MAP[pin].pin); +} + +uint8 isButtonPressed() { + if (digitalRead(BOARD_BUTTON_PIN)) { + while (digitalRead(BOARD_BUTTON_PIN)) + ; + return true; + } + return false; +} + +uint8 waitForButtonPress(uint32 timeout) { + uint32 start = millis(); + uint32 time; + if (timeout == 0) { + while (!isButtonPressed()) + ; + return true; + } + do { + time = millis(); + /* properly handle wrap-around */ + if ((start > time && time + (0xffffffffU - start) > timeout) || + time - start > timeout) { + return false; + } + } while (!isButtonPressed()); + return true; +} |