diff options
author | Florian Pritz <bluewind@xinu.at> | 2013-02-11 22:58:16 +0100 |
---|---|---|
committer | Florian Pritz <bluewind@xinu.at> | 2013-02-11 22:59:53 +0100 |
commit | 5b1afe32cf7496acea8182278aca83f59e8384e3 (patch) | |
tree | d1c0cadb01a5d638bb12251d488b7beef8a156d0 /lib/msp430/wiring.c | |
parent | 4e50c8291bd83a3fbb24a209fd1f6c7cbdb5283c (diff) | |
download | mpd-box-5b1afe32cf7496acea8182278aca83f59e8384e3.tar.gz mpd-box-5b1afe32cf7496acea8182278aca83f59e8384e3.tar.xz |
Make code launchpad/energia compatible
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'lib/msp430/wiring.c')
-rw-r--r-- | lib/msp430/wiring.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/lib/msp430/wiring.c b/lib/msp430/wiring.c new file mode 100644 index 0000000..058b2ac --- /dev/null +++ b/lib/msp430/wiring.c @@ -0,0 +1,223 @@ +/* + ************************************************************************ + * wiring.c + * + * Arduino core files for MSP430 + * Copyright (c) 2012 Robert Wessels. All right reserved. + * + * + *********************************************************************** + Derived from: + wiring.c - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + 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. + + 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. + + 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 +*/ +#include "Energia.h" + +void initClocks(void); +void enableWatchDogIntervalMode(void); + +void init() +{ + disableWatchDog(); + initClocks(); + enableWatchDogIntervalMode(); + /* Clear P2.6 and P2.7 bits to default to GPIO */ +#ifdef P2SEL2_ + P2SEL &= ~(BIT6|BIT7); +#endif + __eint(); +} + +void disableWatchDog() +{ + /* Diable watchdog timer */ + WDTCTL = WDTPW | WDTHOLD; +} + +void enableWatchDog() +{ + enableWatchDogIntervalMode(); +} + +/* WDT_TICKS_PER_MILISECOND = (F_CPU / WDT_DIVIDER) / 1000 + * WDT_TICKS_PER_MILISECONDS = 1.953125 = 2 */ +#define SMCLK_FREQUENCY F_CPU +#define WDT_TICKS_PER_MILISECOND (2*SMCLK_FREQUENCY/1000000) +#define WDT_DIV_BITS WDT_MDLY_0_5 + +void enableWatchDogIntervalMode(void) +{ + /* WDT Password + WDT interval mode + Watchdog clock source /512 + source from SMCLK + * Note that we WDT is running in interval mode. WDT will not trigger a reset on expire in this mode. */ + WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDT_DIV_BITS; + + /* WDT interrupt enable */ +#ifdef __MSP430_HAS_SFR__ + SFRIE1 |= WDTIE; +#else + IE1 |= WDTIE; +#endif +} + +void initClocks(void) +{ +#ifdef __MSP430_HAS_BC2__ +#if defined(CALBC1_16MHZ_) && F_CPU >= 16000000L + BCSCTL1 = CALBC1_16MHZ; + DCOCTL = CALDCO_16MHZ; +#elif defined(CALBC1_12MHZ_) && (F_CPU >= 12000000L) + BCSCTL1 = CALBC1_12MHZ; + DCOCTL = CALDCO_12MHZ; +#elif defined(CALBC1_8MHZ_) && (F_CPU >= 8000000L) + BCSCTL1 = CALBC1_8MHZ; + DCOCTL = CALDCO_8MHZ; +#elif defined(CALBC1_1MHZ_) && (F_CPU >= 1000000L) + BCSCTL1 = CALBC1_1MHZ; + DCOCTL = CALDCO_1MHZ; +#else + #warning No Suitable Frequency found! +#endif + /* SMCLK = DCO / DIVS = nMHz */ + BCSCTL2 &= ~(DIVS_0); + /* ACLK = VLO = ~ 12 KHz */ + BCSCTL3 |= LFXT1S_2; +#endif + +#ifdef __MSP430_HAS_CS__ + CSCTL0 = CSKEY; // Enable Access to CS Registers + + CSCTL2 &= ~SELM_7; // Clear selected Main CLK Source + CSCTL2 |= SELM__DCOCLK; // Use DCO as Main Clock Source + CSCTL3 &= ~(DIVM_3 | DIVS_3); // clear DIVM Bits +#if F_CPU >= 24000000L + CSCTL1 = DCOFSEL0 | DCOFSEL1 | DCORSEL; //Level 2 / Range 1 : 24.0MHz +#elif F_CPU >= 16000000L + CSCTL1 = DCORSEL; //Level 0 / Range 1 : 16.0MHz +#elif F_CPU >= 12000000L + CSCTL1 = DCOFSEL0 | DCOFSEL1 | DCORSEL; //Level 2 / Range 1 : 24.0MHz + CSCTL3 |= DIVM_1; // Div = 2 +#elif F_CPU >= 8000000L + CSCTL1 = DCOFSEL0 | DCOFSEL1; //Level 2 / Range 0 : 8.0MHz +#elif F_CPU >= 1000000L + CSCTL1 = DCOFSEL0 | DCOFSEL1; //Level 2 / Range 0 : 8.0MHz + CSCTL3 |= DIVM_3; // Div = 8 +#else + #warning No Suitable Frequency found! +#endif +// CSCTL0 = 0; // Disable Access to CS Registers +#endif // __MSP430_HAS_CS__ + +} +volatile uint32_t wdtCounter = 0; + +unsigned long micros() +{ + return (1000 * wdtCounter) / WDT_TICKS_PER_MILISECOND; +} + +unsigned long millis() +{ + return wdtCounter / WDT_TICKS_PER_MILISECOND; +} + +/* Delay for the given number of microseconds. Assumes a 1, 8 or 16 MHz clock. */ +void delayMicroseconds(unsigned int us) +{ +#if F_CPU >= 20000000L + /* For a one-microsecond delay, simply wait 2 cycle and return. The overhead + * of the function call yields a delay of exactly one microsecond. */ + __asm__ __volatile__ ( + "nop" "\n\t" + "nop"); + if (--us == 0) + return; + + /* The following loop takes a 1/5 of a microsecond (4 cycles) + * per iteration, so execute it five times for each microsecond of + * delay requested. */ + us = (us<<2) + us; // x5 us + + /* Account for the time taken in the preceeding commands. */ + us -= 2; + +#elif F_CPU >= 16000000L + /* For the 16 MHz clock on most boards */ + + /* For a one-microsecond delay, simply return. the overhead + * of the function call yields a delay of approximately 1 1/8 us. */ + if (--us == 0) + return; + + /* The following loop takes a quarter of a microsecond (4 cycles) + * per iteration, so execute it four times for each microsecond of + * delay requested. */ + us <<= 2; + + /* Account for the time taken in the preceeding commands. */ + us -= 2; +#else + /* For the 1 MHz */ + + /* For a one- or two-microsecond delay, simply return. the overhead of + * the function calls takes more than two microseconds. can't just + * subtract two, since us is unsigned; we'd overflow. */ + if (--us == 0) + return; + if (--us == 0) + return; + + /* The following loop takes 4 microsecond (4 cycles) + * per iteration, so execute it ones for each 4 microsecond of + * delay requested. */ + us >>= 2; + + /* Partially compensate for the time taken by the preceeding commands. + * we can't subtract any more than this or we'd overflow w/ small delays. */ + us--; +#endif + + /* Busy wait */ + __asm__ __volatile__ ( + /* even steven */ + "L1: nop \n\t" + /* 1 instruction */ + "dec.w %[us] \n\t" + /* 2 instructions */ + "jnz L1 \n\t" + : [us] "=r" (us) : "[us]" (us) + ); +} + +/* (ab)use the WDT */ +void delay(uint32_t milliseconds) +{ + uint32_t wakeTime = wdtCounter + (milliseconds * WDT_TICKS_PER_MILISECOND); + while(wdtCounter < wakeTime) + /* Wait for WDT interrupt in LMP0 */ + __bis_status_register(LPM0_bits+GIE); +} + +__attribute__((interrupt(WDT_VECTOR))) +void watchdog_isr (void) +{ + wdtCounter++; + /* Exit from LMP3 on reti (this includes LMP0) */ + __bic_status_register_on_exit(LPM3_bits); +} |