aboutsummaryrefslogtreecommitdiffstats
path: root/wirish
diff options
context:
space:
mode:
Diffstat (limited to 'wirish')
-rw-r--r--wirish/HardwareTimer.cpp150
-rw-r--r--wirish/HardwareTimer.h176
-rw-r--r--wirish/boards.h131
-rw-r--r--wirish/comm/HardwareSerial.cpp11
-rw-r--r--wirish/comm/HardwareSerial.h6
-rw-r--r--wirish/ext_interrupts.h27
-rw-r--r--wirish/io.h58
-rw-r--r--wirish/pwm.c4
-rw-r--r--wirish/time.h6
-rw-r--r--wirish/wirish.c5
-rw-r--r--wirish/wirish_digital.c32
-rw-r--r--wirish/wirish_math.cpp5
-rw-r--r--wirish/wirish_math.h7
13 files changed, 431 insertions, 187 deletions
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
index 5b80ec1..92c6adf 100644
--- a/wirish/HardwareTimer.cpp
+++ b/wirish/HardwareTimer.cpp
@@ -29,13 +29,10 @@
#include "wirish.h"
#include "HardwareTimer.h"
-HardwareTimer::HardwareTimer(uint8 timerNum) {
- ASSERT(timerNum <= NR_TIMERS && timerNum != 6 && timerNum != 7);
+HardwareTimer::HardwareTimer(timer_dev_num timerNum) {
+ ASSERT(timerNum != TIMER_INVALID);
this->timerNum = timerNum;
-
- // Need to remember over flow for bounds checking
- this->overflow = 0xFFFF;
}
void HardwareTimer::resume(void) {
@@ -46,122 +43,158 @@ void HardwareTimer::pause(void) {
timer_pause(this->timerNum);
}
+uint16 HardwareTimer::getPrescaleFactor(void) {
+ return timer_get_prescaler(this->timerNum) + 1;
+}
+
void HardwareTimer::setPrescaleFactor(uint16 factor) {
// The prescaler register is zero-indexed
timer_set_prescaler(this->timerNum, factor-1);
}
-void HardwareTimer::setOverflow(uint16 val) {
- this->overflow = val;
- timer_set_reload(this->timerNum, val);
+uint16 HardwareTimer::getOverflow() {
+ return timer_get_reload(this->timerNum);
}
-void HardwareTimer::setCount(uint16 val) {
- if(val > this->overflow) {
- val = this->overflow;
- }
- timer_set_count(this->timerNum, val);
+void HardwareTimer::setOverflow(uint16 val) {
+ timer_set_reload(this->timerNum, val);
}
uint16 HardwareTimer::getCount(void) {
return timer_get_count(this->timerNum);
}
-uint16 HardwareTimer::setPeriod(uint32 microseconds) {
- // XXX: 72MHz shouldn't be hard coded in here... global define?
+void HardwareTimer::setCount(uint16 val) {
+ uint16 ovf = this->getOverflow();
+ timer_set_count(this->timerNum, min(val, ovf));
+}
+uint16 HardwareTimer::setPeriod(uint32 microseconds) {
// Not the best way to handle this edge case?
if(!microseconds) {
setPrescaleFactor(1);
setOverflow(1);
- return this->overflow;
+ return this->getOverflow();
}
+ uint32 cycles = microseconds * CYCLES_PER_MICROSECOND;
- // With a prescale factor of 1, there are 72counts/ms
- uint16 ps = ((microseconds*72)/65536) + 1;
+ // With a prescale factor of 1, there are CYCLES_PER_MICROSECOND
+ // counts/ms
+ uint16 ps = (uint16)((cycles >> 16) + 1);
setPrescaleFactor(ps);
// Finally, this overflow will always be less than 65536
- setOverflow(((microseconds*72)/ps) - 1);
- return this->overflow;
+ setOverflow((cycles/ps) - 1);
+
+ return this->getOverflow();
+}
+
+inline void HardwareTimer::setChannelMode(int channel, TimerMode mode) {
+ timer_set_mode(this->timerNum, channel, mode);
}
void HardwareTimer::setChannel1Mode(TimerMode mode) {
- timer_set_mode(this->timerNum,1,mode);
+ this->setChannelMode(1, mode);
}
void HardwareTimer::setChannel2Mode(TimerMode mode) {
- timer_set_mode(this->timerNum,2,mode);
+ this->setChannelMode(2, mode);
}
void HardwareTimer::setChannel3Mode(TimerMode mode) {
- timer_set_mode(this->timerNum,3,mode);
+ this->setChannelMode(3, mode);
}
void HardwareTimer::setChannel4Mode(TimerMode mode) {
- timer_set_mode(this->timerNum,4,mode);
+ this->setChannelMode(4, mode);
+}
+
+inline uint16 HardwareTimer::getCompare(int channel) {
+ return timer_get_compare_value(this->timerNum, channel);
+}
+
+uint16 HardwareTimer::getCompare1() {
+ return this->getCompare(1);
+}
+
+uint16 HardwareTimer::getCompare2() {
+ return this->getCompare(2);
+}
+
+uint16 HardwareTimer::getCompare3() {
+ return this->getCompare(3);
+}
+
+uint16 HardwareTimer::getCompare4() {
+ return this->getCompare(4);
+}
+
+inline void HardwareTimer::setCompare(int channel, uint16 val) {
+ uint16 ovf = this->getOverflow();
+ timer_set_compare_value(this->timerNum, channel, min(val, ovf));
}
void HardwareTimer::setCompare1(uint16 val) {
- if(val > this->overflow) {
- val = this->overflow;
- }
- timer_set_compare_value(this->timerNum,1,val);
+ this->setCompare(1, val);
}
void HardwareTimer::setCompare2(uint16 val) {
- if(val > this->overflow) {
- val = this->overflow;
- }
- timer_set_compare_value(this->timerNum,2,val);
+ this->setCompare(2, val);
}
void HardwareTimer::setCompare3(uint16 val) {
- if(val > this->overflow) {
- val = this->overflow;
- }
- timer_set_compare_value(this->timerNum,3,val);
+ this->setCompare(3, val);
}
void HardwareTimer::setCompare4(uint16 val) {
- if(val > this->overflow) {
- val = this->overflow;
- }
- timer_set_compare_value(this->timerNum,4,val);
+ this->setCompare(4, val);
+}
+
+inline void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum, channel, handler);
}
void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,1,handler);
+ this->attachInterrupt(1, handler);
}
void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,2,handler);
+ this->attachInterrupt(2, handler);
}
void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,3,handler);
+ this->attachInterrupt(3, handler);
}
void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,4,handler);
+ this->attachInterrupt(4, handler);
+}
+
+inline void HardwareTimer::detachInterrupt(int channel) {
+ timer_detach_interrupt(this->timerNum, channel);
}
void HardwareTimer::detachCompare1Interrupt(void) {
- timer_detach_interrupt(this->timerNum,1);
+ this->detachInterrupt(1);
}
void HardwareTimer::detachCompare2Interrupt(void) {
- timer_detach_interrupt(this->timerNum,2);
+ this->detachInterrupt(2);
}
void HardwareTimer::detachCompare3Interrupt(void) {
- timer_detach_interrupt(this->timerNum,3);
+ this->detachInterrupt(3);
}
void HardwareTimer::detachCompare4Interrupt(void) {
- timer_detach_interrupt(this->timerNum,4);
+ this->detachInterrupt(4);
+}
+
+void HardwareTimer::generateUpdate(void) {
+ timer_generate_update(this->timerNum);
}
+
HardwareTimer Timer1(TIMER1);
HardwareTimer Timer2(TIMER2);
HardwareTimer Timer3(TIMER3);
@@ -171,3 +204,24 @@ HardwareTimer Timer5(TIMER5); // High-density devices only
HardwareTimer Timer8(TIMER8); // High-density devices only
#endif
+HardwareTimer* getTimer(timer_dev_num timerNum) {
+ switch (timerNum) {
+ case TIMER1:
+ return &Timer1;
+ case TIMER2:
+ return &Timer2;
+ case TIMER3:
+ return &Timer3;
+ case TIMER4:
+ return &Timer4;
+#if NR_TIMERS >= 8
+ case TIMER5:
+ return &Timer5;
+ case TIMER8:
+ return &Timer8;
+#endif
+ default:
+ ASSERT(0);
+ return 0;
+ }
+}
diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h
index b05085f..c72175f 100644
--- a/wirish/HardwareTimer.h
+++ b/wirish/HardwareTimer.h
@@ -26,8 +26,10 @@
* @brief wirish timer class to manage the four 16-bit timer peripherals
*/
-#ifndef _TIMER_H_
-#define _TIMER_H_
+#ifndef _HARDWARETIMER_H_
+#define _HARDWARETIMER_H_
+
+#include "timers.h"
/**
* Interface to one of the 16-bit timer peripherals.
@@ -51,11 +53,16 @@
*/
class HardwareTimer {
private:
- uint16 overflow;
- uint8 timerNum;
+ timer_dev_num timerNum;
public:
- HardwareTimer(uint8 timer_num);
+ HardwareTimer(timer_dev_num timer_num);
+
+ /**
+ * Return this timer's device number. For example,
+ * Timer1.getTimerNum() == TIMER1
+ */
+ timer_dev_num getTimerNum() { return timerNum; }
/**
* Stop the counter, without affecting its configuration.
@@ -90,6 +97,12 @@ class HardwareTimer {
void resume(void);
/**
+ * Returns the timer's prescale factor.
+ * @see HardwareTimer::setPrescaleFactor()
+ */
+ uint16 getPrescaleFactor();
+
+ /**
* Set the timer prescale.
*
* The prescaler acts as a clock divider to slow down the rate at
@@ -112,6 +125,12 @@ class HardwareTimer {
void setPrescaleFactor(uint16 factor);
/**
+ * Gets the timer overflow value.
+ * @see HardwareTimer::setOverflow()
+ */
+ uint16 getOverflow();
+
+ /**
* Sets the timer overflow (or "reload") value.
*
* When the timer's counter reaches this, value it resets to
@@ -122,11 +141,17 @@ class HardwareTimer {
* value for the channel compare values.
*
* @param val The new overflow value to set
- * @see HardwareTimer::setOverflow()
*/
void setOverflow(uint16 val);
/**
+ * Retrieve the current timer count.
+ *
+ * @return The timer's current count value
+ */
+ uint16 getCount(void);
+
+ /**
* Set the current timer count.
*
* Note that there is some function call overhead associated with
@@ -140,13 +165,6 @@ class HardwareTimer {
void setCount(uint16 val);
/**
- * Retrieve the current timer count.
- *
- * @return The timer's current count value
- */
- uint16 getCount(void);
-
- /**
* Configure the prescaler and overflow values to generate a timer
* reload with a period as close to the given number of
* microseconds as possible.
@@ -164,6 +182,18 @@ class HardwareTimer {
uint16 setPeriod(uint32 microseconds);
/**
+ * Set the given channel of this timer to the given mode.
+ *
+ * Note: Timer1.setChannel1Mode(TIMER_PWM) may not work as
+ * expected; if you want PWM functionality on a channel make sure
+ * you don't set it to something else!
+ *
+ * @param channel Timer channel, from 1 to 4
+ * @param mode Mode to set
+ */
+ void setChannelMode(int channel, TimerMode mode);
+
+ /**
* Set channel 1 of this timer to the given mode.
*
* Note: Timer1.setChannel1Mode(TIMER_PWM) may not work as
@@ -193,7 +223,25 @@ class HardwareTimer {
void setChannel4Mode(TimerMode mode);
/**
- * Sets the compare value for channel 1.
+ * Gets the compare value for the given channel.
+ * @see HardwareTimer::setCompare()
+ */
+ uint16 getCompare(int channel);
+
+ /** Like getCompare(1) */
+ uint16 getCompare1();
+
+ /** Like getCompare(2) */
+ uint16 getCompare2();
+
+ /** Like getCompare(3) */
+ uint16 getCompare3();
+
+ /** Like getCompare(4) */
+ uint16 getCompare4();
+
+ /**
+ * Sets the compare value for the given channel.
*
* When the counter reaches this value the interrupt for this
* channel will fire if channel 1 mode is TIMER_OUTPUTCOMPARE and
@@ -210,49 +258,40 @@ class HardwareTimer {
* overheads mean that the smallest increment rate is at least a
* few microseconds.
*
+ * @param channel the channel whose compare to set, from 1 to 4.
* @param val The compare value to set. If greater than this
* timer's overflow value, it will be truncated to the
* overflow value.
*
* @see TimerMode
- * @see HardwareTimer::setChannel1Mode()
+ * @see HardwareTimer::setChannelMode()
*/
- void setCompare1(uint16 val);
+ void setCompare(int channel, uint16 compare);
/**
- * Sets the compare value for channel 2.
- *
- * @param val The compare value to set. If greater than this
- * timer's overflow value, it will be truncated to the
- * overflow value.
- * @see HardwareTimer::setCompare1()
+ * Like setCompare(1, compare).
*/
- void setCompare2(uint16 val);
+ void setCompare1(uint16 compare);
/**
- * Sets the compare value for channel 3.
- *
- * @param val The compare value to set. If greater than this
- * timer's overflow value, it will be truncated to the
- * overflow value.
- * @see HardwareTimer::setCompare1()
+ * Like setCompare(2, compare).
*/
- void setCompare3(uint16 val);
+ void setCompare2(uint16 compare);
/**
- * Sets the compare value for channel 4.
- *
- * @param val The compare value to set. If greater than this
- * timer's overflow value, it will be truncated to the
- * overflow value.
- * @see HardwareTimer::setCompare1()
+ * Like setCompare(3, compare).
+ */
+ void setCompare3(uint16 compare);
+
+ /**
+ * Like setCompare(4, compare).
*/
- void setCompare4(uint16 val);
+ void setCompare4(uint16 compare);
/**
- * Attach an interrupt handler to this timer's channel 1. This
+ * Attach an interrupt handler to the given channel. This
* interrupt handler will be called when the timer's counter
- * reaches its channel 1 compare value.
+ * reaches the given channel compare value.
*
* The argument should be a function which takes no arguments and
* has no return value; i.e. it should have signature
@@ -267,56 +306,75 @@ class HardwareTimer {
* if you have a delay() in your interrupt routine, you're probably
* doing it wrong.
*
- * @param handler The ISR to attach to channel 1.
+ * @param channel the channel to attach the ISR to, from 1 to 4.
+ * @param handler The ISR to attach to the given channel.
* @see voidFuncPtr
*/
+ void attachInterrupt(int channel, voidFuncPtr handler);
+
+ /**
+ * Like attachCompareInterrupt(1, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
+ */
void attachCompare1Interrupt(voidFuncPtr handler);
/**
- * Like attachCompare1Interrupt(), but for channel 2.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like attachCompareInterrupt(2, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
*/
void attachCompare2Interrupt(voidFuncPtr handler);
/**
- * Like attachCompare1Interrupt(), but for channel 3.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like attachCompareInterrupt(3, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
*/
void attachCompare3Interrupt(voidFuncPtr handler);
/**
- * Like attachCompare1Interrupt(), but for channel 4.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like attachCompareInterrupt(4, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
*/
void attachCompare4Interrupt(voidFuncPtr handler);
/**
- * Remove the interrupt handler attached to channel 1, if any.
- * The handler will no longer be called by this timer.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Remove the interrupt handler attached to the given channel, if
+ * any. The handler will no longer be called by this timer.
+ *
+ * @param channel the channel whose interrupt to detach, from 1 to 4.
+ * @see HardwareTimer::attachInterrupt()
+ */
+ void detachInterrupt(int channel);
+
+ /**
+ * Like detachInterrupt(1).
+ * @see HardwareTimer::detachInterrupt()
*/
void detachCompare1Interrupt(void);
/**
- * Remove the interrupt handler attached to channel 2, if any.
- * The handler will no longer be called by this timer.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like detachInterrupt(2).
+ * @see HardwareTimer::detachInterrupt()
*/
void detachCompare2Interrupt(void);
/**
- * Remove the interrupt handler attached to channel 3, if any.
- * The handler will no longer be called by this timer.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like detachInterrupt(3).
+ * @see HardwareTimer::detachInterrupt()
*/
void detachCompare3Interrupt(void);
/**
- * Remove the interrupt handler attached to channel 4, if any.
- * The handler will no longer be called by this timer.
- * @see HardwareTimer::attachCompare1Interrupt()
+ * Like detachInterrupt(4).
+ * @see HardwareTimer::detachInterrupt()
*/
void detachCompare4Interrupt(void);
+
+ /**
+ * Re-initializes the counter (to 0 in upcounting mode, which is
+ * the default), and generates an update of the prescale and
+ * overflow registers.
+ */
+ void generateUpdate(void);
};
/** Pre-instantiated timer for use by user code. */
@@ -336,5 +394,7 @@ extern HardwareTimer Timer5;
extern HardwareTimer Timer8;
#endif
+HardwareTimer* getTimer(timer_dev_num timerNum);
+
#endif
diff --git a/wirish/boards.h b/wirish/boards.h
index 0625d0a..84ff44f 100644
--- a/wirish/boards.h
+++ b/wirish/boards.h
@@ -57,24 +57,26 @@ enum {
ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, };
#define ADC_INVALID 0xFFFFFFFF
-#define TIMER_INVALID 0xFFFFFFFF
/* Types used for the tables below */
typedef struct PinMapping {
GPIO_Port *port;
uint32 pin;
uint32 adc;
- uint32 timer_channel;
+ TimerCCR timer_ccr;
uint32 exti_port;
- uint32 timer_num;
+ timer_dev_num timer_num;
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 SYSTICK_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 */
@@ -86,7 +88,7 @@ typedef struct PinMapping {
/* D3/PA1 */
{GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
/* D4/PB5 */
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D5/PB6 */
{GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
/* D6/PA8 */
@@ -98,78 +100,80 @@ typedef struct PinMapping {
/* D9/PB7 */
{GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 2},
/* D10/PA4 */
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D11/PA7 */
{GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2},
/* D12/PA6 */
{GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
/* D13/PA5 */
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 5, ADC5, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D14/PB8 */
{GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3},
/* Little header */
/* D15/PC0 */
- {GPIOC_BASE, 0, ADC10, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 0, ADC10, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D16/PC1 */
- {GPIOC_BASE, 1, ADC11, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 1, ADC11, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D17/PC2 */
- {GPIOC_BASE, 2, ADC12, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 2, ADC12, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D18/PC3 */
- {GPIOC_BASE, 3, ADC13, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 3, ADC13, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D19/PC4 */
- {GPIOC_BASE, 4, ADC14, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 4, ADC14, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D20/PC5 */
- {GPIOC_BASE, 5, ADC15, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 5, ADC15, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* External header */
/* D21/PC13 */
- {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D22/PC14 */
- {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D23/PC15 */
- {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D24/PB9 */
{GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D25/PD2 */
- {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ {GPIOD_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
/* D26/PC10 */
- {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D27/PB0 */
- {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
/* D28/PB1 */
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
/* D29/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D30/PB11 */
- {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D31/PB12 */
- {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D32/PB13 */
- {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D33/PB14 */
- {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D34/PB15 */
- {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D35/PC6 */
- {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D36/PC7 */
- {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 7, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D37/PC8 */
- {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* PC9 (BUT) */
- {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}
+ {GPIOC_BASE, 9, ADC_INVALID, 0, 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 */
+ #define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
// TODO:
static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
@@ -290,16 +294,18 @@ 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 SYSTICK_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},
+ {GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D1/PA0 */
{GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1},
/* D2/PA1 */
@@ -309,9 +315,9 @@ typedef struct PinMapping {
/* D4/PA3 */
{GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4},
/* D5/PA4 */
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D6/PA5 */
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 5, ADC5, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D7/PA6 */
{GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
/* D8/PA7 */
@@ -321,17 +327,17 @@ typedef struct PinMapping {
/* D10/PB1 */
{GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
/* D11/PB2 */
- {GPIOB_BASE, 2, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D12/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D13/PB11 */
- {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D14/PB13 */
- {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D15/PB14 */
- {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D16/PB15 */
- {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D17/PA8 */
{GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTB, TIMER1, 1},
/* D18/PA9 */
@@ -341,38 +347,45 @@ typedef struct PinMapping {
/* D20/PA11 */
{GPIOA_BASE, 11, ADC_INVALID, TIMER1_CH4_CCR, EXTI_CONFIG_PORTA, TIMER1, 4},
/* D21/PA12 */
- {GPIOA_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D22/PA13 */
- {GPIOA_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D23/PA14 */
- {GPIOA_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D24/PA15 */
- {GPIOA_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ {GPIOA_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D25/PB3 */
- {GPIOB_BASE, 3, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D26/PB4 */
- {GPIOB_BASE, 4, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D27/PB5 */
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D28/PB6 */
{GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
/* D29/PB7 */
{GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
/* D30/PC13 */
- {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D31/PC14 */
- {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ {GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D32/PB8 */
{GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3},
/* D33/PB12 */
- {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 12, ADC_INVALID, 0, 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/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp
index 425c610..d6c7e82 100644
--- a/wirish/comm/HardwareSerial.cpp
+++ b/wirish/comm/HardwareSerial.cpp
@@ -34,9 +34,9 @@
#include "gpio.h"
#include "timers.h"
-HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE, 9, 10, TIMER1, 2);
-HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE, 2, 3, TIMER2, 3);
-HardwareSerial Serial3(USART3, 2250000UL, GPIOB_BASE, 10, 11, 0, 0);
+HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE, 9,10, TIMER1, 2);
+HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE, 2, 3, TIMER2, 3);
+HardwareSerial Serial3(USART3, 2250000UL, GPIOB_BASE, 10,11, TIMER_INVALID, 0);
// TODO: High density device ports
HardwareSerial::HardwareSerial(uint8 usart_num,
@@ -44,7 +44,7 @@ HardwareSerial::HardwareSerial(uint8 usart_num,
GPIO_Port *gpio_port,
uint8 tx_pin,
uint8 rx_pin,
- uint8 timer_num,
+ timer_dev_num timer_num,
uint8 compare_num) {
this->usart_num = usart_num;
this->max_baud = max_baud;
@@ -75,8 +75,7 @@ void HardwareSerial::begin(uint32 baud) {
gpio_set_mode(gpio_port, tx_pin, GPIO_MODE_AF_OUTPUT_PP);
gpio_set_mode(gpio_port, rx_pin, GPIO_MODE_INPUT_FLOATING);
- if ((usart_num == USART1) ||
- (usart_num == USART2)) {
+ if (timer_num != TIMER_INVALID) {
/* turn off any pwm if there's a conflict on this usart */
timer_set_mode(timer_num, compare_num, TIMER_DISABLED);
}
diff --git a/wirish/comm/HardwareSerial.h b/wirish/comm/HardwareSerial.h
index fdfc06d..aad8aa7 100644
--- a/wirish/comm/HardwareSerial.h
+++ b/wirish/comm/HardwareSerial.h
@@ -31,6 +31,8 @@
#ifndef _HARDWARESERIAL_H_
#define _HARDWARESERIAL_H_
+#include "timers.h"
+
#include "Print.h"
/* NB: this class documented "by hand" (i.e., not using Doxygen) in:
@@ -47,7 +49,7 @@ class HardwareSerial : public Print {
GPIO_Port *gpio_port;
uint8 tx_pin;
uint8 rx_pin;
- uint8 timer_num;
+ timer_dev_num timer_num;
uint8 compare_num;
public:
HardwareSerial(uint8 usart_num,
@@ -55,7 +57,7 @@ class HardwareSerial : public Print {
GPIO_Port *gpio_port,
uint8 tx_pin,
uint8 rx_pin,
- uint8 timer_num,
+ timer_dev_num timer_num,
uint8 compare_num);
void begin(uint32 baud);
void end(void);
diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h
index d44978a..057c0d3 100644
--- a/wirish/ext_interrupts.h
+++ b/wirish/ext_interrupts.h
@@ -23,6 +23,7 @@
*****************************************************************************/
#include "libmaple_types.h"
+#include "nvic.h"
/**
* @file ext_interrupts.h
@@ -77,6 +78,32 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode);
*/
void detachInterrupt(uint8 pin);
+/**
+ * Re-enable interrupts.
+ *
+ * Call this after noInterrupts() to re-enable interrupt handling,
+ * after you have finished with a timing-critical section of code.
+ *
+ * @see noInterrupts()
+ */
+static inline __attribute__((always_inline)) void interrupts() {
+ nvic_globalirq_enable();
+}
+
+/**
+ * Disable interrupts.
+ *
+ * After calling this function, all user-programmable interrupts will
+ * be disabled. You can call this function before a timing-critical
+ * section of code, then call interrupts() to re-enable interrupt
+ * handling.
+ *
+ * @see interrupts()
+ */
+static inline __attribute__((always_inline)) void noInterrupts() {
+ nvic_globalirq_disable();
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/wirish/io.h b/wirish/io.h
index 24f2611..547dc8e 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"{
@@ -162,6 +163,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/pwm.c b/wirish/pwm.c
index dc5cfab..072e4cd 100644
--- a/wirish/pwm.c
+++ b/wirish/pwm.c
@@ -38,9 +38,9 @@ void pwmWrite(uint8 pin, uint16 duty_cycle) {
return;
}
- ccr = (TimerCCR)(PIN_MAP[pin].timer_channel);
+ ccr = PIN_MAP[pin].timer_ccr;
- if (ccr == (TimerCCR)TIMER_INVALID) {
+ if (ccr == 0) {
return;
}
diff --git a/wirish/time.h b/wirish/time.h
index 18aef9a..c925f74 100644
--- a/wirish/time.h
+++ b/wirish/time.h
@@ -68,10 +68,10 @@ static inline uint32 micros(void) {
nvic_globalirq_enable();
- /* MAPLE_RELOAD_VAL is 1 less than the number of cycles it actually
- takes to complete a systick reload */
+ /* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it
+ actually takes to complete a SysTick reload */
res = (ms * US_PER_MS) +
- (MAPLE_RELOAD_VAL + 1 - cycle_cnt)/CYCLES_PER_MICROSECOND;
+ (SYSTICK_RELOAD_VAL + 1 - cycle_cnt)/CYCLES_PER_MICROSECOND;
return res;
}
diff --git a/wirish/wirish.c b/wirish/wirish.c
index 0abec41..db38050 100644
--- a/wirish/wirish.c
+++ b/wirish/wirish.c
@@ -62,7 +62,7 @@ void init(void) {
rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
nvic_init();
- systick_init(MAPLE_RELOAD_VAL);
+ systick_init(SYSTICK_RELOAD_VAL);
gpio_init();
adc_init();
timer_init(TIMER1, 1);
@@ -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 d7da81f..6f9906d 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;
+}
diff --git a/wirish/wirish_math.cpp b/wirish/wirish_math.cpp
index 12a21c3..5aa6510 100644
--- a/wirish/wirish_math.cpp
+++ b/wirish/wirish_math.cpp
@@ -47,8 +47,3 @@ long random(long howsmall, long howbig) {
return random(diff) + howsmall;
}
-long map(long x, long in_min, long in_max, long out_min, long out_max) {
- return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
-}
-
-
diff --git a/wirish/wirish_math.h b/wirish/wirish_math.h
index 9578eb4..4156722 100644
--- a/wirish/wirish_math.h
+++ b/wirish/wirish_math.h
@@ -78,9 +78,10 @@ long random(long min, long max);
* @param toEnd the end of the value's mapped range.
* @return the mapped value.
*/
-long map(long value,
- long fromStart, long fromEnd,
- long toStart, long toEnd);
+/* TODO: profile code bloat due to inlining this */
+inline long map(long x, long in_min, long in_max, long out_min, long out_max) {
+ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398