aboutsummaryrefslogtreecommitdiffstats
path: root/wirish
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2011-05-09 16:43:27 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2011-05-09 16:49:08 -0400
commit19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3 (patch)
treea43f7e0fb3650ca54f245b750a078a0e8c356504 /wirish
parent868fb1c273e562a1140abfa948022c9d4f55bccf (diff)
parent1e2e177f6dae62e040c674b617744c73be187062 (diff)
downloadlibrambutan-19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3.tar.gz
librambutan-19ea6ba4ea3f1ecb9830cf4d3e1366513f4f96e3.zip
Merge branch 'refactor'
This merges the libmaple refactor work into master. The contents of libmaple proper (/libmaple/) are almost completely incompatible with previous APIs in master. See /docs/source/libmaple/overview.rst for more information on the new design. Wirish incompatibilities are limited to the HardwareTimer class; however, there are several new deprecations, most likely to be removed in 0.1.0.
Diffstat (limited to 'wirish')
-rw-r--r--wirish/HardwareTimer.cpp228
-rw-r--r--wirish/HardwareTimer.h432
-rw-r--r--wirish/Print.cpp302
-rw-r--r--wirish/Print.h87
-rw-r--r--wirish/boards.cpp160
-rw-r--r--wirish/boards.h557
-rw-r--r--wirish/boards/maple.cpp115
-rw-r--r--wirish/boards/maple.h91
-rw-r--r--wirish/boards/maple_RET6.cpp112
-rw-r--r--wirish/boards/maple_RET6.h79
-rw-r--r--wirish/boards/maple_mini.cpp103
-rw-r--r--wirish/boards/maple_mini.h78
-rw-r--r--wirish/boards/maple_native.cpp199
-rw-r--r--wirish/boards/maple_native.h85
-rw-r--r--wirish/comm/HardwareSPI.cpp322
-rw-r--r--wirish/comm/HardwareSPI.h178
-rw-r--r--wirish/comm/HardwareSerial.cpp81
-rw-r--r--wirish/comm/HardwareSerial.h50
-rw-r--r--wirish/ext_interrupts.cpp (renamed from wirish/ext_interrupts.c)67
-rw-r--r--wirish/ext_interrupts.h17
-rw-r--r--wirish/io.h73
-rw-r--r--wirish/main.cxx9
-rw-r--r--wirish/pwm.cpp (renamed from wirish/pwm.c)22
-rw-r--r--wirish/pwm.h16
-rw-r--r--wirish/rules.mk42
-rw-r--r--wirish/usb_serial.cpp115
-rw-r--r--wirish/usb_serial.h8
-rw-r--r--wirish/wirish.c82
-rw-r--r--wirish/wirish.h22
-rw-r--r--wirish/wirish_analog.cpp (renamed from wirish/wirish_analog.c)9
-rw-r--r--wirish/wirish_debug.h54
-rw-r--r--wirish/wirish_digital.cpp (renamed from wirish/wirish_digital.c)61
-rw-r--r--wirish/wirish_math.h11
-rw-r--r--wirish/wirish_shift.cpp (renamed from wirish/wirish_shift.c)0
-rw-r--r--wirish/wirish_time.cpp (renamed from wirish/time.c)15
-rw-r--r--wirish/wirish_time.h (renamed from wirish/time.h)28
-rw-r--r--wirish/wirish_types.h65
37 files changed, 2386 insertions, 1589 deletions
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
index 354663e..d0e32c3 100644
--- a/wirish/HardwareTimer.cpp
+++ b/wirish/HardwareTimer.cpp
@@ -22,205 +22,125 @@
* THE SOFTWARE.
*****************************************************************************/
-/*
- * wirish timer class to manage the four 16-bit timer peripherals
- */
-
-#include "wirish.h"
#include "HardwareTimer.h"
+#include "boards.h" // for CYCLES_PER_MICROSECOND
+#include "wirish_math.h"
-HardwareTimer::HardwareTimer(timer_dev_num timerNum) {
- ASSERT(timerNum != TIMER_INVALID);
+// TODO [0.1.0] Remove deprecated pieces
- this->timerNum = timerNum;
-}
+#ifdef STM32_MEDIUM_DENSITY
+#define NR_TIMERS 4
+#elif defined(STM32_HIGH_DENSITY)
+#define NR_TIMERS 8
+#else
+#error "Unsupported density"
+#endif
-void HardwareTimer::resume(void) {
- timer_resume(this->timerNum);
+#define MAX_RELOAD ((1 << 16) - 1)
+
+HardwareTimer::HardwareTimer(uint8 timerNum) {
+ if (timerNum > NR_TIMERS) {
+ ASSERT(0);
+ }
+ timer_dev *devs[] = {
+ TIMER1,
+ TIMER2,
+ TIMER3,
+ TIMER4,
+#ifdef STM32_HIGH_DENSITY
+ TIMER5,
+ TIMER6,
+ TIMER7,
+ TIMER8,
+#endif
+ };
+ this->dev = devs[timerNum - 1];
}
void HardwareTimer::pause(void) {
- timer_pause(this->timerNum);
+ timer_pause(this->dev);
}
-uint16 HardwareTimer::getPrescaleFactor(void) {
- return timer_get_prescaler(this->timerNum) + 1;
+void HardwareTimer::resume(void) {
+ timer_resume(this->dev);
+}
+
+uint32 HardwareTimer::getPrescaleFactor(void) {
+ return timer_get_prescaler(this->dev) + 1;
}
-void HardwareTimer::setPrescaleFactor(uint16 factor) {
- // The prescaler register is zero-indexed
- timer_set_prescaler(this->timerNum, factor-1);
+void HardwareTimer::setPrescaleFactor(uint32 factor) {
+ timer_set_prescaler(this->dev, (uint16)(factor - 1));
}
uint16 HardwareTimer::getOverflow() {
- return timer_get_reload(this->timerNum);
+ return timer_get_reload(this->dev);
}
void HardwareTimer::setOverflow(uint16 val) {
- timer_set_reload(this->timerNum, val);
+ timer_set_reload(this->dev, val);
}
uint16 HardwareTimer::getCount(void) {
- return timer_get_count(this->timerNum);
+ return timer_get_count(this->dev);
}
void HardwareTimer::setCount(uint16 val) {
uint16 ovf = this->getOverflow();
- timer_set_count(this->timerNum, min(val, ovf));
+ timer_set_count(this->dev, min(val, ovf));
}
+// FIXME [0.0.10 beta] test!
uint16 HardwareTimer::setPeriod(uint32 microseconds) {
// Not the best way to handle this edge case?
- if(!microseconds) {
- setPrescaleFactor(1);
- setOverflow(1);
+ if (!microseconds) {
+ this->setPrescaleFactor(1);
+ this->setOverflow(1);
return this->getOverflow();
}
- uint32 cycles = microseconds * CYCLES_PER_MICROSECOND;
-
- // 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((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);
-}
-
-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);
+ uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND;
+ uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD);
+ uint16 overflow = (uint16)round(period_cyc / prescaler);
+ this->setPrescaleFactor(prescaler);
+ this->setOverflow(overflow);
+ return overflow;
}
-uint16 HardwareTimer::getCompare3() {
- return this->getCompare(3);
+void HardwareTimer::setMode(int channel, timer_mode mode) {
+ timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode);
}
-uint16 HardwareTimer::getCompare4() {
- return this->getCompare(4);
+uint16 HardwareTimer::getCompare(int channel) {
+ return timer_get_compare(this->dev, (uint8)channel);
}
-inline void HardwareTimer::setCompare(int channel, uint16 val) {
+void HardwareTimer::setCompare(int channel, uint16 val) {
uint16 ovf = this->getOverflow();
- timer_set_compare_value(this->timerNum, channel, min(val, ovf));
+ timer_set_compare(this->dev, (uint8)channel, min(val, ovf));
}
-void HardwareTimer::setCompare1(uint16 val) {
- this->setCompare(1, val);
+void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) {
+ timer_attach_interrupt(this->dev, (uint8)channel, handler);
}
-void HardwareTimer::setCompare2(uint16 val) {
- this->setCompare(2, val);
+void HardwareTimer::detachInterrupt(int channel) {
+ timer_detach_interrupt(this->dev, (uint8)channel);
}
-void HardwareTimer::setCompare3(uint16 val) {
- this->setCompare(3, val);
+void HardwareTimer::refresh(void) {
+ timer_generate_update(this->dev);
}
-void HardwareTimer::setCompare4(uint16 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) {
- this->attachInterrupt(1, handler);
-}
-
-void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) {
- this->attachInterrupt(2, handler);
-}
-
-void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) {
- this->attachInterrupt(3, handler);
-}
-
-void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) {
- this->attachInterrupt(4, handler);
-}
-
-inline void HardwareTimer::detachInterrupt(int channel) {
- timer_detach_interrupt(this->timerNum, channel);
-}
-
-void HardwareTimer::detachCompare1Interrupt(void) {
- this->detachInterrupt(1);
-}
-
-void HardwareTimer::detachCompare2Interrupt(void) {
- this->detachInterrupt(2);
-}
-
-void HardwareTimer::detachCompare3Interrupt(void) {
- this->detachInterrupt(3);
-}
-
-void HardwareTimer::detachCompare4Interrupt(void) {
- this->detachInterrupt(4);
-}
+/* -- Deprecated predefined instances -------------------------------------- */
-void HardwareTimer::generateUpdate(void) {
- timer_generate_update(this->timerNum);
-}
-
-
-HardwareTimer Timer1(TIMER1);
-HardwareTimer Timer2(TIMER2);
-HardwareTimer Timer3(TIMER3);
-HardwareTimer Timer4(TIMER4);
-#if NR_TIMERS >= 8
-HardwareTimer Timer5(TIMER5); // High-density devices only
-HardwareTimer Timer8(TIMER8); // High-density devices only
+HardwareTimer Timer1(1);
+HardwareTimer Timer2(2);
+HardwareTimer Timer3(3);
+HardwareTimer Timer4(4);
+#ifdef STM32_HIGH_DENSITY
+HardwareTimer Timer5(5);
+HardwareTimer Timer6(6);
+HardwareTimer Timer7(7);
+HardwareTimer Timer8(8);
#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 4034b1f..fd8ca9a 100644
--- a/wirish/HardwareTimer.h
+++ b/wirish/HardwareTimer.h
@@ -23,66 +23,45 @@
*****************************************************************************/
/**
- * @brief wirish timer class to manage the four 16-bit timer peripherals
+ * @brief Wirish timer class.
*/
#ifndef _HARDWARETIMER_H_
#define _HARDWARETIMER_H_
-#include "timers.h"
+// TODO [0.1.0] Remove deprecated pieces, pick a better API
+
+#include "timer.h"
+
+/** Timer mode. */
+typedef timer_mode TimerMode;
+
+/** @brief Deprecated; use TIMER_OUTPUT_COMPARE instead. */
+#define TIMER_OUTPUTCOMPARE TIMER_OUTPUT_COMPARE
/**
- * 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.
+ * @brief Interface to one of the 16-bit timer peripherals.
*/
class HardwareTimer {
- private:
- timer_dev_num timerNum;
-
- public:
- HardwareTimer(timer_dev_num timer_num);
+private:
+ timer_dev *dev;
+public:
/**
- * Return this timer's device number. For example,
- * Timer1.getTimerNum() == TIMER1
+ * @brief Construct a new HardwareTimer instance.
+ * @param timerNum number of the timer to control.
*/
- timer_dev_num getTimerNum() { return timerNum; }
+ HardwareTimer(uint8 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.
+ * @brief Stop the counter, without affecting its configuration.
*
* @see HardwareTimer::resume()
*/
void pause(void);
/**
- * Resume a paused timer, without affecting its configuration.
+ * @brief Resume a paused timer, without affecting its configuration.
*
* The timer will resume counting and firing interrupts as
* appropriate.
@@ -97,66 +76,51 @@ class HardwareTimer {
void resume(void);
/**
- * Returns the timer's prescale factor.
+ * @brief Get the timer's prescale factor.
+ * @return Timer prescaler, from 1 to 65,536.
* @see HardwareTimer::setPrescaleFactor()
*/
- uint16 getPrescaleFactor();
+ uint32 getPrescaleFactor();
/**
- * Set the timer's prescale factor.
+ * @brief Set the timer's prescale factor.
*
- * The prescaler acts as a clock divider to slow down the rate at
- * which the counter increments.
+ * The new value won't take effect until the next time the counter
+ * overflows. You can force the counter to reset using
+ * HardwareTimer::refresh().
*
- * 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()
+ * @param factor The new prescale value to set, from 1 to 65,536.
+ * @see HardwareTimer::refresh()
*/
- void setPrescaleFactor(uint16 factor);
+ void setPrescaleFactor(uint32 factor);
/**
- * Gets the timer overflow value.
+ * @brief Get the timer overflow value.
* @see HardwareTimer::setOverflow()
*/
uint16 getOverflow();
/**
- * Sets the timer overflow (or "reload") value.
+ * @brief Set 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.
+ * The new value won't take effect until the next time the counter
+ * overflows. You can force the counter to reset using
+ * HardwareTimer::refresh().
*
* @param val The new overflow value to set
+ * @see HardwareTimer::refresh()
*/
void setOverflow(uint16 val);
/**
- * Retrieve the current timer count.
+ * @brief Get 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
- * calling this method, so using it is not a robust way to get
- * multiple timers to share a count value.
+ * @brief Set the current timer count.
*
* @param val The new count value to set. If this value exceeds
* the timer's overflow value, it is truncated to the
@@ -165,143 +129,50 @@ class HardwareTimer {
void setCount(uint16 val);
/**
- * Configure the prescaler and overflow values to generate a timer
+ * @brief Set the timer's period in microseconds.
+ *
+ * Configures 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).
+ * @param microseconds The desired period of the timer. This must be
+ * greater than zero.
+ * @return The new overflow value.
*/
uint16 setPeriod(uint32 microseconds);
/**
- * Set the given channel of this timer to the given mode.
- *
+ * @brief Configure a timer channel's 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);
+ void setMode(int channel, timer_mode mode);
/**
- * Gets the compare value for the given channel.
+ * @brief Get 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.
+ * @brief Set the compare value for the given channel.
*
* @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 timer_mode
+ * @see HardwareTimer::setMode()
* @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
+ * @brief Attach an interrupt handler to the given channel.
*
- * 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.
+ * This interrupt handler will be called when the timer's counter
+ * reaches the given channel compare value.
*
* @param channel the channel to attach the ISR to, from 1 to 4.
* @param handler The ISR to attach to the given channel.
@@ -310,32 +181,10 @@ class HardwareTimer {
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.
+ * @brief 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()
@@ -343,71 +192,138 @@ class HardwareTimer {
void detachInterrupt(int channel);
/**
- * Equivalent to detachInterrupt(1).
- * @see HardwareTimer::detachInterrupt()
+ * @brief Reset the counter, and update the prescaler and overflow
+ * values.
+ *
+ * This will reset the counter to 0 in upcounting mode (the
+ * default). It will also update the timer's prescaler and
+ * overflow, if you have set them up to be changed using
+ * HardwareTimer::setPrescaleFactor() or
+ * HardwareTimer::setOverflow().
+ *
+ * @see HardwareTimer::setPrescaleFactor()
+ * @see HardwareTimer::setOverflow()
*/
- void detachCompare1Interrupt(void);
+ void refresh(void);
- /**
- * Equivalent to detachInterrupt(2).
- * @see HardwareTimer::detachInterrupt()
- */
- void detachCompare2Interrupt(void);
+ /* -- Deprecated methods ----------------------------------------------- */
- /**
- * Equivalent to detachInterrupt(3).
- * @see HardwareTimer::detachInterrupt()
- */
- void detachCompare3Interrupt(void);
+ /** @brief Deprecated; use setMode(channel, mode) instead. */
+ void setChannelMode(int channel, timer_mode mode) {
+ setMode(channel, mode);
+ }
- /**
- * Equivalent to detachInterrupt(4).
- * @see HardwareTimer::detachInterrupt()
- */
- void detachCompare4Interrupt(void);
+ /** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */
+ void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); }
- /**
- * 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);
+ /** @brief Deprecated; use setMode(TIMER_CH2, mode) instead. */
+ void setChannel2Mode(timer_mode mode) { setMode(TIMER_CH2, mode); }
+
+ /** @brief Deprecated; use setMode(TIMER_CH3, mode) instead. */
+ void setChannel3Mode(timer_mode mode) { setMode(TIMER_CH3, mode); }
+
+ /** @brief Deprecated; use setMode(TIMER_CH4, mode) instead. */
+ void setChannel4Mode(timer_mode mode) { setMode(TIMER_CH4, mode); }
+
+ /** @brief Deprecated; use return getCompare(TIMER_CH1) instead. */
+ uint16 getCompare1() { return getCompare(TIMER_CH1); }
+
+ /** @brief Deprecated; use return getCompare(TIMER_CH2) instead. */
+ uint16 getCompare2() { return getCompare(TIMER_CH2); }
+
+ /** @brief Deprecated; use return getCompare(TIMER_CH3) instead. */
+ uint16 getCompare3() { return getCompare(TIMER_CH3); }
+
+ /** @brief Deprecated; use return getCompare(TIMER_CH4) instead. */
+ uint16 getCompare4() { return getCompare(TIMER_CH4); }
+
+ /** @brief Deprecated; use setCompare(TIMER_CH1, compare) instead. */
+ void setCompare1(uint16 compare) { setCompare(TIMER_CH1, compare); }
+
+ /** @brief Deprecated; use setCompare(TIMER_CH2, compare) instead. */
+ void setCompare2(uint16 compare) { setCompare(TIMER_CH2, compare); }
+
+ /** @brief Deprecated; use setCompare(TIMER_CH3, compare) instead. */
+ void setCompare3(uint16 compare) { setCompare(TIMER_CH3, compare); }
+
+ /** @brief Deprecated; use setCompare(TIMER_CH4, compare) instead. */
+ void setCompare4(uint16 compare) { setCompare(TIMER_CH4, compare); }
+
+ /** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */
+ void attachCompare1Interrupt(voidFuncPtr handler) {
+ attachInterrupt(TIMER_CH1, handler);
+ }
+
+ /** @brief Deprecated; use attachInterrupt(TIMER_CH2, handler) instead. */
+ void attachCompare2Interrupt(voidFuncPtr handler) {
+ attachInterrupt(TIMER_CH2, handler);
+ }
+
+ /** @brief Deprecated; use attachInterrupt(TIMER_CH3, handler) instead. */
+ void attachCompare3Interrupt(voidFuncPtr handler) {
+ attachInterrupt(TIMER_CH3, handler);
+ }
+
+ /** @brief Deprecated; use attachInterrupt(TIMER_CH4, handler) instead. */
+ void attachCompare4Interrupt(voidFuncPtr handler) {
+ attachInterrupt(TIMER_CH4, handler);
+ }
+
+ /** @brief Deprecated; use detachInterrupt(TIMER_CH1) instead. */
+ void detachCompare1Interrupt(void) { detachInterrupt(TIMER_CH1); }
+
+ /** @brief Deprecated; use detachInterrupt(TIMER_CH2) instead. */
+ void detachCompare2Interrupt(void) { detachInterrupt(TIMER_CH2); }
+
+ /** @brief Deprecated; use detachInterrupt(TIMER_CH3) instead. */
+ void detachCompare3Interrupt(void) { detachInterrupt(TIMER_CH3); }
+
+ /** @brief Deprecated; use detachInterrupt(TIMER_CH4) instead. */
+ void detachCompare4Interrupt(void) { detachInterrupt(TIMER_CH4); }
+
+ /** @brief Deprecated; use refresh() instead. */
+ void generateUpdate(void) { refresh(); }
};
-/** Pre-instantiated timer for use by user code. */
+/* -- The rest of this file is deprecated. --------------------------------- */
+
+/**
+ * @brief Deprecated.
+ *
+ * Pre-instantiated timer.
+ */
extern HardwareTimer Timer1;
-/** Pre-instantiated timer for use by user code. */
+/**
+ * @brief Deprecated.
+ *
+ * Pre-instantiated timer.
+ */
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.
+ * @brief Deprecated.
*
- * 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.
+ * Pre-instantiated timer.
+ */
+extern HardwareTimer Timer3;
+/**
+ * @brief Deprecated.
*
- * @param timerNum the timer device number, e.g. TIMER1.
+ * Pre-instantiated timer.
+ */
+extern HardwareTimer Timer4;
+#ifdef STM32_HIGH_DENSITY
+/**
+ * @brief Deprecated.
*
- * @return Pointer to the HardwareTimer instance corresponding to the
- * given timer device number. If timerNum is TIMER_INVALID, returns a
- * null pointer.
+ * Pre-instantiated timer.
+ */
+extern HardwareTimer Timer5;
+/**
+ * @brief Deprecated.
*
- * @see timer_dev_num
+ * Pre-instantiated timer.
*/
-HardwareTimer* getTimer(timer_dev_num timerNum);
-
+extern HardwareTimer Timer8;
#endif
+#endif
diff --git a/wirish/Print.cpp b/wirish/Print.cpp
index 9c52321..9130c9c 100644
--- a/wirish/Print.cpp
+++ b/wirish/Print.cpp
@@ -1,127 +1,121 @@
-/******************************************************************************
- * The MIT License
+/*
+ * Print.cpp - Base class that provides print() and println()
+ * Copyright (c) 2008 David A. Mellis. All right reserved.
*
- * Copyright (c) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 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.
- *****************************************************************************/
+ * Modified 23 November 2006 by David A. Mellis
+ * Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
+ */
#include "Print.h"
-#include <cstdio>
-#include <climits>
-#include <cstring>
-
-// We'll allocate character buffers of size INT_BUF_SIZE to hold the
-// string representations of numbers; this value ensures that they're
-// big enough to accomodate the biggest integral value + null byte.
-//
-// E.g., consider -(2^63-1) = -9223372036854775807, which is 20
-// characters long, including the minus sign. The other edge cases
-// are similar.
-//
-// (Nonetheless, use snprintf everywhere, just in case of error).
-#define INT_BUF_SIZE 21
-
-// An IEEE-754 double buys you about 16 digits of precision; there's
-// the possibility of minus signs, a decimal point, 'e+'/'e-', etc.
-// While the Right Thing is to follow Steele and White, I'm just going
-// to double what I consider a safe number of bytes and hope for the
-// best.
-#define DOUBLE_BUF_SIZE 40
-
-static void fillBase(char *buf, int buf_size, int64 n,
- uint8 n_real_bits, int base);
-static void fillBinary(char *buf, int64 n, int start_bit);
-static char baseToFmtSpec(int base);
+#include <limits.h>
+
+#ifndef LLONG_MAX
+/*
+ * Note:
+ *
+ * At time of writing (12 April 2011), the limits.h that came with the
+ * newlib we distributed didn't include LLONG_MAX. Because we're
+ * staying away from using templates (see /notes/coding_standard.rst,
+ * "Language Features and Compiler Extensions"), this value was
+ * copy-pasted from a println() of the value
+ *
+ * std::numeric_limits<long long>::max().
+ */
+#define LLONG_MAX 9223372036854775807LL
+#endif
+
+#include "wirish_math.h"
+
+/*
+ * Public methods
+ */
void Print::write(const char *str) {
- for (const char *c = str; *c != '\0'; c++) {
- write(*c);
+ while (*str) {
+ write(*str++);
}
}
-void Print::write(void *buffer, uint32 size) {
- for (uint32 i = 0; i < size; i++) {
- write(*((uint8*)buffer + i));
+void Print::write(const void *buffer, uint32 size) {
+ uint8 *ch = (uint8*)buffer;
+ while (size--) {
+ write(*ch++);
}
}
+void Print::print(uint8 b) {
+ this->write(b);
+}
+
void Print::print(char c) {
- print((uint8) c);
+ print((uint8)c);
}
void Print::print(const char str[]) {
write(str);
}
-void Print::print(uint8 b) {
- write(b);
+void Print::print(int n) {
+ print((long long)n);
}
-void Print::print(int32 n) {
- print(n, DEC);
+void Print::print(unsigned int n) {
+ print((unsigned long long)n);
}
-void Print::print(uint32 n) {
- print((uint64) n);
+void Print::print(long n) {
+ print((long long)n);
}
-void Print::print(int64 n) {
- print(n, DEC);
+void Print::print(unsigned long n) {
+ print((unsigned long long)n);
}
-void Print::print(uint64 n) {
- char buf[INT_BUF_SIZE];
- snprintf(buf, INT_BUF_SIZE, "%llu", n);
- write(buf);
+void Print::print(long long n) {
+ if (n < 0) {
+ print('-');
+ n = -n;
+ }
+ printNumber(n, 10);
}
-void Print::print(int32 n, int base) {
- // Worst case: sign bit set && base == BIN: 32 bytes for digits +
- // 1 null (base == BIN means no minus sign).
- char buf[33];
- fillBase(buf, sizeof(buf), (int64)n, 32, base);
- write(buf);
+void Print::print(unsigned long long n) {
+ printNumber(n, 10);
}
-void Print::print(int64 n, int base) {
- // As above, but now 64 bytes for bits + 1 null
- char buf[65];
- fillBase(buf, sizeof(buf), n, 64, base);
- write(buf);
+void Print::print(unsigned long long n, int base) {
+ if (base == 0) {
+ print((char)n);
+ } else if (base == 10) {
+ print(n);
+ } else {
+ printNumber(n, base);
+ }
}
void Print::print(double n) {
- char buf[DOUBLE_BUF_SIZE];
- // This breaks strict compliance with the Arduino library behavior
- // (which is equivalent to using "%.2f"), but that's really not
- // enough. According to Stroustrup, "%f" without precision is
- // equivalent to ".6f", which is much better.
- snprintf(buf, DOUBLE_BUF_SIZE, "%f", n);
- write(buf);
+ printFloat(n, 2);
}
void Print::println(void) {
- print("\r\n");
+ print('\r');
+ print('\n');
}
void Print::println(char c) {
@@ -139,32 +133,37 @@ void Print::println(uint8 b) {
println();
}
-void Print::println(int32 n) {
+void Print::println(int n) {
print(n);
println();
}
-void Print::println(uint32 n) {
+void Print::println(unsigned int n) {
print(n);
println();
}
-void Print::println(int64 n) {
- print(n);
+void Print::println(long n) {
+ print((long long)n);
+ println();
+}
+
+void Print::println(unsigned long n) {
+ print((unsigned long long)n);
println();
}
-void Print::println(uint64 n) {
+void Print::println(long long n) {
print(n);
println();
}
-void Print::println(int32 n, int base) {
- print(n, base);
+void Print::println(unsigned long long n) {
+ print(n);
println();
}
-void Print::println(int64 n, int base) {
+void Print::println(unsigned long long n, int base) {
print(n, base);
println();
}
@@ -174,54 +173,87 @@ void Print::println(double n) {
println();
}
-// -- Auxiliary functions -----------------------------------------------------
+/*
+ * Private methods
+ */
-static void fillBase(char *buf, int buf_size, int64 n,
- uint8 n_real_bits, int base) {
- if (base == BIN) {
- fillBinary(buf, n, n_real_bits - 1);
- } else {
- char spec = baseToFmtSpec(base);
- char fmt[5];
-
- if (base == BYTE)
- n = (uint8)n;
-
- if (n_real_bits == 32) {
- snprintf(fmt, sizeof(fmt), "%%l%c", spec);
- snprintf(buf, buf_size, fmt, (int32)n);
- } else {
- snprintf(fmt, sizeof(fmt), "%%ll%c", spec);
- snprintf(buf, buf_size, fmt, n);
- }
+void Print::printNumber(unsigned long long n, uint8 base) {
+ unsigned char buf[CHAR_BIT * sizeof(long long)];
+ unsigned long i = 0;
+
+ if (n == 0) {
+ print('0');
+ return;
+ }
+
+ while (n > 0) {
+ buf[i++] = n % base;
+ n /= base;
+ }
+
+ for (; i > 0; i--) {
+ print((char)(buf[i - 1] < 10 ?
+ '0' + buf[i - 1] :
+ 'A' + buf[i - 1] - 10));
}
}
-// Assumes sizeof(buf) > start_bit.
-static void fillBinary(char *buf, int64 n, int start_bit) {
- int b = 0; // position in buf
- int i = start_bit; // position in n's bits
- while(!(n & (1 << i))) {
- i--;
+/* According to snprintf(),
+ *
+ * nextafter((double)numeric_limits<long long>::max(), 0.0) ~= 9.22337e+18
+ *
+ * This slightly smaller value was picked semi-arbitrarily. */
+#define LARGE_DOUBLE_TRESHOLD (9.1e18)
+
+/* THIS FUNCTION SHOULDN'T BE USED IF YOU NEED ACCURATE RESULTS.
+ *
+ * This implementation is meant to be simple and not occupy too much
+ * code size. However, printing floating point values accurately is a
+ * subtle task, best left to a well-tested library function.
+ *
+ * See Steele and White 2003 for more details:
+ *
+ * http://kurtstephens.com/files/p372-steele.pdf
+ */
+void Print::printFloat(double number, uint8 digits) {
+ // Hackish fail-fast behavior for large-magnitude doubles
+ if (abs(number) >= LARGE_DOUBLE_TRESHOLD) {
+ if (number < 0.0) {
+ print('-');
+ }
+ print("<large double>");
+ return;
}
- for(; i >= 0; i--) {
- buf[b++] = '0' + ((n >> i) & 0x1);
+
+ // Handle negative numbers
+ if (number < 0.0) {
+ print('-');
+ number = -number;
+ }
+
+ // Simplistic rounding strategy so that e.g. print(1.999, 2)
+ // prints as "2.00"
+ double rounding = 0.5;
+ for (uint8 i = 0; i < digits; i++) {
+ rounding /= 10.0;
}
- buf[b] = '\0';
-}
-
-static char baseToFmtSpec(int base) {
- switch (base) {
- case DEC:
- return 'd';
- case HEX:
- return 'x';
- case OCT:
- return 'o';
- case BYTE:
- return 'd';
- default:
- // Shouldn't happen, but give a sensible default
- return 'd';
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ long long int_part = (long long)number;
+ double remainder = number - int_part;
+ print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 0) {
+ print(".");
+ }
+
+ // Extract digits from the remainder one at a time
+ while (digits-- > 0) {
+ remainder *= 10.0;
+ int to_print = (int)remainder;
+ print(to_print);
+ remainder -= to_print;
}
}
diff --git a/wirish/Print.h b/wirish/Print.h
index 4527948..73d82e7 100644
--- a/wirish/Print.h
+++ b/wirish/Print.h
@@ -1,68 +1,69 @@
-/******************************************************************************
- * The MIT License
+/*
+ * Print.h - Base class that provides print() and println()
+ * Copyright (c) 2008 David A. Mellis. All right reserved.
*
- * Copyright (c) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 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.
- *****************************************************************************/
+ * Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
+ */
#ifndef _PRINT_H_
#define _PRINT_H_
#include "libmaple_types.h"
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
-#define BYTE 0 // yuck
+enum {
+ BYTE = 0,
+ BIN = 2,
+ OCT = 8,
+ DEC = 10,
+ HEX = 16
+};
class Print {
- public:
- virtual void write(uint8) = 0;
+public:
+ virtual void write(uint8 ch) = 0;
virtual void write(const char *str);
- virtual void write(void *buf, uint32 size);
-
+ virtual void write(const void *buf, uint32 len);
void print(char);
void print(const char[]);
void print(uint8);
- void print(int32);
- void print(uint32);
- void print(int64);
- void print(uint64);
- void print(int32, int);
- void print(int64, int);
+ void print(int);
+ void print(unsigned int);
+ void print(long);
+ void print(unsigned long);
+ void print(long long);
+ void print(unsigned long long);
+ void print(unsigned long long, int);
void print(double);
-
void println(void);
void println(char);
void println(const char[]);
void println(uint8);
- void println(int32);
- void println(uint32);
- void println(int64);
- void println(uint64);
- void println(int32, int);
- void println(int64, int);
+ void println(int);
+ void println(unsigned int);
+ void println(long);
+ void println(unsigned long);
+ void println(long long);
+ void println(unsigned long long);
+ void println(unsigned long long, int);
void println(double);
+private:
+ void printNumber(unsigned long long, uint8);
+ void printFloat(double, uint8);
};
#endif
diff --git a/wirish/boards.cpp b/wirish/boards.cpp
new file mode 100644
index 0000000..9e25eeb
--- /dev/null
+++ b/wirish/boards.cpp
@@ -0,0 +1,160 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Perry Hung.
+ *
+ * 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 Generic board initialization routines.
+ *
+ * By default, we bring up all Maple boards to 72MHz, clocked off the
+ * PLL, driven by the 8MHz external crystal. AHB and APB2 are clocked
+ * at 72MHz. APB1 is clocked at 36MHz.
+ */
+
+#include "boards.h"
+
+#include "flash.h"
+#include "rcc.h"
+#include "nvic.h"
+#include "systick.h"
+#include "gpio.h"
+#include "adc.h"
+#include "timer.h"
+#include "usb.h"
+
+static void setupFlash(void);
+static void setupClocks(void);
+static void setupNVIC(void);
+static void setupADC(void);
+static void setupTimers(void);
+
+void init(void) {
+ setupFlash();
+ setupClocks();
+ setupNVIC();
+ systick_init(SYSTICK_RELOAD_VAL);
+ gpio_init_all();
+ afio_init();
+ setupADC();
+ setupTimers();
+ setupUSB();
+ boardInit();
+}
+
+/* You could farm this out to the files in boards/ if e.g. it takes
+ * too long to test on Maple Native (all those FSMC pins...). */
+bool boardUsesPin(uint8 pin) {
+ for (int i = 0; i < BOARD_NR_USED_PINS; i++) {
+ if (pin == boardUsedPins[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void setupFlash(void) {
+ flash_enable_prefetch();
+ flash_set_latency(FLASH_WAIT_STATE_2);
+}
+
+/*
+ * Clock setup. Note that some of this only takes effect if we're
+ * running bare metal and the bootloader hasn't done it for us
+ * already.
+ *
+ * If you change this function, you MUST change the file-level Doxygen
+ * comment above.
+ */
+static void setupClocks() {
+ rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9);
+ rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
+ rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
+ rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
+}
+
+static void setupNVIC() {
+#ifdef VECT_TAB_FLASH
+ nvic_init(USER_ADDR_ROM, 0);
+#elif defined VECT_TAB_RAM
+ nvic_init(USER_ADDR_RAM, 0);
+#elif defined VECT_TAB_BASE
+ nvic_init((uint32)0x08000000, 0);
+#else
+#error "You must select a base address for the vector table."
+#endif
+}
+
+static void adcDefaultConfig(const adc_dev* dev);
+
+static void setupADC() {
+ adc_foreach(adcDefaultConfig);
+}
+
+static void timerDefaultConfig(timer_dev*);
+
+static void setupTimers() {
+ timer_foreach(timerDefaultConfig);
+}
+
+static void adcDefaultConfig(const adc_dev *dev) {
+ adc_init(dev);
+
+ adc_set_extsel(dev, ADC_SWSTART);
+ adc_set_exttrig(dev, true);
+
+ adc_enable(dev);
+ adc_calibrate(dev);
+ adc_set_sample_rate(dev, ADC_SMPR_55_5);
+}
+
+static void timerDefaultConfig(timer_dev *dev) {
+ timer_adv_reg_map *regs = (dev->regs).adv;
+ const uint16 full_overflow = 0xFFFF;
+ const uint16 half_duty = 0x8FFF;
+
+ timer_init(dev);
+ timer_pause(dev);
+
+ regs->CR1 = TIMER_CR1_ARPE;
+ regs->PSC = 1;
+ regs->SR = 0;
+ regs->DIER = 0;
+ regs->EGR = TIMER_EGR_UG;
+
+ switch (dev->type) {
+ case TIMER_ADVANCED:
+ regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF;
+ // fall-through
+ case TIMER_GENERAL:
+ timer_set_reload(dev, full_overflow);
+
+ for (int channel = 1; channel <= 4; channel++) {
+ timer_set_compare(dev, channel, half_duty);
+ timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
+ }
+ // fall-through
+ case TIMER_BASIC:
+ break;
+ }
+
+ timer_resume(dev);
+}
diff --git a/wirish/boards.h b/wirish/boards.h
index f8505ab..2515c00 100644
--- a/wirish/boards.h
+++ b/wirish/boards.h
@@ -3,29 +3,37 @@
*
* Copyright (c) 2010 Bryan Newbold.
*
- * 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
+ * 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 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.
+ * 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.
*****************************************************************************/
-/* This file contains board-specific pin mapping tables. To add a new board
- * type, copy the "BOARD_maple" section below and edit it as needed, then
- * update your build toolchain with a new "BOARD" type. This must match the
- * separate MCU type (which determines the ../libmaple configuration).
+/**
+ * @file boards.h
+ * @author Bryan Newbold <bnewbold@leaflabs.com>,
+ * Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Board-specific pin information.
+ *
+ * To add a new board type, add a new pair of files to
+ * /wirish/boards/, update the section below with a new "BOARD" type,
+ * and update /wirish/rules.mk to include your boards/your_board.cpp
+ * file in the top-level Makefile build.
*/
#ifndef _BOARDS_H_
@@ -33,14 +41,14 @@
#include "libmaple.h"
#include "gpio.h"
-#include "timers.h"
-#include "exti.h"
+#include "timer.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "wirish_types.h"
-/* Set of all possible digital pin names; not all boards have all these */
+/* Set of all possible pin names; not all boards have all these (note
+ * that we use the Dx convention since all of the Maple's pins are
+ * "digital" pins (e.g. can be used with digitalRead() and
+ * digitalWrite()), but not all of them are connected to ADCs. */
enum {
D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16,
D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31,
@@ -51,444 +59,97 @@ enum {
D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105,
D106, D107, D108, D109, D110, D111, };
-/* Set of all possible analog pin names; not all boards have all these */
-enum {
- ADC0, ADC1, ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, ADC10, ADC11,
- ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, };
-
-#define ADC_INVALID 0xFFFFFFFF
-
-/* Types used for the tables below */
-typedef struct PinMapping {
- GPIO_Port *port;
- uint32 pin;
- uint32 adc;
- TimerCCR timer_ccr;
- uint32 exti_port;
- timer_dev_num timer_num;
- uint32 timer_chan;
-} PinMapping;
-
-/* LeafLabs Maple rev3, rev5 */
-#ifdef BOARD_maple
+/**
+ * @brief Maps each Maple pin to a corresponding stm32_pin_info.
+ * @see stm32_pin_info
+ */
+extern const stm32_pin_info PIN_MAP[];
- #define CYCLES_PER_MICROSECOND 72
- #define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
+/**
+ * @brief Pins capable of PWM output.
+ *
+ * Its length is BOARD_NR_PWM_PINS.
+ */
+extern const uint8 boardPWMPins[];
- #define BOARD_BUTTON_PIN 38
- #define BOARD_LED_PIN 13
+/**
+ * @brief Array of pins capable of analog input.
+ *
+ * Its length is BOARD_NR_ADC_PINS.
+ */
+extern const uint8 boardADCPins[];
- static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
- /* D0/PA3 */
- {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4},
- /* D1/PA2 */
- {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2, 3},
- /* D2/PA0 */
- {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1},
- /* D3/PA1 */
- {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
- /* D4/PB5 */
- {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 */
- {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, TIMER1, 2},
- /* D8/PA10 */
- {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, TIMER4, 2},
- /* D10/PA4 */
- {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, 0, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
- /* D14/PB8 */
- {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3},
+/**
+ * @brief Pins which are connected to external hardware.
+ *
+ * For example, on Maple boards, it always at least includes
+ * BOARD_LED_PIN. Its length is BOARD_NR_USED_PINS.
+ */
+extern const uint8 boardUsedPins[];
- /* Little header */
+/**
+ * @brief Generic board initialization function.
+ *
+ * This function is called before main(). It ensures that the clocks
+ * and peripherals are configured properly for use with wirish, then
+ * calls boardInit().
+ *
+ * @see boardInit()
+ */
+void init(void);
- /* D15/PC0 */
- {GPIOC_BASE, 0, ADC10, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D16/PC1 */
- {GPIOC_BASE, 1, ADC11, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D17/PC2 */
- {GPIOC_BASE, 2, ADC12, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D18/PC3 */
- {GPIOC_BASE, 3, ADC13, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D19/PC4 */
- {GPIOC_BASE, 4, ADC14, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D20/PC5 */
- {GPIOC_BASE, 5, ADC15, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
+/**
+ * @brief Board-specific initialization function.
+ *
+ * This function is called from init() after all generic board
+ * initialization has been performed. Each board is required to
+ * define its own.
+ *
+ * @see init()
+ */
+extern void boardInit(void);
- /* External header */
+/**
+ * @brief Test if a pin is used for a special purpose on your board.
+ * @param pin Pin to test
+ * @return true if the given pin is in boardUsedPins, and false otherwise.
+ * @see boardUsedPins
+ */
+bool boardUsesPin(uint8 pin);
- /* D21/PC13 */
- {GPIOC_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D22/PC14 */
- {GPIOC_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D23/PC15 */
- {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, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
- /* D26/PC10 */
- {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},
- /* D28/PB1 */
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
- /* D29/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
- /* D30/PB11 */
- {GPIOB_BASE, 11, 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/PB13 */
- {GPIOB_BASE, 13, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
- /* D33/PB14 */
- {GPIOB_BASE, 14, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
- /* D34/PB15 */
- {GPIOB_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
- /* D35/PC6 */
- {GPIOC_BASE, 6, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D36/PC7 */
- {GPIOC_BASE, 7, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
- /* D37/PC8 */
- {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}
- };
+/* Include the appropriate private header from boards/: */
- #define BOARD_INIT do { \
- } while(0)
+/* FIXME HACK put boards/ before these paths once IDE uses make. */
+#ifdef BOARD_maple
+#include "maple.h"
#elif defined(BOARD_maple_native)
-
- /* LeafLabs Maple Native (prototype) */
-
- #define CYCLES_PER_MICROSECOND 72
- #define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
-
- #define BOARD_LED_PIN D21
- #define BOARD_BUTTON_PIN D18
-
- static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
- /* Top 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},
-
- /* Bottom 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},
-
- /* 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}
- };
-
- #define BOARD_INIT do { \
- } while(0)
-
+#include "maple_native.h"
#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},
- };
-
- /* 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)
-
+#include "maple_mini.h"
+#elif defined(BOARD_maple_RET6)
+/*
+ * **NOT** MAPLE REV6. This the **Maple RET6 EDITION**, which is a
+ * Maple with an STM32F103RET6 (...RET6) instead of an STM32F103RBT6
+ * (...RBT6) on it. Maple Rev6 (as of March 2011) DOES NOT EXIST.
+ */
+#include "maple_RET6.h"
#else
-
+/*
+ * TODO turn this into a warning so people can:
+ *
+ * #include "my_board_config.h"
+ * #include "wirish.h"
+ *
+ * This will enable third-party board support without requiring that
+ * anybody hack around in libmaple itself.
+ */
#error "Board type has not been selected correctly."
-
#endif
-#ifdef __cplusplus
-} // extern "C"
-#endif
+/* Set derived definitions */
-#endif
+#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND
+#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL)
+#endif
diff --git a/wirish/boards/maple.cpp b/wirish/boards/maple.cpp
new file mode 100644
index 0000000..2d35e7b
--- /dev/null
+++ b/wirish/boards/maple.cpp
@@ -0,0 +1,115 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple.cpp
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Maple PIN_MAP and boardInit().
+ */
+
+#include "gpio.h"
+#include "timer.h"
+
+#include "maple.h"
+
+#ifdef BOARD_maple
+
+void boardInit(void) {
+}
+
+extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
+
+ /* Top header */
+
+ {GPIOA, TIMER2, ADC1, 3, 4, 3}, /* D0/PA3 */
+ {GPIOA, TIMER2, ADC1, 2, 3, 2}, /* D1/PA2 */
+ {GPIOA, TIMER2, ADC1, 0, 1, 0}, /* D2/PA0 */
+ {GPIOA, TIMER2, ADC1, 1, 2, 1}, /* D3/PA1 */
+ {GPIOB, NULL, NULL, 5, 0, ADCx}, /* D4/PB5 */
+ {GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* D5/PB6 */
+ {GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* D6/PA8 */
+ {GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* D7/PA9 */
+ {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D8/PA10 */
+ {GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* D9/PB7 */
+ {GPIOA, NULL, ADC1, 4, 0, 4}, /* D10/PA4 */
+ {GPIOA, TIMER3, ADC1, 7, 2, 7}, /* D11/PA7 */
+ {GPIOA, TIMER3, ADC1, 6, 1, 6}, /* D12/PA6 */
+ {GPIOA, NULL, ADC1, 5, 0, 5}, /* D13/PA5 (LED) */
+ {GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* D14/PB8 */
+
+ /* Little header */
+
+ {GPIOC, NULL, ADC1, 0, 0, 10}, /* D15/PC0 */
+ {GPIOC, NULL, ADC1, 1, 0, 11}, /* D16/PC1 */
+ {GPIOC, NULL, ADC1, 2, 0, 12}, /* D17/PC2 */
+ {GPIOC, NULL, ADC1, 3, 0, 13}, /* D18/PC3 */
+ {GPIOC, NULL, ADC1, 4, 0, 14}, /* D19/PC4 */
+ {GPIOC, NULL, ADC1, 5, 0, 15}, /* D20/PC5 */
+
+ /* External header */
+
+ {GPIOC, NULL, NULL, 13, 0, ADCx}, /* D21/PC13 */
+ {GPIOC, NULL, NULL, 14, 0, ADCx}, /* D22/PC14 */
+ {GPIOC, NULL, NULL, 15, 0, ADCx}, /* D23/PC15 */
+ {GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* D24/PB9 */
+ {GPIOD, NULL, NULL, 2, 0, ADCx}, /* D25/PD2 */
+ {GPIOC, NULL, NULL, 10, 0, ADCx}, /* D26/PC10 */
+ {GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D27/PB0 */
+ {GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D28/PB1 */
+ {GPIOB, NULL, NULL, 10, 0, ADCx}, /* D29/PB10 */
+ {GPIOB, NULL, NULL, 11, 0, ADCx}, /* D30/PB11 */
+ {GPIOB, NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */
+ {GPIOB, NULL, NULL, 13, 0, ADCx}, /* D32/PB13 */
+ {GPIOB, NULL, NULL, 14, 0, ADCx}, /* D33/PB14 */
+ {GPIOB, NULL, NULL, 15, 0, ADCx}, /* D34/PB15 */
+ {GPIOC, NULL, NULL, 6, 0, ADCx}, /* D35/PC6 */
+ {GPIOC, NULL, NULL, 7, 0, ADCx}, /* D36/PC7 */
+ {GPIOC, NULL, NULL, 8, 0, ADCx}, /* D37/PC8 */
+ {GPIOC, NULL, NULL, 9, 0, ADCx}, /* D38/PC9 (BUT) */
+
+ /* JTAG header */
+
+ {GPIOA, NULL, NULL, 13, 0, ADCx}, /* D39/PA13 */
+ {GPIOA, NULL, NULL, 14, 0, ADCx}, /* D40/PA14 */
+ {GPIOA, NULL, NULL, 15, 0, ADCx}, /* D41/PA15 */
+ {GPIOB, NULL, NULL, 3, 0, ADCx}, /* D42/PB3 */
+ {GPIOB, NULL, NULL, 4, 0, ADCx}, /* D43/PB4 */
+};
+
+extern const uint8 boardPWMPins[] __FLASH__ = {
+ 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 25, 27, 28
+};
+
+extern const uint8 boardADCPins[] __FLASH__ = {
+ 0, 1, 2, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 27, 28
+};
+
+extern const uint8 boardUsedPins[] __FLASH__ = {
+ BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN,
+ BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN
+};
+
+#endif
diff --git a/wirish/boards/maple.h b/wirish/boards/maple.h
new file mode 100644
index 0000000..4b55f7a
--- /dev/null
+++ b/wirish/boards/maple.h
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private include file for Maple in boards.h
+ */
+
+#include "wirish_types.h"
+
+#ifndef _BOARD_MAPLE_H_
+#define _BOARD_MAPLE_H_
+
+#define CYCLES_PER_MICROSECOND 72
+#define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
+
+#define BOARD_BUTTON_PIN 38
+#define BOARD_LED_PIN 13
+
+/* Number of USARTs/UARTs whose pins are broken out to headers */
+#define BOARD_NR_USARTS 3
+
+/* Default USART pin numbers (not considering AFIO remap) */
+#define BOARD_USART1_TX_PIN 7
+#define BOARD_USART1_RX_PIN 8
+#define BOARD_USART2_TX_PIN 1
+#define BOARD_USART2_RX_PIN 0
+#define BOARD_USART3_TX_PIN 29
+#define BOARD_USART3_RX_PIN 30
+
+/* Number of SPI ports */
+#define BOARD_NR_SPI 2
+
+/* Default SPI pin numbers (not considering AFIO remap) */
+#define BOARD_SPI1_NSS_PIN 10
+#define BOARD_SPI1_MOSI_PIN 11
+#define BOARD_SPI1_MISO_PIN 12
+#define BOARD_SPI1_SCK_PIN 13
+#define BOARD_SPI2_NSS_PIN 31
+#define BOARD_SPI2_MOSI_PIN 34
+#define BOARD_SPI2_MISO_PIN 33
+#define BOARD_SPI2_SCK_PIN 32
+
+/* Total number of GPIO pins that are broken out to headers and
+ * intended for general use. */
+#define BOARD_NR_GPIO_PINS 44
+
+/* Number of pins capable of PWM output */
+#define BOARD_NR_PWM_PINS 16
+
+/* Number of pins capable of ADC conversion */
+#define BOARD_NR_ADC_PINS 15
+
+/* Number of pins already connected to external hardware. For Maple,
+ * these are just BOARD_LED_PIN and BOARD_BUTTON_PIN. */
+#define BOARD_NR_USED_PINS 7
+
+/*
+ * Debug port pins
+ */
+#define BOARD_JTMS_SWDIO_PIN 39
+#define BOARD_JTCK_SWCLK_PIN 40
+#define BOARD_JTDI_PIN 41
+#define BOARD_JTDO_PIN 42
+#define BOARD_NJTRST_PIN 43
+
+#endif
diff --git a/wirish/boards/maple_RET6.cpp b/wirish/boards/maple_RET6.cpp
new file mode 100644
index 0000000..d5d3d32
--- /dev/null
+++ b/wirish/boards/maple_RET6.cpp
@@ -0,0 +1,112 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_RET6.cpp
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Maple RET6 Edition PIN_MAP and boardInit()
+ */
+
+#include "maple_RET6.h"
+
+#ifdef BOARD_maple_RET6
+
+void boardInit(void) {
+}
+
+extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
+
+ /* Top header */
+
+ {GPIOA, TIMER2, ADC1, 3, 4, 3}, /* D0/PA3 */
+ {GPIOA, TIMER2, ADC1, 2, 3, 2}, /* D1/PA2 */
+ {GPIOA, TIMER2, ADC1, 0, 1, 0}, /* D2/PA0 */
+ {GPIOA, TIMER2, ADC1, 1, 2, 1}, /* D3/PA1 */
+ {GPIOB, NULL, NULL, 5, 0, ADCx}, /* D4/PB5 */
+ {GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* D5/PB6 */
+ {GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* D6/PA8 */
+ {GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* D7/PA9 */
+ {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D8/PA10 */
+ {GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* D9/PB7 */
+ {GPIOA, NULL, ADC1, 4, 0, 4}, /* D10/PA4 */
+ {GPIOA, TIMER3, ADC1, 7, 2, 7}, /* D11/PA7 */
+ {GPIOA, TIMER3, ADC1, 6, 1, 6}, /* D12/PA6 */
+ {GPIOA, NULL, ADC1, 5, 0, 5}, /* D13/PA5 (LED) */
+ {GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* D14/PB8 */
+
+ /* Little header */
+
+ {GPIOC, NULL, ADC1, 0, 0, 10}, /* D15/PC0 */
+ {GPIOC, NULL, ADC1, 1, 0, 11}, /* D16/PC1 */
+ {GPIOC, NULL, ADC1, 2, 0, 12}, /* D17/PC2 */
+ {GPIOC, NULL, ADC1, 3, 0, 13}, /* D18/PC3 */
+ {GPIOC, NULL, ADC1, 4, 0, 14}, /* D19/PC4 */
+ {GPIOC, NULL, ADC1, 5, 0, 15}, /* D20/PC5 */
+
+ /* External header */
+
+ {GPIOC, NULL, NULL, 13, 0, ADCx}, /* D21/PC13 */
+ {GPIOC, NULL, NULL, 14, 0, ADCx}, /* D22/PC14 */
+ {GPIOC, NULL, NULL, 15, 0, ADCx}, /* D23/PC15 */
+ {GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* D24/PB9 */
+ {GPIOD, NULL, NULL, 2, 0, ADCx}, /* D25/PD2 */
+ {GPIOC, NULL, NULL, 10, 0, ADCx}, /* D26/PC10 */
+ {GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D27/PB0 */
+ {GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D28/PB1 */
+ {GPIOB, NULL, NULL, 10, 0, ADCx}, /* D29/PB10 */
+ {GPIOB, NULL, NULL, 11, 0, ADCx}, /* D30/PB11 */
+ {GPIOB, NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */
+ {GPIOB, NULL, NULL, 13, 0, ADCx}, /* D32/PB13 */
+ {GPIOB, NULL, NULL, 14, 0, ADCx}, /* D33/PB14 */
+ {GPIOB, NULL, NULL, 15, 0, ADCx}, /* D34/PB15 */
+ {GPIOC, TIMER8, NULL, 6, 1, ADCx}, /* D35/PC6 */
+ {GPIOC, TIMER8, NULL, 7, 2, ADCx}, /* D36/PC7 */
+ {GPIOC, TIMER8, NULL, 8, 3, ADCx}, /* D37/PC8 */
+ {GPIOC, TIMER8, NULL, 9, 4, ADCx}, /* D38/PC9 (BUT) */
+
+ /* JTAG header */
+
+ {GPIOA, NULL, NULL, 13, 0, ADCx}, /* D39/PA13 */
+ {GPIOA, NULL, NULL, 14, 0, ADCx}, /* D40/PA14 */
+ {GPIOA, NULL, NULL, 15, 0, ADCx}, /* D41/PA15 */
+ {GPIOB, NULL, NULL, 3, 0, ADCx}, /* D42/PB3 */
+ {GPIOB, NULL, NULL, 4, 0, ADCx}, /* D43/PB4 */
+};
+
+extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = {
+ 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 25, 27, 28
+};
+
+extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
+ 0, 1, 2, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 27, 28
+};
+
+extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
+ BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN,
+ BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN
+};
+
+#endif
diff --git a/wirish/boards/maple_RET6.h b/wirish/boards/maple_RET6.h
new file mode 100644
index 0000000..4195857
--- /dev/null
+++ b/wirish/boards/maple_RET6.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_RET6.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private include file for Maple RET6 Edition in boards.h
+ *
+ * See maple.h for more information on these definitions.
+ */
+
+#include "gpio.h"
+#include "timer.h"
+
+#include "wirish_types.h"
+
+#ifndef _BOARDS_MAPLE_RET6_H_
+#define _BOARDS_MAPLE_RET6_H_
+
+#define CYCLES_PER_MICROSECOND 72
+#define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
+
+#define BOARD_BUTTON_PIN 38
+#define BOARD_LED_PIN 13
+
+/* Note: UART4 and UART5 have pins which aren't broken out :( */
+#define BOARD_NR_USARTS 3
+#define BOARD_USART1_TX_PIN 7
+#define BOARD_USART1_RX_PIN 8
+#define BOARD_USART2_TX_PIN 1
+#define BOARD_USART2_RX_PIN 0
+#define BOARD_USART3_TX_PIN 29
+#define BOARD_USART3_RX_PIN 30
+
+#define BOARD_NR_SPI 2
+#define BOARD_SPI1_NSS_PIN 10
+#define BOARD_SPI1_MOSI_PIN 11
+#define BOARD_SPI1_MISO_PIN 12
+#define BOARD_SPI1_SCK_PIN 13
+#define BOARD_SPI2_NSS_PIN 31
+#define BOARD_SPI2_MOSI_PIN 34
+#define BOARD_SPI2_MISO_PIN 33
+#define BOARD_SPI2_SCK_PIN 32
+
+#define BOARD_NR_GPIO_PINS 44
+#define BOARD_NR_PWM_PINS 16
+#define BOARD_NR_ADC_PINS 15
+#define BOARD_NR_USED_PINS 7
+
+#define BOARD_JTMS_SWDIO_PIN 39
+#define BOARD_JTCK_SWCLK_PIN 40
+#define BOARD_JTDI_PIN 41
+#define BOARD_JTDO_PIN 42
+#define BOARD_NJTRST_PIN 43
+
+#endif
diff --git a/wirish/boards/maple_mini.cpp b/wirish/boards/maple_mini.cpp
new file mode 100644
index 0000000..3bc250b
--- /dev/null
+++ b/wirish/boards/maple_mini.cpp
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_mini.cpp
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Maple Mini PIN_MAP and boardInit().
+ */
+
+#include "maple_mini.h"
+#include "gpio.h"
+#include "wirish_debug.h"
+
+#ifdef BOARD_maple_mini
+
+/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW
+ * and JTAG debug support */
+void boardInit(void) {
+ disableDebugPorts();
+}
+
+extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
+
+ /* Top header */
+
+ {GPIOB, NULL, NULL, 11, 0, ADCx}, /* D0/PB11 */
+ {GPIOB, NULL, NULL, 10, 0, ADCx}, /* D1/PB10 */
+ {GPIOB, NULL, NULL, 2, 0, ADCx}, /* D2/PB2 */
+ {GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D3/PB0 */
+ {GPIOA, TIMER3, ADC1, 7, 2, 7}, /* D4/PA7 */
+ {GPIOA, TIMER3, ADC1, 6, 1, 6}, /* D5/PA6 */
+ {GPIOA, NULL, ADC1, 5, 0, 5}, /* D6/PA5 */
+ {GPIOA, NULL, ADC1, 4, 0, 4}, /* D7/PA4 */
+ {GPIOA, TIMER2, ADC1, 3, 4, 3}, /* D8/PA3 */
+ {GPIOA, TIMER2, ADC1, 2, 3, 2}, /* D9/PA2 */
+ {GPIOA, TIMER2, ADC1, 1, 2, 1}, /* D10/PA1 */
+ {GPIOA, TIMER2, ADC1, 0, 1, 0}, /* D11/PA0 */
+ {GPIOC, NULL, NULL, 15, 0, ADCx}, /* D12/PC15 */
+ {GPIOC, NULL, NULL, 14, 0, ADCx}, /* D13/PC14 */
+ {GPIOC, NULL, NULL, 13, 0, ADCx}, /* D14/PC13 */
+
+ /* Bottom header */
+
+ {GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* D15/PB7 */
+ {GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* D16/PB6 */
+ {GPIOB, NULL, NULL, 5, 0, ADCx}, /* D17/PB5 */
+ {GPIOB, NULL, NULL, 4, 0, ADCx}, /* D18/PB4 */
+ {GPIOB, NULL, NULL, 3, 0, ADCx}, /* D19/PB3 */
+ {GPIOA, NULL, NULL, 15, 0, ADCx}, /* D20/PA15 */
+ {GPIOA, NULL, NULL, 14, 0, ADCx}, /* D21/PA14 */
+ {GPIOA, NULL, NULL, 13, 0, ADCx}, /* D22/PA13 */
+ {GPIOA, NULL, NULL, 12, 0, ADCx}, /* D23/PA12 */
+ {GPIOA, TIMER1, NULL, 11, 4, ADCx}, /* D24/PA11 */
+ {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D25/PA10 */
+ {GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* D26/PA9 */
+ {GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* D27/PA8 */
+ {GPIOB, NULL, NULL, 15, 0, ADCx}, /* D28/PB15 */
+ {GPIOB, NULL, NULL, 14, 0, ADCx}, /* D29/PB14 */
+ {GPIOB, NULL, NULL, 13, 0, ADCx}, /* D30/PB13 */
+ {GPIOB, NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */
+ {GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* D32/PB8 */
+ {GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D33/PB1 */
+};
+
+extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = {
+ 3, 4, 5, 8, 9, 10, 11, 15, 16, 25, 26, 27
+};
+
+extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 33 // NB: 33 is BOARD_LED_PIN
+};
+
+#define USB_DP 23
+#define USB_DM 24
+
+extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
+ BOARD_LED_PIN, BOARD_BUTTON_PIN, USB_DP, USB_DM
+};
+
+#endif
diff --git a/wirish/boards/maple_mini.h b/wirish/boards/maple_mini.h
new file mode 100644
index 0000000..fde7f98
--- /dev/null
+++ b/wirish/boards/maple_mini.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_mini.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private include file for Maple Mini in boards.h
+ *
+ * See maple.h for more information on these definitions.
+ */
+
+#include "gpio.h"
+#include "timer.h"
+
+#include "wirish_types.h"
+
+#ifndef _BOARD_MAPLE_MINI_H_
+#define _BOARD_MAPLE_MINI_H_
+
+#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
+
+#define BOARD_NR_USARTS 3
+#define BOARD_USART1_TX_PIN 26
+#define BOARD_USART1_RX_PIN 25
+#define BOARD_USART2_TX_PIN 9
+#define BOARD_USART2_RX_PIN 8
+#define BOARD_USART3_TX_PIN 1
+#define BOARD_USART3_RX_PIN 0
+
+#define BOARD_NR_SPI 2
+#define BOARD_SPI1_NSS_PIN 7
+#define BOARD_SPI1_MOSI_PIN 4
+#define BOARD_SPI1_MISO_PIN 5
+#define BOARD_SPI1_SCK_PIN 6
+#define BOARD_SPI2_NSS_PIN 31
+#define BOARD_SPI2_MOSI_PIN 28
+#define BOARD_SPI2_MISO_PIN 29
+#define BOARD_SPI2_SCK_PIN 30
+
+#define BOARD_NR_GPIO_PINS 34
+#define BOARD_NR_PWM_PINS 12
+#define BOARD_NR_ADC_PINS 10
+#define BOARD_NR_USED_PINS 4
+
+#define BOARD_JTMS_SWDIO_PIN 22
+#define BOARD_JTCK_SWCLK_PIN 21
+#define BOARD_JTDI_PIN 20
+#define BOARD_JTDO_PIN 19
+#define BOARD_NJTRST_PIN 18
+
+#endif
diff --git a/wirish/boards/maple_native.cpp b/wirish/boards/maple_native.cpp
new file mode 100644
index 0000000..fa36240
--- /dev/null
+++ b/wirish/boards/maple_native.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_native.cpp
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Maple Native PIN_MAP and boardInit().
+ */
+
+#include "maple_native.h"
+
+#include "fsmc.h"
+#include "gpio.h"
+#include "rcc.h"
+#include "timer.h"
+
+#include "wirish_types.h"
+
+#ifdef BOARD_maple_native
+
+void initSRAMChip(void);
+
+void boardInit(void) {
+ initSRAMChip();
+}
+
+extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
+
+ /* Top header */
+
+ {GPIOB, NULL, NULL, 10, 0, ADCx}, /* D0/PB10 */
+ {GPIOB, NULL, NULL, 11, 0, ADCx}, /* D1/PB11 */
+ {GPIOB, NULL, NULL, 12, 0, ADCx}, /* D2/PB12 */
+ {GPIOB, NULL, NULL, 13, 0, ADCx}, /* D3/PB13 */
+ {GPIOB, NULL, NULL, 14, 0, ADCx}, /* D4/PB14 */
+ {GPIOB, NULL, NULL, 15, 0, ADCx}, /* D5/PB15 */
+ {GPIOG, NULL, NULL, 15, 0, ADCx}, /* D6/PG15 (BUT) */
+ {GPIOC, NULL, ADC1, 0, 0, 10}, /* D7/PC0 */
+ {GPIOC, NULL, ADC1, 1, 0, 11}, /* D8/PC1 */
+ {GPIOC, NULL, ADC1, 2, 0, 12}, /* D9/PC2 */
+ {GPIOC, NULL, ADC1, 3, 0, 13}, /* D10/PC3 */
+ {GPIOC, NULL, ADC1, 4, 0, 14}, /* D11/PC4 */
+ {GPIOC, NULL, ADC1, 5, 0, 15}, /* D12/PC5 */
+ {GPIOC, TIMER8, NULL, 6, 1, ADCx}, /* D13/PC6 */
+ {GPIOC, TIMER8, NULL, 7, 2, ADCx}, /* D14/PC7 */
+ {GPIOC, TIMER8, NULL, 8, 3, ADCx}, /* D15/PC8 */
+ {GPIOC, TIMER8, NULL, 9, 4, ADCx}, /* D16/PC9 */
+ {GPIOC, NULL, NULL, 10, 0, ADCx}, /* D17/PC10 */
+ {GPIOC, NULL, NULL, 11, 0, ADCx}, /* D18/PC11 */
+ {GPIOC, NULL, NULL, 12, 0, ADCx}, /* D19/PC12 */
+ {GPIOC, NULL, NULL, 13, 0, ADCx}, /* D20/PC13 */
+ {GPIOC, NULL, NULL, 14, 0, ADCx}, /* D21/PC14 */
+ {GPIOC, NULL, NULL, 15, 0, ADCx}, /* D22/PC15 (LED) */
+ {GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* D23/PA8 */
+ {GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* D24/PA9 */
+ {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D25/PA10 */
+ {GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* D26/PB9 */
+
+ /* Bottom header */
+ /* Note: D{48, 49, 50, 51} are also TIMER2_CH{1, 2, 3, 4}, respectively. */
+ /* TODO remap timer 2 in boardInit(); make the appropriate changes here */
+
+ {GPIOD, NULL, NULL, 2, 0, ADCx}, /* D27/PD2 */
+ {GPIOD, NULL, NULL, 3, 0, ADCx}, /* D28/PD3 */
+ {GPIOD, NULL, NULL, 6, 0, ADCx}, /* D29/PD6 */
+ {GPIOG, NULL, NULL, 11, 0, ADCx}, /* D30/PG11 */
+ {GPIOG, NULL, NULL, 12, 0, ADCx}, /* D31/PG12 */
+ {GPIOG, NULL, NULL, 13, 0, ADCx}, /* D32/PG13 */
+ {GPIOG, NULL, NULL, 14, 0, ADCx}, /* D33/PG14 */
+ {GPIOG, NULL, NULL, 8, 0, ADCx}, /* D34/PG8 */
+ {GPIOG, NULL, NULL, 7, 0, ADCx}, /* D35/PG7 */
+ {GPIOG, NULL, NULL, 6, 0, ADCx}, /* D36/PG6 */
+ {GPIOB, NULL, NULL, 5, 0, ADCx}, /* D37/PB5 */
+ {GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* D38/PB6 */
+ {GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* D39/PB7 */
+ {GPIOF, NULL, NULL, 11, 0, ADCx}, /* D40/PF11 */
+ {GPIOF, NULL, ADC3, 6, 0, 4}, /* D41/PF6 */
+ {GPIOF, NULL, ADC3, 7, 0, 5}, /* D42/PF7 */
+ {GPIOF, NULL, ADC3, 8, 0, 6}, /* D43/PF8 */
+ {GPIOF, NULL, ADC3, 9, 0, 7}, /* D44/PF9 */
+ {GPIOF, NULL, ADC3, 10, 0, 8}, /* D45/PF10 */
+ {GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D46/PB1 */
+ {GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D47/PB0 */
+ {GPIOA, TIMER5, ADC1, 0, 1, 0}, /* D48/PA0 */
+ {GPIOA, TIMER5, ADC1, 1, 2, 1}, /* D49/PA1 */
+ {GPIOA, TIMER5, ADC1, 2, 3, 2}, /* D50/PA2 */
+ {GPIOA, TIMER5, ADC1, 3, 4, 3}, /* D51/PA3 */
+ {GPIOA, NULL, ADC1, 4, 0, 4}, /* D52/PA4 */
+ {GPIOA, NULL, ADC1, 5, 0, 5}, /* D53/PA5 */
+ {GPIOA, TIMER3, ADC1, 6, 1, 6}, /* D54/PA6 */
+ {GPIOA, TIMER3, ADC1, 7, 2, 7}, /* D55/PA7 */
+
+ /* Right (triple) header */
+
+ {GPIOF, NULL, NULL, 0, 0, ADCx}, /* D56/PF0 */
+ {GPIOD, NULL, NULL, 11, 0, ADCx}, /* D57/PD11 */
+ {GPIOD, NULL, NULL, 14, 0, ADCx}, /* D58/PD14 */
+ {GPIOF, NULL, NULL, 1, 0, ADCx}, /* D59/PF1 */
+ {GPIOD, NULL, NULL, 12, 0, ADCx}, /* D60/PD12 */
+ {GPIOD, NULL, NULL, 15, 0, ADCx}, /* D61/PD15 */
+ {GPIOF, NULL, NULL, 2, 0, ADCx}, /* D62/PF2 */
+ {GPIOD, NULL, NULL, 13, 0, ADCx}, /* D63/PD13 */
+ {GPIOD, NULL, NULL, 0, 0, ADCx}, /* D64/PD0 */
+ {GPIOF, NULL, NULL, 3, 0, ADCx}, /* D65/PF3 */
+ {GPIOE, NULL, NULL, 3, 0, ADCx}, /* D66/PE3 */
+ {GPIOD, NULL, NULL, 1, 0, ADCx}, /* D67/PD1 */
+ {GPIOF, NULL, NULL, 4, 0, ADCx}, /* D68/PF4 */
+ {GPIOE, NULL, NULL, 4, 0, ADCx}, /* D69/PE4 */
+ {GPIOE, NULL, NULL, 7, 0, ADCx}, /* D70/PE7 */
+ {GPIOF, NULL, NULL, 5, 0, ADCx}, /* D71/PF5 */
+ {GPIOE, NULL, NULL, 5, 0, ADCx}, /* D72/PE5 */
+ {GPIOE, NULL, NULL, 8, 0, ADCx}, /* D73/PE8 */
+ {GPIOF, NULL, NULL, 12, 0, ADCx}, /* D74/PF12 */
+ {GPIOE, NULL, NULL, 6, 0, ADCx}, /* D75/PE6 */
+ {GPIOE, NULL, NULL, 9, 0, ADCx}, /* D76/PE9 */
+ {GPIOF, NULL, NULL, 13, 0, ADCx}, /* D77/PF13 */
+ {GPIOE, NULL, NULL, 10, 0, ADCx}, /* D78/PE10 */
+ {GPIOF, NULL, NULL, 14, 0, ADCx}, /* D79/PF14 */
+ {GPIOG, NULL, NULL, 9, 0, ADCx}, /* D80/PG9 */
+ {GPIOE, NULL, NULL, 11, 0, ADCx}, /* D81/PE11 */
+ {GPIOF, NULL, NULL, 15, 0, ADCx}, /* D82/PF15 */
+ {GPIOG, NULL, NULL, 10, 0, ADCx}, /* D83/PG10 */
+ {GPIOE, NULL, NULL, 12, 0, ADCx}, /* D84/PE12 */
+ {GPIOG, NULL, NULL, 0, 0, ADCx}, /* D85/PG0 */
+ {GPIOD, NULL, NULL, 5, 0, ADCx}, /* D86/PD5 */
+ {GPIOE, NULL, NULL, 13, 0, ADCx}, /* D87/PE13 */
+ {GPIOG, NULL, NULL, 1, 0, ADCx}, /* D88/PG1 */
+ {GPIOD, NULL, NULL, 4, 0, ADCx}, /* D89/PD4 */
+ {GPIOE, NULL, NULL, 14, 0, ADCx}, /* D90/PE14 */
+ {GPIOG, NULL, NULL, 2, 0, ADCx}, /* D91/PG2 */
+ {GPIOE, NULL, NULL, 1, 0, ADCx}, /* D92/PE1 */
+ {GPIOE, NULL, NULL, 15, 0, ADCx}, /* D93/PE15 */
+ {GPIOG, NULL, NULL, 3, 0, ADCx}, /* D94/PG3 */
+ {GPIOE, NULL, NULL, 0, 0, ADCx}, /* D95/PE0 */
+ {GPIOD, NULL, NULL, 8, 0, ADCx}, /* D96/PD8 */
+ {GPIOG, NULL, NULL, 4, 0, ADCx}, /* D97/PG4 */
+ {GPIOD, NULL, NULL, 9, 0, ADCx}, /* D98/PD9 */
+ {GPIOG, NULL, NULL, 5, 0, ADCx}, /* D99/PG5 */
+ {GPIOD, NULL, NULL, 10, 0, ADCx}, /* D100/PD10 */
+
+ /* JTAG header */
+
+ {GPIOA, NULL, NULL, 13, 0, ADCx}, /* D101/PA13 */
+ {GPIOA, NULL, NULL, 14, 0, ADCx}, /* D102/PA14 */
+ {GPIOA, NULL, NULL, 15, 0, ADCx}, /* D103/PA15 */
+ {GPIOB, NULL, NULL, 3, 0, ADCx}, /* D104/PB3 */
+ {GPIOB, NULL, NULL, 4, 0, ADCx} /* D105/PB4 */
+};
+
+extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = {
+ 13, 14, 15, 16, 23, 24, 25, 26, 38, 39, 46, 47, 48, 49, 50, 51, 54, 55
+};
+
+extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
+ 7, 8, 9, 10, 11, 12, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55
+};
+
+/* FIXME [0.0.10] see comment by BOARD_NR_USED_PINS in maple_native.h */
+extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
+ BOARD_LED_PIN, BOARD_BUTTON_PIN, BOARD_JTMS_SWDIO_PIN,
+ BOARD_JTCK_SWCLK_PIN, BOARD_JTDI_PIN, BOARD_JTDO_PIN, BOARD_NJTRST_PIN
+};
+
+void initSRAMChip(void) {
+ fsmc_nor_psram_reg_map *regs = FSMC_NOR_PSRAM1_BASE;
+
+ fsmc_sram_init_gpios();
+ rcc_clk_enable(RCC_FSMC);
+
+ regs->BCR = FSMC_BCR_WREN | FSMC_BCR_MWID_16BITS | FSMC_BCR_MBKEN;
+ fsmc_nor_psram_set_addset(regs, 0);
+ fsmc_nor_psram_set_datast(regs, 3);
+}
+
+#endif
diff --git a/wirish/boards/maple_native.h b/wirish/boards/maple_native.h
new file mode 100644
index 0000000..b573d72
--- /dev/null
+++ b/wirish/boards/maple_native.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file maple_native.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private include file for Maple Native in boards.h
+ *
+ * See maple.h for more information on these definitions.
+ */
+
+#ifndef _BOARD_MAPLE_NATIVE_H_
+#define _BOARD_MAPLE_NATIVE_H_
+
+#define CYCLES_PER_MICROSECOND 72
+#define SYSTICK_RELOAD_VAL 71999
+
+#define BOARD_LED_PIN 22
+#define BOARD_BUTTON_PIN 6
+
+#define BOARD_NR_USARTS 5
+#define BOARD_USART1_TX_PIN 26
+#define BOARD_USART1_RX_PIN 27
+#define BOARD_USART2_TX_PIN 52
+#define BOARD_USART2_RX_PIN 53
+#define BOARD_USART3_TX_PIN 0
+#define BOARD_USART3_RX_PIN 1
+#define BOARD_UART4_TX_PIN 19
+#define BOARD_UART4_RX_PIN 20
+#define BOARD_UART5_TX_PIN 21
+#define BOARD_UART5_RX_PIN 29
+
+#define BOARD_NR_SPI 3
+#define BOARD_SPI1_NSS_PIN 52
+#define BOARD_SPI1_MOSI_PIN 55
+#define BOARD_SPI1_MISO_PIN 54
+#define BOARD_SPI1_SCK_PIN 53
+#define BOARD_SPI2_NSS_PIN 2
+#define BOARD_SPI2_MOSI_PIN 5
+#define BOARD_SPI2_MISO_PIN 4
+#define BOARD_SPI2_SCK_PIN 3
+#define BOARD_SPI3_NSS_PIN 103
+#define BOARD_SPI3_MOSI_PIN 37
+#define BOARD_SPI3_MISO_PIN 105
+#define BOARD_SPI3_SCK_PIN 104
+
+#define BOARD_NR_GPIO_PINS 106
+#define BOARD_NR_PWM_PINS 18
+#define BOARD_NR_ADC_PINS 21
+/* FIXME [0.0.10] this isn't true at all; almost all of the triple
+ * header pins are used by the FSMC by default. Fix this (and the
+ * corresponding boardUsedPins definition in maple_native.cpp) by QA
+ * time. */
+#define BOARD_NR_USED_PINS 7
+
+#define BOARD_JTMS_SWDIO_PIN 101
+#define BOARD_JTCK_SWCLK_PIN 102
+#define BOARD_JTDI_PIN 103
+#define BOARD_JTDO_PIN 104
+#define BOARD_NJTRST_PIN 105
+
+#endif
diff --git a/wirish/comm/HardwareSPI.cpp b/wirish/comm/HardwareSPI.cpp
index 20090f5..54b7ab3 100644
--- a/wirish/comm/HardwareSPI.cpp
+++ b/wirish/comm/HardwareSPI.cpp
@@ -23,118 +23,268 @@
*****************************************************************************/
/**
- * @brief HardwareSPI "wiring-like" api for SPI
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Wirish SPI implementation.
*/
-/* NOTES:
- *
- * Speeds:
- * -----------------------------------
- * Interface num: SPI1 SPI2
- * Bus APB2 APB1
- * -----------------------------------
- * Prescaler Frequencies
- * -----------------------------------
- * 2: N/A 18 000 000
- * 4: 18 000 000 9 000 000
- * 8: 9 000 000 4 500 000
- * 16: 4 500 000 2 250 000
- * 32: 2 250 000 1 125 000
- * 64: 1 125 000 562 500
- * 128: 562 500 281 250
- * 256: 281 250 140 625
- *
- * TODO: Do the complementary PWM outputs mess up SPI2?
- * */
+#include "HardwareSPI.h"
+
+#include "timer.h"
+#include "util.h"
#include "wirish.h"
-#include "spi.h"
-#include "HardwareSPI.h"
+#include "boards.h"
-static const uint32 prescaleFactors[MAX_SPI_FREQS] = {
- SPI_PRESCALE_2, // SPI_18MHZ
- SPI_PRESCALE_4, // SPI_9MHZ
- SPI_PRESCALE_8, // SPI_4_5MHZ
- SPI_PRESCALE_16, // SPI_2_25MHZ
- SPI_PRESCALE_32, // SPI_1_125MHZ
- SPI_PRESCALE_64, // SPI_562_500KHZ
- SPI_PRESCALE_128, // SPI_281_250KHZ
- SPI_PRESCALE_256, // SPI_140_625KHZ
-};
+static void enable_device(spi_dev *dev,
+ bool as_master,
+ SPIFrequency frequency,
+ spi_cfg_flag endianness,
+ spi_mode mode);
-/**
- * @brief Initialize a SPI peripheral
- * @param freq frequency to run at, must one of the following values:
- * - SPI_18MHZ
- * - SPI_9MHZ
- * - SPI_4_5MHZ
- * - SPI_2_25MHZ
- * - SPI_1_125MHZ
- * - SPI_562_500KHZ
- * - SPI_281_250KHZ
- * - SPI_140_625KHZ
- * @param endianness endianness of the data frame, must be either LSBFIRST
- * or MSBFIRST
- * @param mode SPI standard CPOL and CPHA levels
+/*
+ * Constructor, public methods
*/
-void HardwareSPI::begin(SPIFrequency freq, uint32 endianness, uint32 mode) {
- uint32 spi_num = this->spi_num;
- uint32 prescale;
-
- if ((freq >= MAX_SPI_FREQS) ||
- !((endianness == LSBFIRST) ||
- (endianness == MSBFIRST)) ||
- (mode >= 4)) {
+
+HardwareSPI::HardwareSPI(uint32 spi_num) {
+ switch (spi_num) {
+ case 1:
+ this->spi_d = SPI1;
+ break;
+ case 2:
+ this->spi_d = SPI2;
+ break;
+#ifdef STM32_HIGH_DENSITY
+ case 3:
+ this->spi_d = SPI3;
+ break;
+#endif
+ default:
+ ASSERT(0);
+ }
+}
+
+void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) {
+ if (mode >= 4) {
+ ASSERT(0);
return;
}
+ spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB;
+ spi_mode m = (spi_mode)mode;
+ enable_device(this->spi_d, true, frequency, end, m);
+}
- if (spi_num == 1) {
- /* SPI1 is too fast for 140625 */
- if (freq == SPI_140_625KHZ) {
- return;
- }
+void HardwareSPI::begin(void) {
+ this->begin(SPI_1_125MHZ, MSBFIRST, 0);
+}
- /* Turn off PWM on shared pins */
- timer_set_mode(TIMER3, 2, TIMER_DISABLED);
- timer_set_mode(TIMER3, 1, TIMER_DISABLED);
+void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) {
+ if (mode >= 4) {
+ ASSERT(0);
+ return;
}
+ spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB;
+ spi_mode m = (spi_mode)mode;
+ enable_device(this->spi_d, false, (SPIFrequency)0, end, m);
+}
- endianness = (endianness == LSBFIRST) ? SPI_LSBFIRST : SPI_MSBFIRST;
- prescale = (spi_num == 1) ?
- prescaleFactors[freq + 1] :
- prescaleFactors[freq];
+void HardwareSPI::beginSlave(void) {
+ this->beginSlave(MSBFIRST, 0);
+}
+
+void HardwareSPI::end(void) {
+ if (!spi_is_enabled(this->spi_d)) {
+ return;
+ }
- spi_init(spi_num, prescale, endianness, mode);
+ // Follows RM0008's sequence for disabling a SPI in master/slave
+ // full duplex mode.
+ while (spi_is_rx_nonempty(this->spi_d)) {
+ // FIXME [0.1.0] remove this once you have an interrupt based driver
+ volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d);
+ }
+ while (!spi_is_tx_empty(this->spi_d))
+ ;
+ while (spi_is_busy(this->spi_d))
+ ;
+ spi_peripheral_disable(this->spi_d);
}
-/**
- * @brief Initialize a SPI peripheral with a default speed of 1.125
- * MHZ, MSBFIRST, mode 0
- */
-void HardwareSPI::begin(void) {
- begin(SPI_1_125MHZ, MSBFIRST, 0);
+uint8 HardwareSPI::read(void) {
+ uint8 buf[1];
+ this->read(buf, 1);
+ return buf[0];
}
-/**
- * @brief send a byte out the spi peripheral
- * @param data byte to send
+void HardwareSPI::read(uint8 *buf, uint32 len) {
+ uint32 rxed = 0;
+ while (rxed < len) {
+ while (!spi_is_rx_nonempty(this->spi_d))
+ ;
+ buf[rxed++] = (uint8)spi_rx_reg(this->spi_d);
+ }
+}
+
+void HardwareSPI::write(uint8 byte) {
+ this->write(&byte, 1);
+}
+
+void HardwareSPI::write(const uint8 *data, uint32 length) {
+ uint32 txed = 0;
+ while (txed < length) {
+ txed += spi_tx(this->spi_d, data + txed, length - txed);
+ }
+}
+
+uint8 HardwareSPI::transfer(uint8 byte) {
+ this->write(byte);
+ return this->read();
+}
+
+/*
+ * Deprecated functions
*/
+
uint8 HardwareSPI::send(uint8 data) {
- return spi_tx_byte(this->spi_num, data);
+ uint8 buf[] = {data};
+ return this->send(buf, 1);
}
uint8 HardwareSPI::send(uint8 *buf, uint32 len) {
- return spi_tx(this->spi_num, buf, len);
+ if (len == 0) {
+ return 0;
+ }
+ uint32 txed = 0;
+ uint8 ret = 0; // shut up, GCC
+ while (txed < len) {
+ this->write(buf[txed++]);
+ ret = this->read();
+ }
+ return ret;
}
-/**
- * @brief read a byte from the spi peripheral
- * @return byte in the buffer
- */
uint8 HardwareSPI::recv(void) {
- return spi_rx(this->spi_num);
+ return this->read();
}
-HardwareSPI::HardwareSPI(uint32 spi_num) {
- this->spi_num = spi_num;
+/*
+ * Auxiliary functions
+ */
+
+static void configure_gpios(spi_dev *dev, bool as_master);
+static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq);
+
+/* Enables the device in master or slave full duplex mode. If you
+ * change this code, you must ensure that appropriate changes are made
+ * to HardwareSPI::end(). */
+static void enable_device(spi_dev *dev,
+ bool as_master,
+ SPIFrequency freq,
+ spi_cfg_flag endianness,
+ spi_mode mode) {
+ spi_baud_rate baud = determine_baud_rate(dev, freq);
+ uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE |
+ (as_master ? SPI_SOFT_SS : 0));
+
+ spi_init(dev);
+ configure_gpios(dev, as_master);
+ if (as_master) {
+ spi_master_enable(dev, baud, mode, cfg_flags);
+ } else {
+ spi_slave_enable(dev, mode, cfg_flags);
+ }
+}
+
+static void disable_pwm(const stm32_pin_info *i) {
+ if (i->timer_device) {
+ timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED);
+ }
+}
+
+typedef struct spi_pins {
+ uint8 nss;
+ uint8 sck;
+ uint8 miso;
+ uint8 mosi;
+} spi_pins;
+
+static void configure_gpios(spi_dev *dev, bool as_master) {
+ const spi_pins spi_pin_config[] = {
+ {BOARD_SPI1_NSS_PIN,
+ BOARD_SPI1_SCK_PIN,
+ BOARD_SPI1_MISO_PIN,
+ BOARD_SPI1_MOSI_PIN},
+ {BOARD_SPI2_NSS_PIN,
+ BOARD_SPI2_SCK_PIN,
+ BOARD_SPI2_MISO_PIN,
+ BOARD_SPI2_MOSI_PIN},
+#ifdef STM32_HIGH_DENSITY
+ {BOARD_SPI3_NSS_PIN,
+ BOARD_SPI3_SCK_PIN,
+ BOARD_SPI3_MISO_PIN,
+ BOARD_SPI3_MOSI_PIN},
+#endif
+ };
+
+ const spi_pins *pins;
+
+ switch (dev->clk_id) {
+ case RCC_SPI1:
+ pins = &spi_pin_config[0];
+ break;
+ case RCC_SPI2:
+ pins = &spi_pin_config[1];
+ break;
+#ifdef STM32_HIGH_DENSITY
+ case RCC_SPI3:
+ pins = &spi_pin_config[2];
+ break;
+#endif
+ default:
+ ASSERT(0);
+ return;
+ }
+
+ const stm32_pin_info *nssi = &PIN_MAP[pins->nss];
+ const stm32_pin_info *scki = &PIN_MAP[pins->sck];
+ const stm32_pin_info *misoi = &PIN_MAP[pins->miso];
+ const stm32_pin_info *mosii = &PIN_MAP[pins->mosi];
+
+ disable_pwm(nssi);
+ disable_pwm(scki);
+ disable_pwm(misoi);
+ disable_pwm(mosii);
+
+ spi_gpio_cfg(as_master,
+ nssi->gpio_device,
+ nssi->gpio_bit,
+ scki->gpio_device,
+ scki->gpio_bit,
+ misoi->gpio_bit,
+ mosii->gpio_bit);
+}
+
+static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = {
+ SPI_BAUD_PCLK_DIV_2,
+ SPI_BAUD_PCLK_DIV_4,
+ SPI_BAUD_PCLK_DIV_8,
+ SPI_BAUD_PCLK_DIV_16,
+ SPI_BAUD_PCLK_DIV_32,
+ SPI_BAUD_PCLK_DIV_64,
+ SPI_BAUD_PCLK_DIV_128,
+ SPI_BAUD_PCLK_DIV_256,
+};
+
+/*
+ * Note: This assumes you're on a LeafLabs-style board
+ * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz).
+ */
+static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) {
+ if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) {
+ /* APB2 peripherals are too fast for 140.625 KHz */
+ ASSERT(0);
+ return (spi_baud_rate)~0;
+ }
+ return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ?
+ baud_rates[freq + 1] :
+ baud_rates[freq]);
}
diff --git a/wirish/comm/HardwareSPI.h b/wirish/comm/HardwareSPI.h
index 7241d0b..3a6def5 100644
--- a/wirish/comm/HardwareSPI.h
+++ b/wirish/comm/HardwareSPI.h
@@ -3,60 +3,188 @@
*
* Copyright (c) 2010 Perry Hung.
*
- * 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
+ * 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 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.
+ * 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 HardwareSPI definitions
+ * @file HardwareSPI.h
+ * @brief High-level SPI interface
+ *
+ * This is a "bare essentials" polling driver for now.
*/
+/* TODO [0.1.0] Remove deprecated methods. */
+
+#include "libmaple_types.h"
+#include "spi.h"
+
+#include "boards.h"
+
#ifndef _HARDWARESPI_H_
#define _HARDWARESPI_H_
/**
- * Defines the possible SPI communication speeds.
+ * @brief Defines the possible SPI communication speeds.
*/
typedef enum SPIFrequency {
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_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. */
+#define MAX_SPI_FREQS 8
+
+#if CYCLES_PER_MICROSECOND != 72
+/* TODO [0.2.0?] something smarter than this */
+#warn "Unexpected clock speed; SPI frequency calculation will be incorrect"
+#endif
+
+/**
+ * @brief Wirish SPI interface.
+ *
+ * This implementation uses software slave management, so the caller
+ * is responsible for controlling the slave select line.
+ */
class HardwareSPI {
- private:
- uint32 spi_num;
+public:
+ /**
+ * @param spiPortNumber Number of the SPI port to manage.
+ */
+ HardwareSPI(uint32 spiPortNumber);
+
+ /**
+ * @brief Turn on a SPI port and set its GPIO pin modes for use as master.
+ *
+ * SPI port is enabled in full duplex mode, with software slave management.
+ *
+ * @param frequency Communication frequency
+ * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST (big-endian)
+ * @param mode SPI mode to use, one of SPI_MODE_0, SPI_MODE_1,
+ * SPI_MODE_2, and SPI_MODE_3.
+ */
+ void begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode);
- public:
- HardwareSPI(uint32 spi_num);
+ /**
+ * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
+ */
void begin(void);
- void begin(SPIFrequency freq, uint32 endianness, uint32 mode);
+
+ /**
+ * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave.
+ *
+ * SPI port is enabled in full duplex mode, with software slave management.
+ *
+ * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian)
+ * @param mode SPI mode to use
+ */
+ void beginSlave(uint32 bitOrder, uint32 mode);
+
+ /**
+ * @brief Equivalent to beginSlave(MSBFIRST, 0).
+ */
+ void beginSlave(void);
+
+ /**
+ * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged.
+ */
+ void end(void);
+
+ /**
+ * @brief Return the next unread byte.
+ *
+ * If there is no unread byte waiting, this function will block
+ * until one is received.
+ */
+ uint8 read(void);
+
+ /**
+ * @brief Read length bytes, storing them into buffer.
+ * @param buffer Buffer to store received bytes into.
+ * @param length Number of bytes to store in buffer. This
+ * function will block until the desired number of
+ * bytes have been read.
+ */
+ void read(uint8 *buffer, uint32 length);
+
+ /**
+ * @brief Transmit a byte.
+ * @param data Byte to transmit.
+ */
+ void write(uint8 data);
+
+ /**
+ * @brief Transmit multiple bytes.
+ * @param buffer Bytes to transmit.
+ * @param length Number of bytes in buffer to transmit.
+ */
+ void write(const uint8 *buffer, uint32 length);
+
+ /**
+ * @brief Transmit a byte, then return the next unread byte.
+ *
+ * This function transmits before receiving.
+ *
+ * @param data Byte to transmit.
+ * @return Next unread byte.
+ */
+ uint8 transfer(uint8 data);
+
+ /* -- The following methods are deprecated --------------------------- */
+
+ /**
+ * @brief Deprecated.
+ *
+ * Use HardwareSPI::transfer() instead.
+ *
+ * @see HardwareSPI::transfer()
+ */
uint8 send(uint8 data);
+
+ /**
+ * @brief Deprecated.
+ *
+ * Use HardwareSPI::write() in combination with
+ * HardwareSPI::read() (or HardwareSPI::transfer()) instead.
+ *
+ * @see HardwareSPI::write()
+ * @see HardwareSPI::read()
+ * @see HardwareSPI::transfer()
+ */
uint8 send(uint8 *data, uint32 length);
+
+ /**
+ * @brief Deprecated.
+ *
+ * Use HardwareSPI::read() instead.
+ *
+ * @see HardwareSPI::read()
+ */
uint8 recv(void);
+private:
+ spi_dev *spi_d;
};
#endif
diff --git a/wirish/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp
index d6c7e82..5c9bff6 100644
--- a/wirish/comm/HardwareSerial.cpp
+++ b/wirish/comm/HardwareSerial.cpp
@@ -24,69 +24,86 @@
/**
* @file HardwareSerial.cpp
- *
- * @brief Wiring-like serial api
+ * @brief Wirish serial port implementation.
*/
-#include "wirish.h"
-#include "HardwareSerial.h"
-#include "usart.h"
#include "gpio.h"
-#include "timers.h"
+#include "timer.h"
+
+#include "HardwareSerial.h"
+#include "boards.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, TIMER_INVALID, 0);
-// TODO: High density device ports
+#define TX1 BOARD_USART1_TX_PIN
+#define RX1 BOARD_USART1_RX_PIN
+#define TX2 BOARD_USART2_TX_PIN
+#define RX2 BOARD_USART2_RX_PIN
+#define TX3 BOARD_USART3_TX_PIN
+#define RX3 BOARD_USART3_RX_PIN
+#if defined STM32_HIGH_DENSITY && !defined(BOARD_maple_RET6)
+#define TX4 BOARD_UART4_TX_PIN
+#define RX4 BOARD_UART4_RX_PIN
+#define TX5 BOARD_UART5_TX_PIN
+#define RX5 BOARD_UART5_RX_PIN
+#endif
-HardwareSerial::HardwareSerial(uint8 usart_num,
- uint32 max_baud,
- GPIO_Port *gpio_port,
+// TODO Put these magic numbers into boards.h #defines
+HardwareSerial Serial1(USART1, TX1, RX1, 72000000UL);
+HardwareSerial Serial2(USART2, TX2, RX2, 36000000UL);
+HardwareSerial Serial3(USART3, TX3, RX3, 36000000UL);
+#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
+HardwareSerial Serial4(UART4, TX4, RX4, 36000000UL);
+HardwareSerial Serial5(UART5, TX5, RX5, 36000000UL);
+#endif
+
+HardwareSerial::HardwareSerial(usart_dev *usart_device,
uint8 tx_pin,
uint8 rx_pin,
- timer_dev_num timer_num,
- uint8 compare_num) {
- this->usart_num = usart_num;
- this->max_baud = max_baud;
- this->gpio_port = gpio_port;
+ uint32 clock_speed) {
+ this->usart_device = usart_device;
+ this->clock_speed = clock_speed;
this->tx_pin = tx_pin;
this->rx_pin = rx_pin;
- this->timer_num = timer_num;
- this->compare_num = compare_num;
}
uint8 HardwareSerial::read(void) {
- return usart_getc(usart_num);
+ return usart_getc(usart_device);
}
uint32 HardwareSerial::available(void) {
- return usart_data_available(usart_num);
+ return usart_data_available(usart_device);
}
void HardwareSerial::write(unsigned char ch) {
- usart_putc(usart_num, ch);
+ usart_putc(usart_device, ch);
}
void HardwareSerial::begin(uint32 baud) {
- if (baud > max_baud) {
+ ASSERT(baud <= usart_device->max_baud);
+
+ if (baud > usart_device->max_baud) {
return;
}
- gpio_set_mode(gpio_port, tx_pin, GPIO_MODE_AF_OUTPUT_PP);
- gpio_set_mode(gpio_port, rx_pin, GPIO_MODE_INPUT_FLOATING);
+ const stm32_pin_info *txi = &PIN_MAP[tx_pin];
+ const stm32_pin_info *rxi = &PIN_MAP[rx_pin];
+
+ gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP);
+ gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING);
- 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);
+ if (txi->timer_device != NULL) {
+ /* Turn off any PWM if there's a conflict on this GPIO bit. */
+ timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED);
}
- usart_init(usart_num, baud);
+ usart_init(usart_device);
+ usart_set_baud_rate(usart_device, clock_speed, baud);
+ usart_enable(usart_device);
}
void HardwareSerial::end(void) {
- usart_disable(usart_num);
+ usart_disable(usart_device);
}
void HardwareSerial::flush(void) {
- usart_reset_rx(usart_num);
+ usart_reset_rx(usart_device);
}
diff --git a/wirish/comm/HardwareSerial.h b/wirish/comm/HardwareSerial.h
index aad8aa7..934db23 100644
--- a/wirish/comm/HardwareSerial.h
+++ b/wirish/comm/HardwareSerial.h
@@ -24,41 +24,34 @@
/**
* @file HardwareSerial.h
- *
- * @brief Wirish interface to hardware serial communications.
+ * @brief Wirish serial port interface.
*/
#ifndef _HARDWARESERIAL_H_
#define _HARDWARESERIAL_H_
-#include "timers.h"
+#include "libmaple_types.h"
+#include "usart.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. */
+/*
+ * IMPORTANT:
+ *
+ * This class documented "by hand" (i.e., not using Doxygen) in:
+ *
+ * libmaple/docs/source/lang/api/serial.rst
+ *
+ * If you alter the public HardwareSerial interface, you MUST update
+ * the documentation accordingly.
+ */
class HardwareSerial : public Print {
- private:
- uint8 usart_num;
- uint32 max_baud;
- GPIO_Port *gpio_port;
- uint8 tx_pin;
- uint8 rx_pin;
- timer_dev_num timer_num;
- uint8 compare_num;
- public:
- HardwareSerial(uint8 usart_num,
- uint32 max_baud,
- GPIO_Port *gpio_port,
+public:
+ HardwareSerial(usart_dev *usart_device,
uint8 tx_pin,
uint8 rx_pin,
- timer_dev_num timer_num,
- uint8 compare_num);
+ uint32 clock_speed);
void begin(uint32 baud);
void end(void);
uint32 available(void);
@@ -66,10 +59,19 @@ class HardwareSerial : public Print {
void flush(void);
virtual void write(unsigned char);
using Print::write;
+private:
+ usart_dev *usart_device;
+ uint8 tx_pin;
+ uint8 rx_pin;
+ uint32 clock_speed;
};
+
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
extern HardwareSerial Serial3;
-// TODO: high density device ports
+#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6)
+extern HardwareSerial Serial4;
+extern HardwareSerial Serial5;
#endif
+#endif
diff --git a/wirish/ext_interrupts.c b/wirish/ext_interrupts.cpp
index dd7c1a8..557fffd 100644
--- a/wirish/ext_interrupts.c
+++ b/wirish/ext_interrupts.cpp
@@ -28,52 +28,55 @@
* @brief Wiring-like interface for external interrupts
*/
-#include "wirish.h"
+#include "boards.h"
+#include "gpio.h"
#include "exti.h"
#include "ext_interrupts.h"
-/* Attach ISR handler on pin, triggering on the given mode. */
-void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
- uint8 outMode;
-
- /* Parameter checking */
- if (pin >= NR_GPIO_PINS) {
- return;
- }
+static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode);
- if (!handler) {
+/**
+ * @brief Attach an interrupt handler to a pin, triggering on the given mode.
+ * @param pin Pin to attach an interrupt handler onto.
+ * @param handler Function to call when the external interrupt is triggered.
+ * @param mode Trigger mode for the given interrupt.
+ * @see ExtIntTriggerMode
+ */
+void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
+ if (pin >= BOARD_NR_GPIO_PINS || !handler) {
return;
}
- switch (mode) {
- case RISING:
- outMode = EXTI_RISING;
- break;
- case FALLING:
- outMode = EXTI_FALLING;
- break;
- case CHANGE:
- outMode = EXTI_RISING_FALLING;
- break;
- default:
- ASSERT(0);
- return;
- }
+ exti_trigger_mode outMode = exti_out_mode(mode);
- exti_attach_interrupt(PIN_MAP[pin].exti_port,
- PIN_MAP[pin].pin,
+ exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit),
+ gpio_exti_port(PIN_MAP[pin].gpio_device),
handler,
- mode);
-
- return;
+ outMode);
}
-/* Disable any interrupts */
+/**
+ * @brief Disable any external interrupt attached to a pin.
+ * @param pin Pin number to detach any interrupt from.
+ */
void detachInterrupt(uint8 pin) {
- if (!(pin < NR_GPIO_PINS)) {
+ if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
- exti_detach_interrupt(PIN_MAP[pin].pin);
+ exti_detach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit));
}
+static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) {
+ switch (mode) {
+ case RISING:
+ return EXTI_RISING;
+ case FALLING:
+ return EXTI_FALLING;
+ case CHANGE:
+ return EXTI_RISING_FALLING;
+ }
+ // Can't happen
+ ASSERT(0);
+ return (exti_trigger_mode)0;
+}
diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h
index 304e267..7d20801 100644
--- a/wirish/ext_interrupts.h
+++ b/wirish/ext_interrupts.h
@@ -28,7 +28,7 @@
/**
* @file ext_interrupts.h
*
- * @brief External interrupt wiring prototypes and types
+ * @brief Wiring-like external interrupt prototypes and types.
*/
#ifndef _EXT_INTERRUPTS_H_
@@ -38,7 +38,7 @@
* The kind of transition on an external pin which should trigger an
* interrupt.
*/
-typedef enum ExtIntTriggerMode_ {
+typedef enum ExtIntTriggerMode {
RISING, /**< To trigger an interrupt when the pin transitions LOW
to HIGH */
FALLING, /**< To trigger an interrupt when the pin transitions
@@ -48,10 +48,6 @@ typedef enum ExtIntTriggerMode_ {
changes). */
} ExtIntTriggerMode;
-#ifdef __cplusplus
-extern "C"{
-#endif
-
/**
* @brief Registers an interrupt handler on a pin.
*
@@ -86,7 +82,7 @@ void detachInterrupt(uint8 pin);
*
* @see noInterrupts()
*/
-static ALWAYS_INLINE void interrupts() {
+static inline void interrupts() {
nvic_globalirq_enable();
}
@@ -100,14 +96,9 @@ static ALWAYS_INLINE void interrupts() {
*
* @see interrupts()
*/
-static ALWAYS_INLINE void noInterrupts() {
+static inline void noInterrupts() {
nvic_globalirq_disable();
}
-#ifdef __cplusplus
-}
-#endif
-
-
#endif
diff --git a/wirish/io.h b/wirish/io.h
index 2d22dcd..ace40f2 100644
--- a/wirish/io.h
+++ b/wirish/io.h
@@ -28,30 +28,16 @@
* @brief Arduino-compatible digital pin I/O interface.
*/
-#ifndef _IO_H
-#define _IO_H
+#ifndef _IO_H_
+#define _IO_H_
#include "gpio.h"
#include "adc.h"
-#include "time.h"
-#ifdef __cplusplus
-extern "C"{
-#endif
+#include "wirish_time.h"
/**
* 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 {
@@ -68,11 +54,11 @@ typedef enum WiringPinMode {
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
+ 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/
+ mode, no current is ever actually sourced
from the pin. */
INPUT, /**< Basic digital input. The pin voltage is sampled; when
@@ -118,8 +104,7 @@ typedef enum 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 pin Number of pin to configure.
* @param mode Mode corresponding to desired pin behavior.
* @see WiringPinMode
*/
@@ -127,10 +112,9 @@ void pinMode(uint8 pin, WiringPinMode mode);
/**
* Writes a (digital) value to a pin. The pin must have its
- * mode set to <code>OUTPUT</code> or <code>OUTPUT_OPEN_DRAIN</code>.
+ * mode set to OUTPUT or OUTPUT_OPEN_DRAIN.
*
- * @param pin Pin to write to. One of: 0-38 (pin numbers as labeled
- * on silkscreen), or D0-D38 (symbols for same)
+ * @param pin Pin to write to.
* @param value Either LOW (write a 0) or HIGH (write a 1).
* @see pinMode()
*/
@@ -140,8 +124,7 @@ 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)
+ * @param pin Pin to read from.
* @return LOW or HIGH.
* @see pinMode()
*/
@@ -150,18 +133,14 @@ 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.
+ * mode set to INPUT_ANALOG.
*
- * @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).
-
+ * @param pin Pin to read from.
+ * @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC
+ * conversion).
* @see pinMode()
*/
-uint32 analogRead(uint8 pin);
+uint16 analogRead(uint8 pin);
/**
* Toggles the digital value at the given pin.
@@ -211,17 +190,31 @@ uint8 isButtonPressed();
* 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.
+ * button is pressed. If timeout_millis is left out (or 0), wait
+ * forever.
*
* @return true, if the button was pressed; false, if the timeout was
* reached.
*
* @see pinMode()
*/
-uint8 waitForButtonPress(uint32 timeout_millis);
+uint8 waitForButtonPress(uint32 timeout_millis=0);
+
+/**
+ * Shift out a byte of data, one bit at a time.
+ *
+ * This function starts at either the most significant or least
+ * significant bit in a byte value, and shifts out each byte in order
+ * onto a data pin. After each bit is written to the data pin, a
+ * separate clock pin is pulsed to indicate that the new bit is
+ * available.
+ *
+ * @param dataPin Pin to shift data out on
+ * @param clockPin Pin to pulse after each bit is shifted out
+ * @param bitOrder Either MSBFIRST (big-endian) or LSBFIRST (little-endian).
+ * @param value Value to shift out
+ */
+void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value);
-#ifdef __cplusplus
-} // extern "C"
-#endif
#endif
diff --git a/wirish/main.cxx b/wirish/main.cxx
index f0158f8..dd5e296 100644
--- a/wirish/main.cxx
+++ b/wirish/main.cxx
@@ -1,4 +1,4 @@
-/* *****************************************************************************
+/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 LeafLabs LLC.
@@ -20,16 +20,15 @@
* 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.
- * ****************************************************************************/
+ *****************************************************************************/
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
+// Otherwise, statically allocated objects that need libmaple may fail.
__attribute__(( constructor )) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/wirish/pwm.c b/wirish/pwm.cpp
index 072e4cd..bf69bfb 100644
--- a/wirish/pwm.c
+++ b/wirish/pwm.cpp
@@ -23,26 +23,20 @@
*****************************************************************************/
/**
- * @brief Arduino-compatible PWM implementation.
+ * @brief Arduino-style PWM implementation.
*/
-#include "wirish.h"
-#include "timers.h"
-#include "io.h"
+#include "libmaple_types.h"
+#include "timer.h"
+
+#include "boards.h"
#include "pwm.h"
void pwmWrite(uint8 pin, uint16 duty_cycle) {
- TimerCCR ccr;
-
- if (pin >= NR_GPIO_PINS) {
- return;
- }
-
- ccr = PIN_MAP[pin].timer_ccr;
-
- if (ccr == 0) {
+ timer_dev *dev = PIN_MAP[pin].timer_device;
+ if (pin >= BOARD_NR_GPIO_PINS || dev == NULL || dev->type == TIMER_BASIC) {
return;
}
- timer_pwm_write_ccr(ccr, duty_cycle);
+ timer_set_compare(dev, PIN_MAP[pin].timer_channel, duty_cycle);
}
diff --git a/wirish/pwm.h b/wirish/pwm.h
index d0bc9e0..4ce4bb4 100644
--- a/wirish/pwm.h
+++ b/wirish/pwm.h
@@ -28,12 +28,8 @@
* @brief Arduino-compatible PWM interface.
*/
-#ifndef _PWM_H
-#define _PWM_H
-
-#ifdef __cplusplus
-extern "C"{
-#endif
+#ifndef _PWM_H_
+#define _PWM_H_
/**
* As a convenience, analogWrite is an alias of pwmWrite to ease
@@ -47,13 +43,11 @@ extern "C"{
*
* User code is expected to determine and honor the maximum value
* (based on the configured period).
+ *
+ * @param pin PWM output pin
+ * @param duty_cycle Duty cycle to set.
*/
void pwmWrite(uint8 pin, uint16 duty_cycle);
-#ifdef __cplusplus
-}
-#endif
-
-
#endif
diff --git a/wirish/rules.mk b/wirish/rules.mk
index cb5a69f..6999288 100644
--- a/wirish/rules.mk
+++ b/wirish/rules.mk
@@ -4,30 +4,36 @@ dirstack_$(sp) := $(d)
d := $(dir)
BUILDDIRS += $(BUILD_PATH)/$(d)
BUILDDIRS += $(BUILD_PATH)/$(d)/comm
+BUILDDIRS += $(BUILD_PATH)/$(d)/boards
-WIRISH_INCLUDES := -I$(d) -I$(d)/comm
+WIRISH_INCLUDES := -I$(d) -I$(d)/comm -I$(d)/boards
# Local flags
CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES)
# Local rules and targets
-cSRCS_$(d) := wirish.c \
- wirish_shift.c \
- wirish_analog.c \
- time.c \
- pwm.c \
- ext_interrupts.c \
- wirish_digital.c
-
-cppSRCS_$(d) := wirish_math.cpp \
- Print.cpp \
- comm/HardwareSerial.cpp \
- comm/HardwareSPI.cpp \
- usb_serial.cpp \
- HardwareTimer.cpp \
- cxxabi-compat.cpp \
-
-cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
+cSRCS_$(d) :=
+
+cppSRCS_$(d) := wirish_math.cpp \
+ Print.cpp \
+ boards.cpp \
+ boards/maple.cpp \
+ boards/maple_mini.cpp \
+ boards/maple_native.cpp \
+ boards/maple_RET6.cpp \
+ comm/HardwareSerial.cpp \
+ comm/HardwareSPI.cpp \
+ HardwareTimer.cpp \
+ usb_serial.cpp \
+ cxxabi-compat.cpp \
+ wirish_shift.cpp \
+ wirish_analog.cpp \
+ wirish_time.cpp \
+ pwm.cpp \
+ ext_interrupts.cpp \
+ wirish_digital.cpp
+
+cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%)
OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \
diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp
index e2cdee3..0a2be43 100644
--- a/wirish/usb_serial.cpp
+++ b/wirish/usb_serial.cpp
@@ -3,28 +3,29 @@
*
* Copyright (c) 2010 Perry Hung.
*
- * 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
+ * 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 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.
+ * 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 Wirish USB class for easy communication, uses libmaple's
- * virtual com port implementation
+ * @brief USB virtual serial terminal
*/
#include <string.h>
@@ -34,7 +35,7 @@
#define USB_TIMEOUT 50
-USBSerial :: USBSerial(void) {
+USBSerial::USBSerial(void) {
}
void USBSerial::begin(void) {
@@ -46,54 +47,29 @@ void USBSerial::end(void) {
}
void USBSerial::write(uint8 ch) {
- if(!(usbIsConnected() && usbIsConfigured())) {
- return;
- }
-
- uint16 status = 0;
- uint32 start = millis();
-
- while(status == 0 && (millis() - start <= USB_TIMEOUT)) {
- status = usbSendBytes(&ch, 1);
- }
+ const uint8 buf[] = {ch};
+ this->write(buf, 1);
}
void USBSerial::write(const char *str) {
- if(!(usbIsConnected() && usbIsConfigured())) {
- return;
- }
-
- uint32 len = strlen(str);
- uint16 status = 0;
- uint16 oldstatus = 0;
- uint32 start = millis();
-
- while(status < len && (millis() - start < USB_TIMEOUT)) {
- status += usbSendBytes((uint8*)str+status, len-status);
- if(oldstatus != status)
- start = millis();
- oldstatus = status;
- }
+ this->write(str, strlen(str));
}
-void USBSerial::write(void *buf, uint32 size) {
- if(!(usbIsConnected() && usbIsConfigured())) {
+void USBSerial::write(const void *buf, uint32 len) {
+ if (!(usbIsConnected() && usbIsConfigured()) || !buf) {
return;
}
- if (!buf) {
- return;
- }
-
- uint16 status = 0;
- uint16 oldstatus = 0;
+ uint32 txed = 0;
+ uint32 old_txed = 0;
uint32 start = millis();
- while(status < size && (millis() - start < USB_TIMEOUT)) {
- status += usbSendBytes((uint8*)buf+status, size-status);
- if(oldstatus != status)
+ while (txed < len && (millis() - start < USB_TIMEOUT)) {
+ txed += usbSendBytes((const uint8*)buf + txed, len - txed);
+ if (old_txed != txed) {
start = millis();
- oldstatus = status;
+ }
+ old_txed = txed;
}
}
@@ -101,47 +77,40 @@ uint32 USBSerial::available(void) {
return usbBytesAvailable();
}
-/* blocks forever until len_bytes is received */
uint32 USBSerial::read(void *buf, uint32 len) {
if (!buf) {
return 0;
}
- uint32 bytes_in = 0;
- while (len > 0) {
- uint32 new_bytes = usbReceiveBytes((uint8*)((uint8*)buf+bytes_in), len);
- len -= new_bytes;
- bytes_in += new_bytes;
+ uint32 rxed = 0;
+ while (rxed < len) {
+ rxed += usbReceiveBytes((uint8*)buf + rxed, len - rxed);
}
- return len;
+ return rxed;
}
-/* blocks forever until 1 byte is received */
+/* Blocks forever until 1 byte is received */
uint8 USBSerial::read(void) {
- uint8 ch;
-
- while (usbReceiveBytes(&ch, 1) == 0);
- return ch;
+ uint8 buf[1];
+ this->read(buf, 1);
+ return buf[0];
}
uint8 USBSerial::pending(void) {
return usbGetPending();
}
-// TODO deprecate the crap out of this
+uint8 USBSerial::isConnected(void) {
+ return usbIsConnected() && usbIsConfigured();
+}
+
uint8 USBSerial::getDTR(void) {
return usbGetDTR();
}
-// TODO deprecate the crap out of this
uint8 USBSerial::getRTS(void) {
return usbGetRTS();
}
-uint8 USBSerial::isConnected(void) {
- return (usbIsConnected() && usbIsConfigured());
-}
-
USBSerial SerialUSB;
-
diff --git a/wirish/usb_serial.h b/wirish/usb_serial.h
index c228837..ba9e18c 100644
--- a/wirish/usb_serial.h
+++ b/wirish/usb_serial.h
@@ -23,8 +23,7 @@
*****************************************************************************/
/**
- * @brief wirish usb class for easy goin communication, uses libmaple's
- * virtual com port implementation
+ * @brief Wirish virtual serial port
*/
#ifndef _USB_SERIAL_H_
@@ -32,6 +31,9 @@
#include "Print.h"
+/**
+ * @brief Virtual serial terminal.
+ */
class USBSerial : public Print {
public:
USBSerial(void);
@@ -46,7 +48,7 @@ public:
void write(uint8);
void write(const char *str);
- void write(void *, uint32);
+ void write(const void*, uint32);
uint8 getRTS();
uint8 getDTR();
diff --git a/wirish/wirish.c b/wirish/wirish.c
deleted file mode 100644
index aaae9d4..0000000
--- a/wirish/wirish.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- * The MIT License
- *
- * Copyright (c) 2010 Perry Hung.
- *
- * 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 generic maple board bring up:
- *
- * By default, we bring up all maple boards running on the stm32 to 72mhz,
- * clocked off the PLL, driven by the 8MHz external crystal.
- *
- * AHB and APB2 are clocked at 72MHz
- * APB1 is clocked at 36MHz
- */
-
-#include "wirish.h"
-#include "systick.h"
-#include "gpio.h"
-#include "nvic.h"
-#include "usb.h"
-#include "rcc.h"
-#include "fsmc.h"
-#include "dac.h"
-#include "flash.h"
-
-void init(void) {
- /* make sure the flash is ready before spinning the high speed clock up */
- flash_enable_prefetch();
- flash_set_latency(FLASH_WAIT_STATE_2);
-
-#if NR_FSMC > 0
- fsmc_native_sram_init();
-#endif
-
-#if NR_DAC_PINS > 0
- dac_init();
-#endif
-
- /* initialize clocks */
- rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9);
- rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
- rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
- rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
-
- nvic_init();
- systick_init(SYSTICK_RELOAD_VAL);
- gpio_init();
- /* Initialize the ADC for slow conversions, to allow for high
- impedance inputs. */
- adc_init(ADC_SMPR_55_5);
- timer_init(TIMER1, 1);
- timer_init(TIMER2, 1);
- timer_init(TIMER3, 1);
- timer_init(TIMER4, 1);
-#if NR_TIMERS >= 8
- timer_init(TIMER5, 1);
- 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 311c74f..82a9897 100644
--- a/wirish/wirish.h
+++ b/wirish/wirish.h
@@ -32,25 +32,20 @@
#define _WIRISH_H_
#include "libmaple.h"
+
+#include "wirish_types.h"
#include "boards.h"
-#include "time.h"
-#include "timers.h"
#include "io.h"
#include "bits.h"
#include "pwm.h"
#include "ext_interrupts.h"
+#include "wirish_debug.h"
#include "wirish_math.h"
-
-#ifdef __cplusplus
+#include "wirish_time.h"
#include "HardwareSPI.h"
#include "HardwareSerial.h"
-#include "usb_serial.h"
#include "HardwareTimer.h"
-#endif
-
-#ifdef __cplusplus
-extern "C"{
-#endif
+#include "usb_serial.h"
/* Arduino wiring macros and bit defines */
#define HIGH 0x1
@@ -74,12 +69,5 @@ extern "C"{
typedef uint8 boolean;
typedef uint8 byte;
-void init(void);
-void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, byte val);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
#endif
diff --git a/wirish/wirish_analog.c b/wirish/wirish_analog.cpp
index 3c63342..8756caf 100644
--- a/wirish/wirish_analog.c
+++ b/wirish/wirish_analog.cpp
@@ -31,11 +31,12 @@
#include "io.h"
/* Assumes that the ADC has been initialized and that the pin is set
- * to ANALOG_INPUT */
-uint32 analogRead(uint8 pin) {
- if(PIN_MAP[pin].adc == ADC_INVALID) {
+ * to INPUT_ANALOG */
+uint16 analogRead(uint8 pin) {
+ const adc_dev *dev = PIN_MAP[pin].adc_device;
+ if (dev == NULL) {
return 0;
}
- return adc_read(PIN_MAP[pin].adc);
+ return adc_read(dev, PIN_MAP[pin].adc_channel);
}
diff --git a/wirish/wirish_debug.h b/wirish/wirish_debug.h
new file mode 100644
index 0000000..d4c0bab
--- /dev/null
+++ b/wirish/wirish_debug.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file wirish_debug.h
+ * @brief High level debug port configuration
+ */
+
+/**
+ * @brief Disable the JTAG and Serial Wire (SW) debug ports.
+ *
+ * You can call this function in order to use the JTAG and SW debug
+ * pins as ordinary GPIOs.
+ *
+ * @see enableDebugPorts()
+ */
+static inline void disableDebugPorts(void) {
+ afio_cfg_debug_ports(AFIO_DEBUG_NONE);
+}
+
+/**
+ * @brief Enable the JTAG and Serial Wire (SW) debug ports.
+ *
+ * After you call this function, the JTAG and SW debug pins will no
+ * longer be usable as GPIOs.
+ *
+ * @see disableDebugPorts()
+ */
+static inline void enableDebugPorts(void) {
+ afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ);
+}
diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.cpp
index bb28f0a..9b9f175 100644
--- a/wirish/wirish_digital.c
+++ b/wirish/wirish_digital.cpp
@@ -30,39 +30,39 @@
#include "io.h"
void pinMode(uint8 pin, WiringPinMode mode) {
- uint8 outputMode;
+ gpio_pin_mode outputMode;
boolean pwm = false;
- if (pin >= NR_GPIO_PINS) {
+ if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
switch(mode) {
case OUTPUT:
- outputMode = GPIO_MODE_OUTPUT_PP;
+ outputMode = GPIO_OUTPUT_PP;
break;
case OUTPUT_OPEN_DRAIN:
- outputMode = GPIO_MODE_OUTPUT_OD;
+ outputMode = GPIO_OUTPUT_OD;
break;
case INPUT:
case INPUT_FLOATING:
- outputMode = GPIO_MODE_INPUT_FLOATING;
+ outputMode = GPIO_INPUT_FLOATING;
break;
case INPUT_ANALOG:
- outputMode = GPIO_MODE_INPUT_ANALOG;
+ outputMode = GPIO_INPUT_ANALOG;
break;
case INPUT_PULLUP:
- outputMode = GPIO_MODE_INPUT_PU;
+ outputMode = GPIO_INPUT_PU;
break;
case INPUT_PULLDOWN:
- outputMode = GPIO_MODE_INPUT_PD;
+ outputMode = GPIO_INPUT_PD;
break;
case PWM:
- outputMode = GPIO_MODE_AF_OUTPUT_PP;
+ outputMode = GPIO_AF_OUTPUT_PP;
pwm = true;
break;
case PWM_OPEN_DRAIN:
- outputMode = GPIO_MODE_AF_OUTPUT_OD;
+ outputMode = GPIO_AF_OUTPUT_OD;
pwm = true;
break;
default:
@@ -70,51 +70,48 @@ void pinMode(uint8 pin, WiringPinMode mode) {
return;
}
- 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);
- }
+ gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode);
+
+ if (PIN_MAP[pin].timer_device != NULL) {
+ /* Enable/disable timer channels if we're switching into or
+ * out of PWM. */
+ timer_set_mode(PIN_MAP[pin].timer_device,
+ PIN_MAP[pin].timer_channel,
+ pwm ? TIMER_PWM : TIMER_DISABLED);
}
}
uint32 digitalRead(uint8 pin) {
- if (pin >= NR_GPIO_PINS) {
+ if (pin >= BOARD_NR_GPIO_PINS) {
return 0;
}
- return gpio_read_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin);
+ return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ?
+ HIGH : LOW;
}
void digitalWrite(uint8 pin, uint8 val) {
- if (pin >= NR_GPIO_PINS) {
+ if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
- gpio_write_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin, val);
+ gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
}
void togglePin(uint8 pin) {
- if (pin >= NR_GPIO_PINS) {
+ if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
-
- gpio_toggle_pin(PIN_MAP[pin].port, PIN_MAP[pin].pin);
+
+ gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit);
}
+#define BUTTON_DEBOUNCE_DELAY 1
+
uint8 isButtonPressed() {
if (digitalRead(BOARD_BUTTON_PIN)) {
- delay(1);
+ delay(BUTTON_DEBOUNCE_DELAY);
while (digitalRead(BOARD_BUTTON_PIN))
;
return true;
diff --git a/wirish/wirish_math.h b/wirish/wirish_math.h
index 14614ba..f9062af 100644
--- a/wirish/wirish_math.h
+++ b/wirish/wirish_math.h
@@ -24,7 +24,7 @@
/**
* @file wirish_math.h
- * @brief Includes cmath; provides Arduino-compatible math routines.
+ * @brief Includes <math.h>; provides Arduino-compatible math routines.
*/
#ifndef _WIRING_MATH_H_
@@ -32,8 +32,6 @@
#include <math.h>
-#ifdef __cplusplus
-
/**
* @brief Initialize the pseudo-random number generator.
* @param seed the number used to initialize the seed; cannot be zero.
@@ -78,8 +76,7 @@ long random(long min, long max);
* @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,
+static inline long map(long value, long fromStart, long fromEnd,
long toStart, long toEnd) {
return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) +
toStart;
@@ -103,9 +100,7 @@ inline long map(long value, long fromStart, long fromEnd,
#ifdef abs
#undef abs
#endif
-#define abs(x) (((x) > 0) ? (x) : -(unsigned)(x))
-
-#endif
+#define abs(x) (((x) > 0) ? (x) : -(x))
/* Following are duplicate declarations (with Doxygen comments) for
* some of the math.h functions; this is for the convenience of the
diff --git a/wirish/wirish_shift.c b/wirish/wirish_shift.cpp
index f67364d..f67364d 100644
--- a/wirish/wirish_shift.c
+++ b/wirish/wirish_shift.cpp
diff --git a/wirish/time.c b/wirish/wirish_time.cpp
index c0a0649..2771e95 100644
--- a/wirish/time.c
+++ b/wirish/wirish_time.cpp
@@ -28,7 +28,8 @@
#include "libmaple.h"
#include "systick.h"
-#include "time.h"
+#include "wirish_time.h"
+#include "delay.h"
void delay(unsigned long ms) {
uint32 i;
@@ -38,15 +39,5 @@ void delay(unsigned long ms) {
}
void delayMicroseconds(uint32 us) {
- /* So (2^32)/12 micros max, or less than 6 minutes */
- us *= 12;
-
- /* fudge for function call overhead */
- us--;
- asm volatile(" mov r0, %[us] \n\t"
- "1: subs r0, #1 \n\t"
- " bhi 1b \n\t"
- :
- : [us] "r" (us)
- : "r0");
+ delay_us(us);
}
diff --git a/wirish/time.h b/wirish/wirish_time.h
index 8d3d074..d5349e3 100644
--- a/wirish/time.h
+++ b/wirish/wirish_time.h
@@ -23,22 +23,18 @@
*****************************************************************************/
/**
- * @file time.h
+ * @file wirish_time.h
* @brief Timing and delay functions.
*/
-#ifndef _TIME_H
-#define _TIME_H
+#ifndef _TIME_H_
+#define _TIME_H_
#include "libmaple.h"
#include "nvic.h"
#include "systick.h"
#include "boards.h"
-#ifdef __cplusplus
-extern "C"{
-#endif
-
#define US_PER_MS 1000
/**
@@ -60,17 +56,15 @@ static inline uint32 micros(void) {
uint32 cycle_cnt;
uint32 res;
- nvic_globalirq_disable();
-
- cycle_cnt = systick_get_count();
- ms = millis();
-
- nvic_globalirq_enable();
+ do {
+ cycle_cnt = systick_get_count();
+ ms = millis();
+ } while (ms != millis());
/* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it
actually takes to complete a SysTick reload */
res = (ms * US_PER_MS) +
- (SYSTICK_RELOAD_VAL + 1 - cycle_cnt)/CYCLES_PER_MICROSECOND;
+ (SYSTICK_RELOAD_VAL + 1 - cycle_cnt) / CYCLES_PER_MICROSECOND;
return res;
}
@@ -99,10 +93,4 @@ void delay(unsigned long ms);
*/
void delayMicroseconds(uint32 us);
-#ifdef __cplusplus
-} // extern "C"
#endif
-
-
-#endif
-
diff --git a/wirish/wirish_types.h b/wirish/wirish_types.h
new file mode 100644
index 0000000..39efae0
--- /dev/null
+++ b/wirish/wirish_types.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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.
+ *****************************************************************************/
+
+/**
+ * @file wirish_types.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Wirish library type definitions.
+ */
+
+#include "libmaple_types.h"
+#include "gpio.h"
+#include "timer.h"
+#include "adc.h"
+
+#ifndef _WIRISH_TYPES_H_
+#define _WIRISH_TYPES_H_
+
+/**
+ * Invalid stm32_pin_info adc_channel value.
+ * @see stm32_pin_info
+ */
+#define ADCx 0xFF
+
+/**
+ * @brief Stores STM32-specific information related to a given Maple pin.
+ * @see PIN_MAP
+ */
+typedef struct stm32_pin_info {
+ gpio_dev *gpio_device; /**< Maple pin's GPIO device */
+ timer_dev *timer_device; /**< Pin's timer device, if any. */
+ const adc_dev *adc_device; /**< ADC device, if any. */
+ uint8 gpio_bit; /**< Pin's GPIO port bit. */
+ uint8 timer_channel; /**< Timer channel, or 0 if none. */
+ uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */
+} stm32_pin_info;
+
+/**
+ * Variable attribute, instructs the linker to place the marked
+ * variable in Flash instead of RAM. */
+#define __FLASH__ __attr_flash
+
+#endif