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