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