aboutsummaryrefslogtreecommitdiffstats
path: root/wirish
diff options
context:
space:
mode:
Diffstat (limited to 'wirish')
-rw-r--r--wirish/HardwareTimer.cpp167
-rw-r--r--wirish/HardwareTimer.h368
-rw-r--r--wirish/bit_constants.h579
-rw-r--r--wirish/bits.h74
-rw-r--r--wirish/boards.h514
-rw-r--r--wirish/comm/HardwareSPI.h23
-rw-r--r--wirish/comm/HardwareSerial.cpp11
-rw-r--r--wirish/comm/HardwareSerial.h15
-rw-r--r--wirish/ext_interrupts.c20
-rw-r--r--wirish/ext_interrupts.h72
-rw-r--r--wirish/io.h213
-rw-r--r--wirish/pwm.c6
-rw-r--r--wirish/pwm.h14
-rw-r--r--wirish/time.c1
-rw-r--r--wirish/time.h42
-rw-r--r--wirish/usb_serial.cpp16
-rw-r--r--wirish/wirish.c5
-rw-r--r--wirish/wirish.h4
-rw-r--r--wirish/wirish_digital.c53
-rw-r--r--wirish/wirish_math.cpp5
-rw-r--r--wirish/wirish_math.h103
21 files changed, 1910 insertions, 395 deletions
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
index 6fbad8b..354663e 100644
--- a/wirish/HardwareTimer.cpp
+++ b/wirish/HardwareTimer.cpp
@@ -22,22 +22,17 @@
* THE SOFTWARE.
*****************************************************************************/
-/**
- * @brief wirish timer class to manage the four 16-bit timer peripherals
- *
- * This implementation is not very efficient (lots of duplicated functions)
+/*
+ * wirish timer class to manage the four 16-bit timer peripherals
*/
#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) {
@@ -48,126 +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);
}
-/* This function will set the prescaler and overflow to get a period
- * of the given length with the most resolution; the return value is
- * the overflow value and thus the largest value that can be set as a
- * compare. */
-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) {
+ this->setChannelMode(1, mode);
+}
+
+void HardwareTimer::setChannel2Mode(TimerMode mode) {
+ this->setChannelMode(2, mode);
+}
+
+void HardwareTimer::setChannel3Mode(TimerMode mode) {
+ this->setChannelMode(3, mode);
+}
+
+void HardwareTimer::setChannel4Mode(TimerMode mode) {
+ this->setChannelMode(4, mode);
}
-void HardwareTimer::setChannel1Mode(uint8 mode) {
- timer_set_mode(this->timerNum,1,mode);
+inline uint16 HardwareTimer::getCompare(int channel) {
+ return timer_get_compare_value(this->timerNum, channel);
}
-void HardwareTimer::setChannel2Mode(uint8 mode) {
- timer_set_mode(this->timerNum,2,mode);
+uint16 HardwareTimer::getCompare1() {
+ return this->getCompare(1);
}
-void HardwareTimer::setChannel3Mode(uint8 mode) {
- timer_set_mode(this->timerNum,3,mode);
+uint16 HardwareTimer::getCompare2() {
+ return this->getCompare(2);
}
-void HardwareTimer::setChannel4Mode(uint8 mode) {
- timer_set_mode(this->timerNum,4,mode);
+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);
@@ -177,3 +204,23 @@ 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:
+ return 0;
+ }
+}
diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h
index c6e11c8..4034b1f 100644
--- a/wirish/HardwareTimer.h
+++ b/wirish/HardwareTimer.h
@@ -26,52 +26,388 @@
* @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.
+ *
+ * User code should not instantiate this class directly; instead, use
+ * one of the predefined Timer<n> instances (Timer1, Timer2, etc.).
+ *
+ * HardwareTimer instances can be configured to generate periodic or
+ * delayed events with minimal work done by the microcontroller. Each
+ * timer maintains a single 16-bit count that can be configured with a
+ * prescaler and overflow value.
+ *
+ * By default, a timer's counter is incremented once per clock cycle.
+ * The prescaler acts as a divider of the 72MHz Maple system clock;
+ * without prescaling, the timer's count would reach 65535 (2**16-1)
+ * and roll over over 1000 times per second.
+ *
+ * The overflow value is the maximum value the counter will reach. It
+ * defaults to 65535; smaller values will cause the counter to reset
+ * more frequently.
+ */
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.
+ *
+ * The timer will no longer count or fire interrupts after this
+ * function is called, until it is resumed. This function is
+ * useful during timer setup periods, in order to prevent
+ * interrupts from firing before the timer is fully configured.
+ *
+ * Note that there is some function call overhead associated with
+ * this method, so using it in concert with
+ * HardwareTimer::resume() is not a robust way to align multiple
+ * timers to the same count value.
+ *
+ * @see HardwareTimer::resume()
+ */
void pause(void);
+
+ /**
+ * Resume a paused timer, without affecting its configuration.
+ *
+ * The timer will resume counting and firing interrupts as
+ * appropriate.
+ *
+ * Note that there is some function call overhead associated with
+ * using this method, so using it in concert with
+ * HardwareTimer::pause() is not a robust way to align multiple
+ * timers to the same count value.
+ *
+ * @see HardwareTimer::pause()
+ */
void resume(void);
+
+ /**
+ * Returns the timer's prescale factor.
+ * @see HardwareTimer::setPrescaleFactor()
+ */
+ uint16 getPrescaleFactor();
+
+ /**
+ * Set the timer's prescale factor.
+ *
+ * The prescaler acts as a clock divider to slow down the rate at
+ * which the counter increments.
+ *
+ * For example, the system clock rate is 72MHz, so the counter
+ * will reach 65535 in (13.89 nanoseconds) * (65535 counts) =
+ * (910.22 microseconds), or about a thousand times a second. If
+ * the prescaler equals 1098, then the clock rate is effectively
+ * 65.56KHz, and the counter will reach 65536 in (15.25
+ * microseconds) * (65536 counts) = (0.999 seconds), or about once
+ * per second.
+ *
+ * The HardwareTimer::setPeriod() method may also be used as a
+ * convenient alternative.
+ *
+ * @param factor The new prescale value to set.
+ * @see HardwareTimer::setPeriod()
+ */
void setPrescaleFactor(uint16 factor);
- void setOverflow(uint16 val); // truncates to overflow
- void setCount(uint16 val); // truncates to overflow
+
+ /**
+ * 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
+ * zero. Its default value is 65535 (the largest unsigned 16-bit
+ * integer); setting the overflow to anything lower will cause
+ * interrupts to be called more frequently (see the setPeriod()
+ * function below for a shortcut). This number sets the maximum
+ * value for the channel compare values.
+ *
+ * @param val The new overflow value to set
+ */
+ void setOverflow(uint16 val);
+
+ /**
+ * Retrieve the current timer count.
+ *
+ * @return The timer's current count value
+ */
uint16 getCount(void);
- // tries to set prescaler and overflow wisely; returns overflow
+ /**
+ * Set the current timer count.
+ *
+ * Note that there is some function call overhead associated with
+ * calling this method, so using it is not a robust way to get
+ * multiple timers to share a count value.
+ *
+ * @param val The new count value to set. If this value exceeds
+ * the timer's overflow value, it is truncated to the
+ * overflow value.
+ */
+ void setCount(uint16 val);
+
+ /**
+ * Configure the prescaler and overflow values to generate a timer
+ * reload with a period as close to the given number of
+ * microseconds as possible.
+ *
+ * The return value is the overflow, which may be used to set
+ * channel compare values. However, if a clock that fires an
+ * interrupt every given number of microseconds is all that is
+ * desired, and the relative "phases" are unimportant, channel
+ * compare values may all be set to 1.
+ *
+ * @param microseconds the desired period of the timer.
+ * @return the overflow value (and thus, the largest value that can be
+ * set as a compare).
+ */
uint16 setPeriod(uint32 microseconds);
- void setChannel1Mode(uint8 mode);
- void setChannel2Mode(uint8 mode);
- void setChannel3Mode(uint8 mode);
- void setChannel4Mode(uint8 mode);
- void setCompare1(uint16 val); // truncates to overflow
- void setCompare2(uint16 val); // truncates to overflow
- void setCompare3(uint16 val); // truncates to overflow
- void setCompare4(uint16 val); // truncates to overflow
+
+ /**
+ * Set the given channel of this timer to the given mode.
+ *
+ * @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
+ * expected; if you want PWM functionality on a channel make sure
+ * you don't set it to something else!
+ *
+ * @see TimerMode
+ */
+ void setChannel1Mode(TimerMode mode);
+
+ /**
+ * Set channel 2 of this timer to the given mode.
+ * @see TimerMode
+ */
+ void setChannel2Mode(TimerMode mode);
+
+ /**
+ * Set channel 3 of this timer to the given mode.
+ * @see TimerMode
+ */
+ void setChannel3Mode(TimerMode mode);
+
+ /**
+ * Set channel 4 of this timer to the given mode.
+ * @see TimerMode
+ */
+ void setChannel4Mode(TimerMode mode);
+
+ /**
+ * Gets the compare value for the given channel.
+ * @see HardwareTimer::setCompare()
+ */
+ uint16 getCompare(int channel);
+
+ /** Equivalent to getCompare(1) */
+ uint16 getCompare1();
+
+ /** Equivalent to getCompare(2) */
+ uint16 getCompare2();
+
+ /** Equivalent to getCompare(3) */
+ uint16 getCompare3();
+
+ /** Equivalent to 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 the channel mode is TIMER_OUTPUTCOMPARE
+ * and an interrupt is attached.
+ *
+ * By default, this only changes the relative offsets between
+ * events on a single timer ("phase"); they don't control the
+ * frequency with which they occur. However, a common trick is to
+ * increment the compare value manually in the interrupt handler
+ * so that the event will fire again after the increment
+ * period. There can be a different increment value for each
+ * channel, so this trick allows events to be programmed at 4
+ * different rates on a single timer. Note that function call
+ * 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 compare 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::setChannelMode()
+ * @see HardwareTimer::attachInterrupt()
+ */
+ void setCompare(int channel, uint16 compare);
+
+ /**
+ * Equivalent to setCompare(1, compare).
+ */
+ void setCompare1(uint16 compare);
+
+ /**
+ * Equivalent to setCompare(2, compare).
+ */
+ void setCompare2(uint16 compare);
+
+ /**
+ * Equivalent to setCompare(3, compare).
+ */
+ void setCompare3(uint16 compare);
+
+ /**
+ * Equivalent to setCompare(4, compare).
+ */
+ void setCompare4(uint16 compare);
+
+ /**
+ * Attach an interrupt handler to the given channel. This
+ * interrupt handler will be called when the timer's counter
+ * 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
+ *
+ * void (*handler)(void);
+ *
+ * Note: The function (often called an interrupt service routine,
+ * or ISR) should attempt to return as quickly as possible.
+ * Blinking the LED, some logic, PWM updates, and Serial writes
+ * are fine; writing to SerialUSB or waiting for user input can
+ * take a long time and other compare interrupts won't fire. Tip:
+ * if you have a delay() in your interrupt routine, you're probably
+ * doing it wrong.
+ *
+ * @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);
+
+ /**
+ * Equivalent to attachCompareInterrupt(1, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
+ */
void attachCompare1Interrupt(voidFuncPtr handler);
+
+ /**
+ * Equivalent to attachCompareInterrupt(2, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
+ */
void attachCompare2Interrupt(voidFuncPtr handler);
+
+ /**
+ * Equivalent to attachCompareInterrupt(3, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
+ */
void attachCompare3Interrupt(voidFuncPtr handler);
+
+ /**
+ * Equivalent to attachCompareInterrupt(4, handler).
+ * @see HardwareTimer::attachCompareInterrupt()
+ */
void attachCompare4Interrupt(voidFuncPtr handler);
+
+ /**
+ * 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);
+
+ /**
+ * Equivalent to detachInterrupt(1).
+ * @see HardwareTimer::detachInterrupt()
+ */
void detachCompare1Interrupt(void);
+
+ /**
+ * Equivalent to detachInterrupt(2).
+ * @see HardwareTimer::detachInterrupt()
+ */
void detachCompare2Interrupt(void);
+
+ /**
+ * Equivalent to detachInterrupt(3).
+ * @see HardwareTimer::detachInterrupt()
+ */
void detachCompare3Interrupt(void);
+
+ /**
+ * Equivalent to 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. */
extern HardwareTimer Timer1;
+/** Pre-instantiated timer for use by user code. */
extern HardwareTimer Timer2;
+/** Pre-instantiated timer for use by user code. */
extern HardwareTimer Timer3;
+/** Pre-instantiated timer for use by user code. */
extern HardwareTimer Timer4;
#if NR_TIMERS >= 8
+/** Pre-instantiated timer for use by user code, on devices with
+ more than four timers (this does not include the Maple). */
extern HardwareTimer Timer5;
+/** Pre-instantiated timer for use by user code, on devices with
+ more than four timers (this does not include the Maple). */
extern HardwareTimer Timer8;
#endif
+/**
+ * Get one of the pre-instantiated HardwareTimer instances, given a
+ * timer device number.
+ *
+ * Be careful not to pass an actual number to this function. For
+ * example, getTimer(1) will not return Timer1. Use a real
+ * timer_dev_num, e.g. TIMER1, TIMER2, etc.
+ *
+ * @param timerNum the timer device number, e.g. TIMER1.
+ *
+ * @return Pointer to the HardwareTimer instance corresponding to the
+ * given timer device number. If timerNum is TIMER_INVALID, returns a
+ * null pointer.
+ *
+ * @see timer_dev_num
+ */
+HardwareTimer* getTimer(timer_dev_num timerNum);
+
#endif
diff --git a/wirish/bit_constants.h b/wirish/bit_constants.h
new file mode 100644
index 0000000..8accc6b
--- /dev/null
+++ b/wirish/bit_constants.h
@@ -0,0 +1,579 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 LeafLabs, LLC.
+ *
+ * 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.
+ *****************************************************************************/
+
+/**
+ * @brief BIT[n] and binary literal defines, for Arduino
+ * compatibility.
+ */
+
+#ifndef _BIT_CONSTANTS_H_
+#define _BIT_CONSTANTS_H_
+
+#define BIT0 (1 << 0)
+#define BIT1 (1 << 1)
+#define BIT2 (1 << 2)
+#define BIT3 (1 << 3)
+#define BIT4 (1 << 4)
+#define BIT5 (1 << 5)
+#define BIT6 (1 << 6)
+#define BIT7 (1 << 7)
+#define BIT8 (1 << 8)
+#define BIT9 (1 << 9)
+#define BIT10 (1 << 10)
+#define BIT11 (1 << 11)
+#define BIT12 (1 << 12)
+#define BIT13 (1 << 13)
+#define BIT14 (1 << 14)
+#define BIT15 (1 << 15)
+#define BIT16 (1 << 16)
+#define BIT17 (1 << 17)
+#define BIT18 (1 << 18)
+#define BIT19 (1 << 19)
+#define BIT20 (1 << 20)
+#define BIT21 (1 << 21)
+#define BIT22 (1 << 22)
+#define BIT23 (1 << 23)
+#define BIT24 (1 << 24)
+#define BIT25 (1 << 25)
+#define BIT26 (1 << 26)
+#define BIT27 (1 << 27)
+#define BIT28 (1 << 28)
+#define BIT29 (1 << 29)
+#define BIT30 (1 << 30)
+#define BIT31 (1 << 31)
+
+#define B0 0
+#define B00 0
+#define B000 0
+#define B0000 0
+#define B00000 0
+#define B000000 0
+#define B0000000 0
+#define B00000000 0
+#define B1 1
+#define B01 1
+#define B001 1
+#define B0001 1
+#define B00001 1
+#define B000001 1
+#define B0000001 1
+#define B00000001 1
+#define B10 2
+#define B010 2
+#define B0010 2
+#define B00010 2
+#define B000010 2
+#define B0000010 2
+#define B00000010 2
+#define B11 3
+#define B011 3
+#define B0011 3
+#define B00011 3
+#define B000011 3
+#define B0000011 3
+#define B00000011 3
+#define B100 4
+#define B0100 4
+#define B00100 4
+#define B000100 4
+#define B0000100 4
+#define B00000100 4
+#define B101 5
+#define B0101 5
+#define B00101 5
+#define B000101 5
+#define B0000101 5
+#define B00000101 5
+#define B110 6
+#define B0110 6
+#define B00110 6
+#define B000110 6
+#define B0000110 6
+#define B00000110 6
+#define B111 7
+#define B0111 7
+#define B00111 7
+#define B000111 7
+#define B0000111 7
+#define B00000111 7
+#define B1000 8
+#define B01000 8
+#define B001000 8
+#define B0001000 8
+#define B00001000 8
+#define B1001 9
+#define B01001 9
+#define B001001 9
+#define B0001001 9
+#define B00001001 9
+#define B1010 10
+#define B01010 10
+#define B001010 10
+#define B0001010 10
+#define B00001010 10
+#define B1011 11
+#define B01011 11
+#define B001011 11
+#define B0001011 11
+#define B00001011 11
+#define B1100 12
+#define B01100 12
+#define B001100 12
+#define B0001100 12
+#define B00001100 12
+#define B1101 13
+#define B01101 13
+#define B001101 13
+#define B0001101 13
+#define B00001101 13
+#define B1110 14
+#define B01110 14
+#define B001110 14
+#define B0001110 14
+#define B00001110 14
+#define B1111 15
+#define B01111 15
+#define B001111 15
+#define B0001111 15
+#define B00001111 15
+#define B10000 16
+#define B010000 16
+#define B0010000 16
+#define B00010000 16
+#define B10001 17
+#define B010001 17
+#define B0010001 17
+#define B00010001 17
+#define B10010 18
+#define B010010 18
+#define B0010010 18
+#define B00010010 18
+#define B10011 19
+#define B010011 19
+#define B0010011 19
+#define B00010011 19
+#define B10100 20
+#define B010100 20
+#define B0010100 20
+#define B00010100 20
+#define B10101 21
+#define B010101 21
+#define B0010101 21
+#define B00010101 21
+#define B10110 22
+#define B010110 22
+#define B0010110 22
+#define B00010110 22
+#define B10111 23
+#define B010111 23
+#define B0010111 23
+#define B00010111 23
+#define B11000 24
+#define B011000 24
+#define B0011000 24
+#define B00011000 24
+#define B11001 25
+#define B011001 25
+#define B0011001 25
+#define B00011001 25
+#define B11010 26
+#define B011010 26
+#define B0011010 26
+#define B00011010 26
+#define B11011 27
+#define B011011 27
+#define B0011011 27
+#define B00011011 27
+#define B11100 28
+#define B011100 28
+#define B0011100 28
+#define B00011100 28
+#define B11101 29
+#define B011101 29
+#define B0011101 29
+#define B00011101 29
+#define B11110 30
+#define B011110 30
+#define B0011110 30
+#define B00011110 30
+#define B11111 31
+#define B011111 31
+#define B0011111 31
+#define B00011111 31
+#define B100000 32
+#define B0100000 32
+#define B00100000 32
+#define B100001 33
+#define B0100001 33
+#define B00100001 33
+#define B100010 34
+#define B0100010 34
+#define B00100010 34
+#define B100011 35
+#define B0100011 35
+#define B00100011 35
+#define B100100 36
+#define B0100100 36
+#define B00100100 36
+#define B100101 37
+#define B0100101 37
+#define B00100101 37
+#define B100110 38
+#define B0100110 38
+#define B00100110 38
+#define B100111 39
+#define B0100111 39
+#define B00100111 39
+#define B101000 40
+#define B0101000 40
+#define B00101000 40
+#define B101001 41
+#define B0101001 41
+#define B00101001 41
+#define B101010 42
+#define B0101010 42
+#define B00101010 42
+#define B101011 43
+#define B0101011 43
+#define B00101011 43
+#define B101100 44
+#define B0101100 44
+#define B00101100 44
+#define B101101 45
+#define B0101101 45
+#define B00101101 45
+#define B101110 46
+#define B0101110 46
+#define B00101110 46
+#define B101111 47
+#define B0101111 47
+#define B00101111 47
+#define B110000 48
+#define B0110000 48
+#define B00110000 48
+#define B110001 49
+#define B0110001 49
+#define B00110001 49
+#define B110010 50
+#define B0110010 50
+#define B00110010 50
+#define B110011 51
+#define B0110011 51
+#define B00110011 51
+#define B110100 52
+#define B0110100 52
+#define B00110100 52
+#define B110101 53
+#define B0110101 53
+#define B00110101 53
+#define B110110 54
+#define B0110110 54
+#define B00110110 54
+#define B110111 55
+#define B0110111 55
+#define B00110111 55
+#define B111000 56
+#define B0111000 56
+#define B00111000 56
+#define B111001 57
+#define B0111001 57
+#define B00111001 57
+#define B111010 58
+#define B0111010 58
+#define B00111010 58
+#define B111011 59
+#define B0111011 59
+#define B00111011 59
+#define B111100 60
+#define B0111100 60
+#define B00111100 60
+#define B111101 61
+#define B0111101 61
+#define B00111101 61
+#define B111110 62
+#define B0111110 62
+#define B00111110 62
+#define B111111 63
+#define B0111111 63
+#define B00111111 63
+#define B1000000 64
+#define B01000000 64
+#define B1000001 65
+#define B01000001 65
+#define B1000010 66
+#define B01000010 66
+#define B1000011 67
+#define B01000011 67
+#define B1000100 68
+#define B01000100 68
+#define B1000101 69
+#define B01000101 69
+#define B1000110 70
+#define B01000110 70
+#define B1000111 71
+#define B01000111 71
+#define B1001000 72
+#define B01001000 72
+#define B1001001 73
+#define B01001001 73
+#define B1001010 74
+#define B01001010 74
+#define B1001011 75
+#define B01001011 75
+#define B1001100 76
+#define B01001100 76
+#define B1001101 77
+#define B01001101 77
+#define B1001110 78
+#define B01001110 78
+#define B1001111 79
+#define B01001111 79
+#define B1010000 80
+#define B01010000 80
+#define B1010001 81
+#define B01010001 81
+#define B1010010 82
+#define B01010010 82
+#define B1010011 83
+#define B01010011 83
+#define B1010100 84
+#define B01010100 84
+#define B1010101 85
+#define B01010101 85
+#define B1010110 86
+#define B01010110 86
+#define B1010111 87
+#define B01010111 87
+#define B1011000 88
+#define B01011000 88
+#define B1011001 89
+#define B01011001 89
+#define B1011010 90
+#define B01011010 90
+#define B1011011 91
+#define B01011011 91
+#define B1011100 92
+#define B01011100 92
+#define B1011101 93
+#define B01011101 93
+#define B1011110 94
+#define B01011110 94
+#define B1011111 95
+#define B01011111 95
+#define B1100000 96
+#define B01100000 96
+#define B1100001 97
+#define B01100001 97
+#define B1100010 98
+#define B01100010 98
+#define B1100011 99
+#define B01100011 99
+#define B1100100 100
+#define B01100100 100
+#define B1100101 101
+#define B01100101 101
+#define B1100110 102
+#define B01100110 102
+#define B1100111 103
+#define B01100111 103
+#define B1101000 104
+#define B01101000 104
+#define B1101001 105
+#define B01101001 105
+#define B1101010 106
+#define B01101010 106
+#define B1101011 107
+#define B01101011 107
+#define B1101100 108
+#define B01101100 108
+#define B1101101 109
+#define B01101101 109
+#define B1101110 110
+#define B01101110 110
+#define B1101111 111
+#define B01101111 111
+#define B1110000 112
+#define B01110000 112
+#define B1110001 113
+#define B01110001 113
+#define B1110010 114
+#define B01110010 114
+#define B1110011 115
+#define B01110011 115
+#define B1110100 116
+#define B01110100 116
+#define B1110101 117
+#define B01110101 117
+#define B1110110 118
+#define B01110110 118
+#define B1110111 119
+#define B01110111 119
+#define B1111000 120
+#define B01111000 120
+#define B1111001 121
+#define B01111001 121
+#define B1111010 122
+#define B01111010 122
+#define B1111011 123
+#define B01111011 123
+#define B1111100 124
+#define B01111100 124
+#define B1111101 125
+#define B01111101 125
+#define B1111110 126
+#define B01111110 126
+#define B1111111 127
+#define B01111111 127
+#define B10000000 128
+#define B10000001 129
+#define B10000010 130
+#define B10000011 131
+#define B10000100 132
+#define B10000101 133
+#define B10000110 134
+#define B10000111 135
+#define B10001000 136
+#define B10001001 137
+#define B10001010 138
+#define B10001011 139
+#define B10001100 140
+#define B10001101 141
+#define B10001110 142
+#define B10001111 143
+#define B10010000 144
+#define B10010001 145
+#define B10010010 146
+#define B10010011 147
+#define B10010100 148
+#define B10010101 149
+#define B10010110 150
+#define B10010111 151
+#define B10011000 152
+#define B10011001 153
+#define B10011010 154
+#define B10011011 155
+#define B10011100 156
+#define B10011101 157
+#define B10011110 158
+#define B10011111 159
+#define B10100000 160
+#define B10100001 161
+#define B10100010 162
+#define B10100011 163
+#define B10100100 164
+#define B10100101 165
+#define B10100110 166
+#define B10100111 167
+#define B10101000 168
+#define B10101001 169
+#define B10101010 170
+#define B10101011 171
+#define B10101100 172
+#define B10101101 173
+#define B10101110 174
+#define B10101111 175
+#define B10110000 176
+#define B10110001 177
+#define B10110010 178
+#define B10110011 179
+#define B10110100 180
+#define B10110101 181
+#define B10110110 182
+#define B10110111 183
+#define B10111000 184
+#define B10111001 185
+#define B10111010 186
+#define B10111011 187
+#define B10111100 188
+#define B10111101 189
+#define B10111110 190
+#define B10111111 191
+#define B11000000 192
+#define B11000001 193
+#define B11000010 194
+#define B11000011 195
+#define B11000100 196
+#define B11000101 197
+#define B11000110 198
+#define B11000111 199
+#define B11001000 200
+#define B11001001 201
+#define B11001010 202
+#define B11001011 203
+#define B11001100 204
+#define B11001101 205
+#define B11001110 206
+#define B11001111 207
+#define B11010000 208
+#define B11010001 209
+#define B11010010 210
+#define B11010011 211
+#define B11010100 212
+#define B11010101 213
+#define B11010110 214
+#define B11010111 215
+#define B11011000 216
+#define B11011001 217
+#define B11011010 218
+#define B11011011 219
+#define B11011100 220
+#define B11011101 221
+#define B11011110 222
+#define B11011111 223
+#define B11100000 224
+#define B11100001 225
+#define B11100010 226
+#define B11100011 227
+#define B11100100 228
+#define B11100101 229
+#define B11100110 230
+#define B11100111 231
+#define B11101000 232
+#define B11101001 233
+#define B11101010 234
+#define B11101011 235
+#define B11101100 236
+#define B11101101 237
+#define B11101110 238
+#define B11101111 239
+#define B11110000 240
+#define B11110001 241
+#define B11110010 242
+#define B11110011 243
+#define B11110100 244
+#define B11110101 245
+#define B11110110 246
+#define B11110111 247
+#define B11111000 248
+#define B11111001 249
+#define B11111010 250
+#define B11111011 251
+#define B11111100 252
+#define B11111101 253
+#define B11111110 254
+#define B11111111 255
+
+#endif /* _BIT_CONSTANTS_H_ */
diff --git a/wirish/bits.h b/wirish/bits.h
index 7b51e5e..b2c9d5c 100644
--- a/wirish/bits.h
+++ b/wirish/bits.h
@@ -1,56 +1,30 @@
-/*
- * Part of Arduino - http://www.arduino.cc/
+/******************************************************************************
+ * The MIT License
*
- * Copyright (c) 2005-2006 David A. Mellis
+ * Copyright (c) 2010 LeafLabs, LLC.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
+ * 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:
*
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
+ * 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.
+ *****************************************************************************/
-// BIT DEFINITION
-
-#define BIT0 0x00000001
-#define BIT1 0x00000002
-#define BIT2 0x00000004
-#define BIT3 0x00000008
-#define BIT4 0x00000010
-#define BIT5 0x00000020
-#define BIT6 0x00000040
-#define BIT7 0x00000080
-#define BIT8 0x00000100
-#define BIT9 0x00000200
-#define BIT10 0x00000400
-#define BIT11 0x00000800
-#define BIT12 0x00001000
-#define BIT13 0x00002000
-#define BIT14 0x00004000
-#define BIT15 0x00008000
-#define BIT16 0x00010000
-#define BIT17 0x00020000
-#define BIT18 0x00040000
-#define BIT19 0x00080000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
+/* Note: Use of this header file is deprecated. Use bit_constants.h
+ instead. */
+#include "bit_constants.h"
diff --git a/wirish/boards.h b/wirish/boards.h
index eed3e26..f8505ab 100644
--- a/wirish/boards.h
+++ b/wirish/boards.h
@@ -57,241 +57,433 @@ enum {
ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, };
#define ADC_INVALID 0xFFFFFFFF
-#define TIMER_INVALID (TimerCCR)0xFFFFFFFF
/* Types used for the tables below */
typedef struct PinMapping {
GPIO_Port *port;
uint32 pin;
uint32 adc;
- TimerCCR timer_channel;
+ TimerCCR timer_ccr;
uint32 exti_port;
+ 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 */
- {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4},
/* D1/PA2 */
- {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2, 3},
/* D2/PA0 */
- {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1},
/* D3/PA1 */
- {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
/* D4/PB5 */
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {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},
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
/* D6/PA8 */
- {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA, TIMER1, 1},
/* D7/PA9 */
- {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER1, 2},
/* D8/PA10 */
- {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1, 3},
/* D9/PB7 */
- {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 2},
/* D10/PA4 */
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D11/PA7 */
- {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2},
/* D12/PA6 */
- {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
/* D13/PA5 */
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID, EXTI_CONFIG_PORTA},
+ {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},
+ {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},
+ {GPIOC_BASE, 0, ADC10, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D16/PC1 */
- {GPIOC_BASE, 1, ADC11, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 1, ADC11, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D17/PC2 */
- {GPIOC_BASE, 2, ADC12, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 2, ADC12, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D18/PC3 */
- {GPIOC_BASE, 3, ADC13, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 3, ADC13, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D19/PC4 */
- {GPIOC_BASE, 4, ADC14, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 4, ADC14, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D20/PC5 */
- {GPIOC_BASE, 5, ADC15, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
/* D28/PB1 */
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
/* D29/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
+ {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},
- /* PC9 (BUT) */
- {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC}
+ {GPIOC_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D38/PC9 (BUT) */
+ {GPIOC_BASE, 9, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}
};
-#endif
+ #define BOARD_INIT do { \
+ } while(0)
+
+#elif defined(BOARD_maple_native)
-/* LeafLabs Maple Native (prototype) */
-#ifdef 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 */
+
+ #define BOARD_LED_PIN D21
+ #define BOARD_BUTTON_PIN D18
- // TODO:
static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
- /* D0/PA3 */
- {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR},
- /* D1/PA2 */
- {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR},
- /* D2/PA0 */
- {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR},
- /* D3/PA1 */
- {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR},
- /* D4/PB5 */
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID},
- /* D5/PB6 */
- {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR},
- /* D6/PA8 */
- {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR},
- /* D7/PA9 */
- {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR},
- /* D8/PA10 */
- {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR},
- /* D9/PB7 */
- {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR},
- /* D10/PA4 */
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID},
- /* D11/PA7 */
- {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR},
- /* D12/PA6 */
- {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR},
- /* D13/PA5 */
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID},
- /* D14/PB8 */
- {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR},
+ /* Top header */
- /* Little header */
+ /* D0/PB10 */
+ {GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D1/PB2 */
+ {GPIOB_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D2/PB12 */
+ {GPIOB_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D3/PB13 */
+ {GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D4/PB14 */
+ {GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D5/PB15 */
+ {GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D6/PC0 */
+ {GPIOC_BASE, 0, ADC10, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D7/PC1 */
+ {GPIOC_BASE, 1, ADC11, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D8/PC2 */
+ {GPIOC_BASE, 2, ADC12, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D9/PC3 */
+ {GPIOC_BASE, 3, ADC13, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D10/PC4 */
+ {GPIOC_BASE, 4, ADC14, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D11/PC5 */
+ {GPIOC_BASE, 5, ADC15, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D12/PC6 */
+ {GPIOC_BASE, 6, ADC_INVALID, TIMER8_CH1_CCR, EXTI_CONFIG_PORTC, TIMER8, 1},
+ /* D13/PC7 */
+ {GPIOC_BASE, 7, ADC_INVALID, TIMER8_CH2_CCR, EXTI_CONFIG_PORTC, TIMER8, 2},
+ /* D14/PC8 */
+ {GPIOC_BASE, 8, ADC_INVALID, TIMER8_CH3_CCR, EXTI_CONFIG_PORTC, TIMER8, 3},
+ /* D15/PC9 */
+ {GPIOC_BASE, 9, ADC_INVALID, TIMER8_CH4_CCR, EXTI_CONFIG_PORTC, TIMER8, 4},
+ /* D16/PC10 */
+ {GPIOC_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D17/PC11 */
+ {GPIOC_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D18/PC12 */
+ {GPIOC_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D19/PC13 */
+ {GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D20/PC14 */
+ {GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D21/PC15 */
+ {GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D22/PA8 */
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA, TIMER1, 1},
+ /* D23/PA9 */
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER1, 2},
+ /* D24/PA10 */
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1, 3},
+ /* D25/PB9 */
+ {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER4, 4},
- /* D15/PC0 */
- {GPIOC_BASE, 0, ADC10, TIMER_INVALID},
- /* D16/PC1 */
- {GPIOC_BASE, 1, ADC11, TIMER_INVALID},
- /* D17/PC2 */
- {GPIOC_BASE, 2, ADC12, TIMER_INVALID},
- /* D18/PC3 */
- {GPIOC_BASE, 3, ADC13, TIMER_INVALID},
- /* D19/PC4 */
- {GPIOC_BASE, 4, ADC14, TIMER_INVALID},
- /* D20/PC5 */
- {GPIOC_BASE, 5, ADC15, TIMER_INVALID},
+ /* Bottom header */
- /* External header */
+ /* D26/PD2 */
+ {GPIOD_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D27/PD3 */
+ {GPIOD_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D28/PD6 */
+ {GPIOD_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D29/PG11 */
+ {GPIOG_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D30/PG12 */
+ {GPIOG_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D31/PG13 */
+ {GPIOG_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D32/PG14 */
+ {GPIOG_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D33/PG8 */
+ {GPIOG_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D34/PG7 */
+ {GPIOG_BASE, 7, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D35/PG6 */
+ {GPIOG_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D36/PB5 */
+ {GPIOB_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D37/PB6 */
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
+ /* D38/PB7 */
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 2},
+ /* D39/PF6 */
+ {GPIOF_BASE, 6, ADC4, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D40/PF7 */
+ {GPIOF_BASE, 7, ADC5, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D41/PF8 */
+ {GPIOF_BASE, 8, ADC6, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D42/PF9 */
+ {GPIOF_BASE, 9, ADC7, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D43/PF10 */
+ {GPIOF_BASE, 10, ADC8, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D44/PF11 */
+ {GPIOF_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D45/PB1 */
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
+ /* D46/PB0 */
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
+ /* D47/PA0 */
+ {GPIOA_BASE, 0, ADC0, TIMER5_CH1_CCR, EXTI_CONFIG_PORTA, TIMER5, 1},
+ /* D48/PA1 */
+ {GPIOA_BASE, 1, ADC1, TIMER5_CH2_CCR, EXTI_CONFIG_PORTA, TIMER5, 2}, /* FIXME (?) what to do about D48--D50
+ also being TIMER2_CH[2,3,4]? */
+ /* D49/PA2 */
+ {GPIOA_BASE, 2, ADC2, TIMER5_CH3_CCR, EXTI_CONFIG_PORTA, TIMER5, 3},
+ /* D50/PA3 */
+ {GPIOA_BASE, 3, ADC3, TIMER5_CH4_CCR, EXTI_CONFIG_PORTA, TIMER5, 4},
+ /* D51/PA4 */
+ {GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D52/PA5 */
+ {GPIOA_BASE, 5, ADC5, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D53/PA6 */
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
+ /* D54/PA7 */
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2},
- /* D21/PC13 */
- {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID},
- /* D22/PC14 */
- {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID},
- /* D23/PC15 */
- {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID},
- /* D24/PB9 */
- {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR},
- /* D25/PD2 */
- {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID},
- /* D26/PC10 */
- {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID},
- /* D27/PB0 */
- {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR},
- /* D28/PB1 */
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR},
- /* D29/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID},
- /* D30/PB11 */
- {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID},
- /* D31/PB12 */
- {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID},
- /* D32/PB13 */
- {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID},
- /* D33/PB14 */
- {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID},
- /* D34/PB15 */
- {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID},
- /* D35/PC6 */
- {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID},
- /* D36/PC7 */
- {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID},
- /* D37/PC8 */
- {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID},
- /* PC9 (BUT) */
- {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID}
+ /* Right (triple) header */
+
+ /* D55/PF0 */
+ {GPIOF_BASE, 0, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D56/PD11 */
+ {GPIOD_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D57/PD14 */
+ {GPIOD_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D58/PF1 */
+ {GPIOF_BASE, 1, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D59/PD12 */
+ {GPIOD_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D60/PD15 */
+ {GPIOD_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D61/PF2 */
+ {GPIOF_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D62/PD13 */
+ {GPIOD_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D63/PD0 */
+ {GPIOD_BASE, 0, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D64/PF3 */
+ {GPIOF_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D65/PE3 */
+ {GPIOE_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D66/PD1 */
+ {GPIOD_BASE, 1, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D67/PF4 */
+ {GPIOF_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D68/PE4 */
+ {GPIOE_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D69/PE7 */
+ {GPIOE_BASE, 7, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D70/PF5 */
+ {GPIOF_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D71/PE5 */
+ {GPIOE_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D72/PE8 */
+ {GPIOE_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D73/PF12 */
+ {GPIOF_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D74/PE6 */
+ {GPIOE_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D75/PE9 */
+ {GPIOE_BASE, 9, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D76/PF13 */
+ {GPIOF_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D77/PE10 */
+ {GPIOE_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D78/PF14 */
+ {GPIOF_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D79/PG9 */
+ {GPIOG_BASE, 9, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D80/PE11 */
+ {GPIOE_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D81/PF15 */
+ {GPIOF_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTF, TIMER_INVALID, TIMER_INVALID},
+ /* D82/PG10 */
+ {GPIOG_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D83/PE12 */
+ {GPIOE_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D84/PG0 */
+ {GPIOG_BASE, 0, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D85/PD5 */
+ {GPIOD_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D86/PE13 */
+ {GPIOE_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D87/PG1 */
+ {GPIOG_BASE, 1, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D88/PD4 */
+ {GPIOD_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D89/PE14 */
+ {GPIOE_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D90/PG2 */
+ {GPIOG_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D91/PE1 */
+ {GPIOE_BASE, 1, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D92/PE15 */
+ {GPIOE_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D93/PG3 */
+ {GPIOG_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D94/PE0 */
+ {GPIOE_BASE, 0, ADC_INVALID, 0, EXTI_CONFIG_PORTE, TIMER_INVALID, TIMER_INVALID},
+ /* D95/PD8 */
+ {GPIOD_BASE, 8, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D96/PG4 */
+ {GPIOG_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D97/PD9 */
+ {GPIOD_BASE, 9, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
+ /* D98/PG5 */
+ {GPIOG_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTG, TIMER_INVALID, TIMER_INVALID},
+ /* D99/PD10 */
+ {GPIOD_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID}
};
- static __attribute__((unused)) ExtiInfo PIN_TO_EXTI_CHANNEL[NR_GPIO_PINS] =
- {
- /* D0/PA3 */
- {EXTI3, EXTI_CONFIG_PORTA},
- /* D1/PA2 */
- {EXTI2, EXTI_CONFIG_PORTA},
- /* D2/PA0 */
- {EXTI0, EXTI_CONFIG_PORTA},
- /* D3/PA1 */
- {EXTI1, EXTI_CONFIG_PORTA},
- /* D4/PB5 */
- {EXTI5, EXTI_CONFIG_PORTB},
- /* D5/PB6 */
- {EXTI6, EXTI_CONFIG_PORTB},
- /* D6/PA8 */
- {EXTI8, EXTI_CONFIG_PORTA},
- /* D7/PA9 */
- {EXTI9, EXTI_CONFIG_PORTA},
- /* D8/PA10 */
- {EXTI10, EXTI_CONFIG_PORTA},
- /* D9/PB7 */
- {EXTI7, EXTI_CONFIG_PORTB},
- /* D10/PA4 */
- {EXTI4, EXTI_CONFIG_PORTA},
- /* D11/PA7 */
- {EXTI7, EXTI_CONFIG_PORTA},
- /* D12/PA6 */
- {EXTI6, EXTI_CONFIG_PORTA},
- /* D13/PA5 */
- {EXTI5, EXTI_CONFIG_PORTA},
+ #define BOARD_INIT do { \
+ } while(0)
+
+#elif defined(BOARD_maple_mini)
+
+ #define CYCLES_PER_MICROSECOND 72
+ #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/PB11 */
+ {GPIOB_BASE, 11, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D1/PB10 */
+ {GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D2/PB2 */
+ {GPIOB_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D3/PB0 */
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
+ /* D4/PA7 */
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2},
+ /* D5/PA6 */
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
+ /* D6/PA5 */
+ {GPIOA_BASE, 5, ADC5, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D7/PA4 */
+ {GPIOA_BASE, 4, ADC4, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D8/PA3 */
+ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4},
+ /* D9/PA2 */
+ {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2, 3},
+ /* D10/PA1 */
+ {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
+ /* D11/PA0 */
+ {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1},
+ /* D12/PC15 */
+ {GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D13/PC14 */
+ {GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D14/PC13 */
+ {GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+ /* D15/PB7 */
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
+ /* D16/PB6 */
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
+ /* D17/PB5 */
+ {GPIOB_BASE, 5, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D18/PB4 */
+ {GPIOB_BASE, 4, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D19/PB3 */
+ {GPIOB_BASE, 3, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D20/PA15 */
+ {GPIOA_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D21/PA14 */
+ {GPIOA_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D22/PA13 */
+ {GPIOA_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D23/PA12 */
+ {GPIOA_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
+ /* D24/PA11 */
+ {GPIOA_BASE, 11, ADC_INVALID, TIMER1_CH4_CCR, EXTI_CONFIG_PORTA, TIMER1, 4},
+ /* D25/PA10 */
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1, 3},
+ /* D26/PA9 */
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
+ /* D27/PA8 */
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTB, TIMER1, 1},
+ /* D28/PB15 */
+ {GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D29/PB14 */
+ {GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D30/PB13 */
+ {GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D31/PB12 */
+ {GPIOB_BASE, 12, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ /* D32/PB8 */
+ {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3},
+ /* D33/PB1 */
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
};
-#endif
-#ifndef CYCLES_PER_MICROSECOND
+ /* 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)
+
+#else
+
#error "Board type has not been selected correctly."
+
#endif
#ifdef __cplusplus
diff --git a/wirish/comm/HardwareSPI.h b/wirish/comm/HardwareSPI.h
index 03d1ea1..7241d0b 100644
--- a/wirish/comm/HardwareSPI.h
+++ b/wirish/comm/HardwareSPI.h
@@ -29,18 +29,23 @@
#ifndef _HARDWARESPI_H_
#define _HARDWARESPI_H_
+/**
+ * Defines the possible SPI communication speeds.
+ */
typedef enum SPIFrequency {
- SPI_18MHZ = 0,
- SPI_9MHZ = 1,
- SPI_4_5MHZ = 2,
- SPI_2_25MHZ = 3,
- SPI_1_125MHZ = 4,
- SPI_562_500KHZ = 5,
- SPI_281_250KHZ = 6,
- SPI_140_625KHZ = 7,
- MAX_SPI_FREQS = 8,
+ SPI_18MHZ = 0, /**< 18 MHz */
+ SPI_9MHZ = 1, /**< 9 MHz */
+ SPI_4_5MHZ = 2, /**< 4.5 MHz */
+ SPI_2_25MHZ = 3, /**< 2.25 MHZ */
+ SPI_1_125MHZ = 4, /**< 1.125 MHz */
+ SPI_562_500KHZ = 5, /**< 562.500 KHz */
+ SPI_281_250KHZ = 6, /**< 281.250 KHz */
+ SPI_140_625KHZ = 7, /**< 140.625 KHz */
+ MAX_SPI_FREQS = 8, /**< The number of SPI frequencies. */
} SPIFrequency;
+/* Documented by hand in docs/source/lang/api/hardwarespi.rst; if you
+ make any changes, make sure to update this document. */
class HardwareSPI {
private:
uint32 spi_num;
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 17be49f..aad8aa7 100644
--- a/wirish/comm/HardwareSerial.h
+++ b/wirish/comm/HardwareSerial.h
@@ -31,8 +31,17 @@
#ifndef _HARDWARESERIAL_H_
#define _HARDWARESERIAL_H_
+#include "timers.h"
+
#include "Print.h"
+/* NB: this class documented "by hand" (i.e., not using Doxygen) in:
+
+ libmaple/docs/source/lang/serial.rst
+
+ If you alter the public HardwareSerial interface, you must update
+ the documentation accordingly. */
+
class HardwareSerial : public Print {
private:
uint8 usart_num;
@@ -40,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,
@@ -48,9 +57,9 @@ 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);
+ void begin(uint32 baud);
void end(void);
uint32 available(void);
uint8 read(void);
diff --git a/wirish/ext_interrupts.c b/wirish/ext_interrupts.c
index f02cdc5..dd7c1a8 100644
--- a/wirish/ext_interrupts.c
+++ b/wirish/ext_interrupts.c
@@ -32,17 +32,8 @@
#include "exti.h"
#include "ext_interrupts.h"
-/**
- * @brief Attach an interrupt handler to be triggered on a given
- * transition on the pin. Runs in interrupt context
- *
- * @param pin Maple pin number
- * @param handler Function to run upon external interrupt trigger.
- * @param mode Type of transition to trigger on, eg falling, rising, etc.
- *
- * @sideeffect Registers a handler
- */
-void attachInterrupt(uint8 pin, voidFuncPtr handler, uint32 mode) {
+/* Attach ISR handler on pin, triggering on the given mode. */
+void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
uint8 outMode;
/* Parameter checking */
@@ -65,6 +56,7 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, uint32 mode) {
outMode = EXTI_RISING_FALLING;
break;
default:
+ ASSERT(0);
return;
}
@@ -76,11 +68,7 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, uint32 mode) {
return;
}
-/**
- * @brief Disable an external interrupt
- * @param pin maple pin number
- * @sideeffect unregisters external interrupt handler
- */
+/* Disable any interrupts */
void detachInterrupt(uint8 pin) {
if (!(pin < NR_GPIO_PINS)) {
return;
diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h
index fef8c8f..304e267 100644
--- a/wirish/ext_interrupts.h
+++ b/wirish/ext_interrupts.h
@@ -22,6 +22,9 @@
* THE SOFTWARE.
*****************************************************************************/
+#include "libmaple_types.h"
+#include "nvic.h"
+
/**
* @file ext_interrupts.h
*
@@ -31,19 +34,76 @@
#ifndef _EXT_INTERRUPTS_H_
#define _EXT_INTERRUPTS_H_
-enum {
- RISING,
- FALLING,
- CHANGE
-};
+/**
+ * The kind of transition on an external pin which should trigger an
+ * interrupt.
+ */
+typedef enum ExtIntTriggerMode_ {
+ RISING, /**< To trigger an interrupt when the pin transitions LOW
+ to HIGH */
+ FALLING, /**< To trigger an interrupt when the pin transitions
+ HIGH to LOW */
+ CHANGE /**< To trigger an interrupt when the pin transitions from
+ LOW to HIGH or HIGH to LOW (i.e., when the pin
+ changes). */
+} ExtIntTriggerMode;
#ifdef __cplusplus
extern "C"{
#endif
-void attachInterrupt(uint8 pin, voidFuncPtr, uint32 mode);
+/**
+ * @brief Registers an interrupt handler on a pin.
+ *
+ * The interrupt will be triggered on a given transition on the pin,
+ * as specified by the mode parameter. The handler runs in interrupt
+ * context. The new handler will replace whatever handler is
+ * currently registered for the pin, if any.
+ *
+ * @param pin Maple pin number
+ * @param handler Function to run upon external interrupt trigger.
+ * The handler should take no arguments, and have void return type.
+ * @param mode Type of transition to trigger on, e.g. falling, rising, etc.
+ *
+ * @sideeffect Registers a handler
+ * @see detachInterrupt()
+ */
+void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode);
+
+/**
+ * @brief Disable any registered external interrupt.
+ * @param pin Maple pin number
+ * @sideeffect unregisters external interrupt handler
+ * @see attachInterrupt()
+ */
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 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 ALWAYS_INLINE void noInterrupts() {
+ nvic_globalirq_disable();
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/wirish/io.h b/wirish/io.h
index 647e79c..2d22dcd 100644
--- a/wirish/io.h
+++ b/wirish/io.h
@@ -33,59 +33,192 @@
#include "gpio.h"
#include "adc.h"
+#include "time.h"
#ifdef __cplusplus
extern "C"{
#endif
+/**
+ * Specifies a GPIO pin behavior.
+ *
+ * Each of the GPIO pins on a Maple board may be configured using
+ * pinMode() to behave in a number of ways: as a digital output pin,
+ * or as an analog input pin, etc., depending on the particular pin.
+ *
+ * This enum specifies the complete set of possible configurations;
+ * not every pin can have all of these modes. For example, on the
+ * Maple, pin 15 may be configured as INPUT_ANALOG, but not as PWM.
+ * See your device's silkscreen and and the GPIO documentation for
+ * more information.
+ *
+ * @see pinMode()
+ */
typedef enum WiringPinMode {
- OUTPUT,
- OUTPUT_OPEN_DRAIN,
- INPUT,
- INPUT_ANALOG,
- INPUT_PULLUP,
- INPUT_PULLDOWN,
- INPUT_FLOATING,
- PWM,
- PWM_OPEN_DRAIN,
+ OUTPUT, /**< Basic digital output: when the pin is HIGH, the
+ voltage is held at +3.3v (Vcc) and when it is LOW, it
+ is pulled down to ground. */
+
+ OUTPUT_OPEN_DRAIN, /**< In open drain mode, the pin indicates
+ "low" by accepting current flow to ground
+ and "high" by providing increased
+ impedance. An example use would be to
+ connect a pin to a bus line (which is pulled
+ up to a positive voltage by a separate
+ supply through a large resistor). When the
+ pin is high, not much current flows through
+ to ground and the line stays at positive
+ voltage; when the pin is low the bus
+ "drains" to ground with a small amount of
+ current constantly flowing through the large
+ resistor from the external supply. In this
+ mode no current is ever actually /sourced/
+ from the pin. */
+
+ INPUT, /**< Basic digital input. The pin voltage is sampled; when
+ it is closer to 3.3v (Vcc) the pin status is high, and
+ when it is closer to 0v (ground) it is low. If no
+ external circuit is pulling the pin voltage to high or
+ low, it will tend to randomly oscillate and be very
+ sensitive to noise (e.g., a breath of air across the pin
+ might cause the state to flip). */
+
+ INPUT_ANALOG, /**< This is a special mode for when the pin will be
+ used for analog (not digital) reads. Enables ADC
+ conversion to be performed on the voltage at the
+ pin. */
+
+ INPUT_PULLUP, /**< The state of the pin in this mode is reported
+ the same way as with INPUT, but the pin voltage
+ is gently "pulled up" towards +3.3v. This means
+ the state will be high unless an external device
+ is specifically pulling the pin down to ground,
+ in which case the "gentle" pull up will not
+ affect the state of the input. */
+
+ INPUT_PULLDOWN, /**< The state of the pin in this mode is reported
+ the same way as with INPUT, but the pin voltage
+ is gently "pulled down" towards 0v. This means
+ the state will be low unless an external device
+ is specifically pulling the pin up to 3.3v, in
+ which case the "gentle" pull down will not
+ affect the state of the input. */
+
+ INPUT_FLOATING, /**< Synonym for INPUT. */
+
+ PWM, /**< This is a special mode for when the pin will be used for
+ PWM output (a special case of digital output). */
+
+ PWM_OPEN_DRAIN, /**< Like PWM, except that instead of alternating
+ cycles of LOW and HIGH, the voltage on the pin
+ consists of alternating cycles of LOW and
+ floating (disconnected). */
} WiringPinMode;
+/**
+ * Configure behavior of a GPIO pin.
+ *
+ * @param pin Pin to configure. One of: 0-38 (pin numbers as labeled
+ * on silkscreen), or D0-D38 (symbols for same)
+ * @param mode Mode corresponding to desired pin behavior.
+ * @see WiringPinMode
+ */
+void pinMode(uint8 pin, WiringPinMode mode);
-/* Set pin to mode
- * pinMode(pin, mode):
- * pin -> {0-38, D0-D39, A0-16}
- * mode -> {
- * INPUT/INPUT_DIGITAL
- * INPUT_PULLUP
- * INPUT_PULLDOWN
- * INPUT_ANALOG
- * OUTPUT/OUTPUT_PP
- * OUTPUT_OPEN_DRAIN
- * }
+/**
+ * Writes a (digital) value to a pin. The pin must have its
+ * mode set to <code>OUTPUT</code> or <code>OUTPUT_OPEN_DRAIN</code>.
+ *
+ * @param pin Pin to write to. One of: 0-38 (pin numbers as labeled
+ * on silkscreen), or D0-D38 (symbols for same)
+ * @param value Either LOW (write a 0) or HIGH (write a 1).
+ * @see pinMode()
*/
-void pinMode(uint8, uint8);
-
-/*
- * Writes VALUE to digital pin[0-38]
- * digitalWrite(pin, value):
- * pin -> {0-38, D0-D39, A0-16}
- * value -> LOW, HIGH;
-*/
-void digitalWrite(uint8, uint8);
-
-/* Read a digital value from pin, the pin mode must be set to
- * {INPUT, INPUT_PULLUP, INPUT_PULLDOWN}
- * digitalRead(pin)
- * pin -> {0-38, D0-D39, A0-16}
+void digitalWrite(uint8 pin, uint8 value);
+
+/**
+ * Read a digital value from a pin. The pin must have its mode set to
+ * one of INPUT, INPUT_PULLUP, and INPUT_PULLDOWN.
+ *
+ * @param pin Pin to read from. One of: 0-38 (pin numbers as labeled
+ * on silkscreen), or D0-D38 (symbols for same)
+ * @return LOW or HIGH.
+ * @see pinMode()
*/
-uint32 digitalRead(uint8);
+uint32 digitalRead(uint8 pin);
+
+/**
+ * Read an analog value from pin. This function blocks during ADC
+ * conversion, and has 12 bits of resolution. The pin must have its
+ * mode set to INPUT_ANALOG. Ignoring function call overhead,
+ * conversion time is 55.5 cycles.
+ *
+ * @param pin Pin to read from. One of: 0, 1, 2, 3, 10, 11, 12, 13,
+ * 15, 16, 17, 18, 19, 20, 27, 28.
+
+ * @return ADC-converted voltage, in the range 0--4095, inclusive
+ * (i.e. a 12-bit ADC conversion).
-/* Read an analog value from pin, the pin mode must be set
- * to INPUT_ANALOG
- * analogRead(pin)
- * pin -> {A0-A16}
+ * @see pinMode()
+ */
+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()
*/
-uint32 analogRead(uint8);
+uint8 waitForButtonPress(uint32 timeout_millis);
#ifdef __cplusplus
} // extern "C"
diff --git a/wirish/pwm.c b/wirish/pwm.c
index 2f555ab..072e4cd 100644
--- a/wirish/pwm.c
+++ b/wirish/pwm.c
@@ -38,13 +38,11 @@ void pwmWrite(uint8 pin, uint16 duty_cycle) {
return;
}
- ccr = PIN_MAP[pin].timer_channel;
+ ccr = PIN_MAP[pin].timer_ccr;
- if (ccr == TIMER_INVALID) {
+ if (ccr == 0) {
return;
}
timer_pwm_write_ccr(ccr, duty_cycle);
}
-
-
diff --git a/wirish/pwm.h b/wirish/pwm.h
index fe170cd..d0bc9e0 100644
--- a/wirish/pwm.h
+++ b/wirish/pwm.h
@@ -35,8 +35,20 @@
extern "C"{
#endif
+/**
+ * As a convenience, analogWrite is an alias of pwmWrite to ease
+ * porting Arduino code. However, period and duty will have to be
+ * recalibrated.
+ */
#define analogWrite pwmWrite
-void pwmWrite(uint8, uint16);
+
+/**
+ * Set the PWM duty on the given pin.
+ *
+ * User code is expected to determine and honor the maximum value
+ * (based on the configured period).
+ */
+void pwmWrite(uint8 pin, uint16 duty_cycle);
#ifdef __cplusplus
}
diff --git a/wirish/time.c b/wirish/time.c
index 3a48197..c0a0649 100644
--- a/wirish/time.c
+++ b/wirish/time.c
@@ -43,7 +43,6 @@ void delayMicroseconds(uint32 us) {
/* fudge for function call overhead */
us--;
- int x = 4;
asm volatile(" mov r0, %[us] \n\t"
"1: subs r0, #1 \n\t"
" bhi 1b \n\t"
diff --git a/wirish/time.h b/wirish/time.h
index 2a561d3..8d3d074 100644
--- a/wirish/time.h
+++ b/wirish/time.h
@@ -23,7 +23,8 @@
*****************************************************************************/
/**
- * @brief Timing and delay functions.
+ * @file time.h
+ * @brief Timing and delay functions.
*/
#ifndef _TIME_H
@@ -40,12 +41,20 @@ extern "C"{
#define US_PER_MS 1000
-/* time in milliseconds since boot */
+/**
+ * Returns time (in milliseconds) since the beginning of program
+ * execution. On overflow, restarts at 0.
+ * @see micros()
+ */
static inline uint32 millis(void) {
return systick_timer_millis;
}
-/* Time in microseconds since boot */
+/**
+ * Returns time (in microseconds) since the beginning of program
+ * execution. On overflow, restarts at 0.
+ * @see millis()
+ */
static inline uint32 micros(void) {
uint32 ms;
uint32 cycle_cnt;
@@ -58,15 +67,36 @@ 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;
}
+/**
+ * Delay for at least the given number of milliseconds.
+ *
+ * Interrupts, etc. may cause the actual number of milliseconds to
+ * exceed ms. However, this function will return no less than ms
+ * milliseconds from the time it is called.
+ *
+ * @param ms the number of milliseconds to delay.
+ * @see delayMicroseconds()
+ */
void delay(unsigned long ms);
+
+/**
+ * Delay for at least the given number of microseconds.
+ *
+ * Interrupts, etc. may cause the actual number of microseconds to
+ * exceed us. However, this function will return no less than us
+ * microseconds from the time it is called.
+ *
+ * @param us the number of microseconds to delay.
+ * @see delay()
+ */
void delayMicroseconds(uint32 us);
#ifdef __cplusplus
diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp
index 405220a..e2cdee3 100644
--- a/wirish/usb_serial.cpp
+++ b/wirish/usb_serial.cpp
@@ -101,17 +101,27 @@ uint32 USBSerial::available(void) {
return usbBytesAvailable();
}
+/* blocks forever until len_bytes is received */
uint32 USBSerial::read(void *buf, uint32 len) {
if (!buf) {
return 0;
}
- return usbReceiveBytes((uint8*)buf, len);
+ uint32 bytes_in = 0;
+ while (len > 0) {
+ uint32 new_bytes = usbReceiveBytes((uint8*)((uint8*)buf+bytes_in), len);
+ len -= new_bytes;
+ bytes_in += new_bytes;
+ }
+
+ return len;
}
+/* blocks forever until 1 byte is received */
uint8 USBSerial::read(void) {
uint8 ch;
- usbReceiveBytes(&ch, 1);
+
+ while (usbReceiveBytes(&ch, 1) == 0);
return ch;
}
@@ -119,10 +129,12 @@ uint8 USBSerial::pending(void) {
return usbGetPending();
}
+// TODO deprecate the crap out of this
uint8 USBSerial::getDTR(void) {
return usbGetDTR();
}
+// TODO deprecate the crap out of this
uint8 USBSerial::getRTS(void) {
return usbGetRTS();
}
diff --git a/wirish/wirish.c b/wirish/wirish.c
index 89adc1e..5935f95 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.h b/wirish/wirish.h
index c1c46cb..311c74f 100644
--- a/wirish/wirish.h
+++ b/wirish/wirish.h
@@ -62,8 +62,8 @@ extern "C"{
#define LSBFIRST 0
#define MSBFIRST 1
-#define lowByte(w) ((w) & 0xff)
-#define highByte(w) ((w) >> 8)
+#define lowByte(w) ((w) & 0xFF)
+#define highByte(w) (((w) >> 8) & 0xFF)
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.c
index f4868da..6f9906d 100644
--- a/wirish/wirish_digital.c
+++ b/wirish/wirish_digital.c
@@ -22,8 +22,8 @@
* THE SOFTWARE.
*****************************************************************************/
-/**
- * @brief Arduino-compatible digital I/O implementation.
+/*
+ * Arduino-compatible digital I/O implementation.
*/
#include "wirish.h"
@@ -31,6 +31,7 @@
void pinMode(uint8 pin, WiringPinMode mode) {
uint8 outputMode;
+ boolean pwm = false;
if (pin >= NR_GPIO_PINS) {
return;
@@ -58,9 +59,11 @@ void pinMode(uint8 pin, WiringPinMode mode) {
break;
case PWM:
outputMode = GPIO_MODE_AF_OUTPUT_PP;
+ pwm = true;
break;
case PWM_OPEN_DRAIN:
outputMode = GPIO_MODE_AF_OUTPUT_OD;
+ pwm = true;
break;
default:
ASSERT(0);
@@ -68,6 +71,20 @@ void pinMode(uint8 pin, WiringPinMode mode) {
}
gpio_set_mode(PIN_MAP[pin].port, PIN_MAP[pin].pin, outputMode);
+
+ if (PIN_MAP[pin].timer_num != TIMER_INVALID) {
+ /* enable/disable timer channels if we're switching into or
+ out of pwm */
+ if (pwm) {
+ timer_set_mode(PIN_MAP[pin].timer_num,
+ PIN_MAP[pin].timer_chan,
+ TIMER_PWM);
+ } else {
+ timer_set_mode(PIN_MAP[pin].timer_num,
+ PIN_MAP[pin].timer_chan,
+ TIMER_DISABLED);
+ }
+ }
}
@@ -86,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 4543c1b..14614ba 100644
--- a/wirish/wirish_math.h
+++ b/wirish/wirish_math.h
@@ -22,6 +22,11 @@
* THE SOFTWARE.
*****************************************************************************/
+/**
+ * @file wirish_math.h
+ * @brief Includes cmath; provides Arduino-compatible math routines.
+ */
+
#ifndef _WIRING_MATH_H_
#define _WIRING_MATH_H_
@@ -29,10 +34,56 @@
#ifdef __cplusplus
-void randomSeed(unsigned int);
-long random(long);
-long random(long, long);
-long map(long, long, long, long, long);
+/**
+ * @brief Initialize the pseudo-random number generator.
+ * @param seed the number used to initialize the seed; cannot be zero.
+ */
+void randomSeed(unsigned int seed);
+
+/**
+ * @brief Generate a pseudo-random number with upper bound.
+ * @param max An upper bound on the returned value, exclusive.
+ * @return A pseudo-random number in the range [0,max).
+ * @see randomSeed()
+ */
+long random(long max);
+
+/**
+ * @brief Generate a pseudo-random number with lower and upper bounds.
+ * @param min Lower bound on the returned value, inclusive.
+ * @param max Upper bound on the returned value, exclusive.
+ * @return A pseudo-random number in the range [min, max).
+ * @see randomSeed()
+ */
+long random(long min, long max);
+
+/**
+ * @brief Remap a number from one range to another.
+ *
+ * That is, a value equal to fromStart gets mapped to toStart, a value
+ * of fromEnd to toEnd, and other values are mapped proportionately.
+ *
+ * Does not constrain value to lie within [fromStart, fromEnd].
+ *
+ * If a "start" value is larger than its corresponding "end", the
+ * ranges are reversed, so map(n, 1, 10, 10, 1) would reverse the
+ * range [1,10].
+ *
+ * Negative numbers may appear as any argument.
+ *
+ * @param value the value to map.
+ * @param fromStart the beginning of the value's current range.
+ * @param fromEnd the end of the value's current range.
+ * @param toStart the beginning of the value's mapped range.
+ * @param toEnd the end of the value's mapped range.
+ * @return the mapped value.
+ */
+/* TODO: profile code bloat due to inlining this */
+inline long map(long value, long fromStart, long fromEnd,
+ long toStart, long toEnd) {
+ return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) +
+ toStart;
+}
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
@@ -56,4 +107,48 @@ long map(long, long, long, long, long);
#endif
+/* Following are duplicate declarations (with Doxygen comments) for
+ * some of the math.h functions; this is for the convenience of the
+ * Sphinx docs.
+ */
+
+/**
+ * Compute the cosine of an angle, in radians.
+ * @param x The radian measure of the angle.
+ * @return The cosine of x. This value will be between -1 and 1.
+ */
+double cos(double x);
+
+/**
+ * Compute the sine of an angle, in radians.
+ * @param x The radian measure of the angle.
+ * @return The sine of x. This value will be between -1 and 1.
+ */
+double sin(double x);
+
+/**
+ * Compute the tangent of an angle, in radians.
+ * @param x The radian measure of the angle.
+ * @return The tangent of x. There are no limits on the return value
+ * of this function.
+ */
+double tan(double x);
+
+/**
+ * Compute the square root of a number.
+ * @param x The number whose square root to find. This value cannot
+ * be negative.
+ * @return The square root of x. The return value is never negative.
+ */
+double sqrt(double x);
+
+/**
+ * Compute an exponentiation.
+ * @param x the base. This value cannot be zero if y <= 0. This value
+ * cannot be negative if y is not an integral value.
+ * @param y the exponent.
+ * @return x raised to the power y.
+ */
+double pow(double x, double y);
+
#endif