aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@mit.edu>2010-11-30 21:31:17 -0500
committerMarti Bolivar <mbolivar@mit.edu>2010-11-30 21:31:17 -0500
commit4d424d98b63df873ff373a66aeee27a75ae63f1d (patch)
treee26d75bb6429952325a44cf3013483a59102124a
parent3a9a119e9a8ce72c0e1b8fa4d3904bdf84ce355c (diff)
downloadlibrambutan-4d424d98b63df873ff373a66aeee27a75ae63f1d.tar.gz
librambutan-4d424d98b63df873ff373a66aeee27a75ae63f1d.zip
maple mini prototype seems to be working
-rw-r--r--libmaple/gpio.h26
-rw-r--r--wirish/boards.h30
-rw-r--r--wirish/io.h58
-rw-r--r--wirish/wirish.c3
-rw-r--r--wirish/wirish_digital.c32
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;
+}