summaryrefslogtreecommitdiffstats
path: root/lib/msp430
diff options
context:
space:
mode:
Diffstat (limited to 'lib/msp430')
-rw-r--r--lib/msp430/Arduino.h4
-rw-r--r--lib/msp430/Energia.h231
-rw-r--r--lib/msp430/HardwareSerial.cpp237
-rw-r--r--lib/msp430/HardwareSerial.h69
-rw-r--r--lib/msp430/Print.cpp252
-rw-r--r--lib/msp430/Print.h85
-rw-r--r--lib/msp430/Printable.h40
-rw-r--r--lib/msp430/Stream.cpp246
-rw-r--r--lib/msp430/Stream.h94
-rw-r--r--lib/msp430/TimerSerial.cpp272
-rw-r--r--lib/msp430/TimerSerial.h78
-rwxr-xr-xlib/msp430/Tone.cpp223
-rw-r--r--lib/msp430/WCharacter.h170
-rw-r--r--lib/msp430/WInterrupts.c138
-rw-r--r--lib/msp430/WMath.cpp65
-rw-r--r--lib/msp430/WString.cpp649
-rw-r--r--lib/msp430/WString.h204
-rw-r--r--lib/msp430/Wire.cpp307
-rw-r--r--lib/msp430/Wire.h94
-rw-r--r--lib/msp430/binary.h515
-rw-r--r--lib/msp430/main.cpp16
-rw-r--r--lib/msp430/new.cpp18
-rw-r--r--lib/msp430/new.h22
-rw-r--r--lib/msp430/random.c90
-rw-r--r--lib/msp430/twi.c850
-rw-r--r--lib/msp430/twi.h104
-rw-r--r--lib/msp430/usci_isr_handler.c59
-rw-r--r--lib/msp430/usci_isr_handler.h18
-rw-r--r--lib/msp430/wiring.c223
-rw-r--r--lib/msp430/wiring_analog.c297
-rw-r--r--lib/msp430/wiring_digital.c181
-rw-r--r--lib/msp430/wiring_private.h60
-rwxr-xr-xlib/msp430/wiring_pulse.c76
-rwxr-xr-xlib/msp430/wiring_shift.c63
34 files changed, 6050 insertions, 0 deletions
diff --git a/lib/msp430/Arduino.h b/lib/msp430/Arduino.h
new file mode 100644
index 0000000..5f3919f
--- /dev/null
+++ b/lib/msp430/Arduino.h
@@ -0,0 +1,4 @@
+// Stub for Arduino header file - For added compatibility with existing arduino libraries
+// Include Energia instead
+#include "Energia.h"
+
diff --git a/lib/msp430/Energia.h b/lib/msp430/Energia.h
new file mode 100644
index 0000000..facfd06
--- /dev/null
+++ b/lib/msp430/Energia.h
@@ -0,0 +1,231 @@
+#ifndef Energia_h
+#define Energia_h
+
+#include <msp430.h>
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+
+#include "binary.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define NOT_A_PORT 0
+#define NOT_A_PIN 0
+#define NOT_ON_TIMER 0
+
+#define HIGH 0x1
+#define LOW 0x0
+
+#define LSBFIRST 0
+#define MSBFIRST 1
+
+#define CHANGE 1
+#define FALLING 2
+#define RISING 3
+
+#define INPUT 0x0
+#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
+#define INPUT_PULLDOWN 0x4
+#define PORT_SELECTION0 0x10
+#define PORT_SELECTION1 0x20
+
+
+#define true 0x1
+#define false 0x0
+
+#define PI 3.1415926535897932384626433832795
+#define HALF_PI 1.5707963267948966192313216916398
+#define TWO_PI 6.283185307179586476925286766559
+#define DEG_TO_RAD 0.017453292519943295769236907684886
+#define RAD_TO_DEG 57.295779513082320876798154814105
+
+#if defined(__MSP430_HAS_ADC10__)
+#define DEFAULT SREF_0
+#define INTERNAL1V5 SREF_1 + REFON
+#define INTERNAL2V5 SREF_1 + REFON + REF2_5V
+#define EXTERNAL SREF_2
+#endif
+
+#if defined(__MSP430_HAS_ADC10_B__)
+#define DEFAULT ADC10SREF_0
+#define INTERNAL1V5 ADC10SREF_1 + REFON + REFVSEL_0
+#define INTERNAL2V5 ADC10SREF_1 + REFON + REFVSEL_2
+#define EXTERNAL ADC10SREF_2
+#endif
+
+enum{
+ P1 = 1,
+ P2,
+#ifdef __MSP430_HAS_PORT3_R__
+ P3,
+#endif
+#ifdef __MSP430_HAS_PORT4_R__
+ P4,
+#endif
+#ifdef __MSP430_HAS_PORT5_R__
+ P5,
+#endif
+#ifdef __MSP430_HAS_PORT6_R__
+ P6,
+#endif
+#ifdef __MSP430_HAS_PORT7_R__
+ P7,
+#endif
+#ifdef __MSP430_HAS_PORTJ_R__
+ PJ,
+#endif
+ };
+
+enum{
+ T0A0,
+ T0A1,
+ T0A2,
+ T1A0,
+ T1A1,
+ T1A2,
+ T1A3,
+ T1A4,
+ T1A5,
+ T2A0,
+ T2A1,
+ T2A2,
+ T0B0,
+ T0B1,
+ T0B2,
+ T1B0,
+ T1B1,
+ T1B2,
+ T2B0,
+ T2B1,
+ T2B2
+ };
+
+typedef uint8_t boolean;
+typedef uint8_t byte;
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+#define radians(deg) ((deg)*DEG_TO_RAD)
+#define degrees(rad) ((rad)*RAD_TO_DEG)
+#define sq(x) ((x)*(x))
+
+#define interrupts() __bis_SR_register(GIE)
+#define noInterrupts() __bic_SR_register(GIE)
+
+#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
+#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
+#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
+
+#define lowByte(w) ((uint8_t) ((w) & 0xff))
+#define highByte(w) ((uint8_t) ((w) >> 8))
+
+#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
+#define bitSet(value, bit) ((value) |= (1UL << (bit)))
+#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
+#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
+
+
+typedef unsigned int word;
+
+#define bit(b) (1UL << (b))
+
+void init(void);
+void setup(void);
+void loop(void);
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
+uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
+void pinMode(uint8_t, uint8_t);
+void pinMode_int(uint8_t, uint8_t);
+void digitalWrite(uint8_t, uint8_t);
+int digitalRead(uint8_t);
+uint16_t analogRead(uint8_t);
+void analogWrite(uint8_t, int);
+void analogReference(uint16_t);
+void analogFrequency(uint32_t);
+void analogResolution(uint16_t);
+
+
+
+void delay(uint32_t milliseconds);
+
+void attachInterrupt(uint8_t, void (*)(void), int mode);
+void detachInterrupt(uint8_t);
+
+extern const uint8_t digital_pin_to_timer[];
+extern const uint8_t digital_pin_to_port[];
+extern const uint8_t digital_pin_to_bit_mask[];
+extern const uint16_t port_to_sel0[];
+extern const uint16_t port_to_sel1[];
+extern const uint16_t port_to_sel2[];
+extern const uint16_t port_to_input[];
+extern const uint16_t port_to_output[];
+
+#define digitalPinToPort(P) ( digital_pin_to_port[P] )
+#define digitalPinToBitMask(P) ( digital_pin_to_bit_mask[P] )
+#define digitalPinToTimer(P) ( digital_pin_to_timer[P] )
+#define portDirRegister(P) ( (volatile uint8_t *)( port_to_dir[P]) )
+/*
+ * We either of the compination PxSEL and PxSEL2 or PxSEL0 and PxSEL1
+ * So we can remap PxSEL and PxSEL2 to PxSEL0 and PxSEL1
+*/
+#define portSelRegister(P) ( (volatile uint8_t *)( port_to_sel0[P]) )
+#define portSel2Register(P) ( (volatile uint8_t *)( port_to_sel2[P]) )
+
+#define portSel0Register(P) ( (volatile uint8_t *)( port_to_sel0[P]) )
+#define portSel1Register(P) ( (volatile uint8_t *)( port_to_sel1[P]) )
+#define portRenRegister(P) ( (volatile uint8_t *)( port_to_ren[P]) )
+#define portOutputRegister(P) ( (volatile uint8_t *)( port_to_output[P]) )
+#define portInputRegister(P) ( (volatile uint8_t *)( port_to_input[P]) )
+#define digitalPinToTimer(P) ( digital_pin_to_timer[P] )
+
+// Implemented in wiring.c
+void delayMicroseconds(unsigned int us);
+unsigned long micros();
+unsigned long millis();
+void disableWatchDog();
+void enableWatchDog();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+#include "WCharacter.h"
+#include "WString.h"
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+#include "HardwareSerial.h"
+#else
+#include "TimerSerial.h"
+#endif
+
+uint16_t makeWord(uint16_t w);
+uint16_t makeWord(byte h, byte l);
+
+#define word(...) makeWord(__VA_ARGS__)
+
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
+
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
+void noTone(uint8_t _pin);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned int);
+long map(long, long, long, long, long);
+
+#endif
+
+#include "pins_energia.h"
+
+#endif
+
+
diff --git a/lib/msp430/HardwareSerial.cpp b/lib/msp430/HardwareSerial.cpp
new file mode 100644
index 0000000..1195262
--- /dev/null
+++ b/lib/msp430/HardwareSerial.cpp
@@ -0,0 +1,237 @@
+/*
+ ************************************************************************
+ * HardwareSerial.cpp
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ HardwareSerial.cpp - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 23 November 2006 by David A. Mellis
+ Modified 28 September 2010 by Mark Sproul
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "Energia.h"
+#include "wiring_private.h"
+#include "usci_isr_handler.h"
+
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+
+#include "HardwareSerial.h"
+
+HardwareSerial *SerialPtr;
+
+
+
+#define SERIAL_BUFFER_SIZE 64
+
+struct ring_buffer
+{
+ unsigned char buffer[SERIAL_BUFFER_SIZE];
+ volatile unsigned int head;
+ volatile unsigned int tail;
+};
+
+ring_buffer rx_buffer = { { 0 }, 0, 0 };
+ring_buffer tx_buffer = { { 0 }, 0, 0 };
+
+inline void store_char(unsigned char c, ring_buffer *buffer)
+{
+ unsigned int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;
+
+ // if we should be storing the received character into the location
+ // just before the tail (meaning that the head would advance to the
+ // current location of the tail), we're about to overflow the buffer
+ // and so we don't write the character or advance the head.
+ if (i != buffer->tail) {
+ buffer->buffer[buffer->head] = c;
+ buffer->head = i;
+ }
+}
+
+void serialEvent() __attribute__((weak));
+void serialEvent() {}
+
+void serialEventRun(void)
+{
+ if (Serial.available()) serialEvent();
+}
+// Constructors ////////////////////////////////////////////////////////////////
+
+HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer)
+{
+ _rx_buffer = rx_buffer;
+ _tx_buffer = tx_buffer;
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+#define SMCLK F_CPU //SMCLK = F_CPU for now
+
+void HardwareSerial::begin(unsigned long baud)
+{
+ unsigned int mod, divider;
+ unsigned char oversampling;
+
+ /* Calling this dummy function prevents the linker
+ * from stripping the USCI interupt vectors.*/
+ usci_isr_install();
+ if (SMCLK/baud>=48) { // requires SMCLK for oversampling
+ oversampling = 1;
+ }
+ else {
+ oversampling= 0;
+ }
+
+ divider=(SMCLK<<4)/baud;
+
+ SerialPtr = this;
+
+ pinMode_int(UARTRXD, UARTRXD_SET_MODE);
+ pinMode_int(UARTTXD, UARTTXD_SET_MODE);
+
+ UCA0CTL1 = UCSWRST;
+ UCA0CTL1 = UCSSEL_2; // SMCLK
+ UCA0CTL0 = 0;
+ UCA0ABCTL = 0;
+#if defined(__MSP430_HAS_EUSCI_A0__)
+ if(!oversampling) {
+ mod = ((divider&0xF)+1)&0xE; // UCBRSx (bit 1-3)
+ divider >>=4;
+ } else {
+ mod = divider&0xFFF0; // UCBRFx = INT([(N/16) – INT(N/16)] × 16)
+ divider>>=8;
+ }
+ UCA0BR0 = divider;
+ UCA0BR1 = divider>>8;
+ UCA0MCTLW = (oversampling ? UCOS16:0) | mod;
+#else
+ if(!oversampling) {
+ mod = ((divider&0xF)+1)&0xE; // UCBRSx (bit 1-3)
+ divider >>=4;
+ } else {
+ mod = ((divider&0xf8)+0x8)&0xf0; // UCBRFx (bit 4-7)
+ divider>>=8;
+ }
+ UCA0BR0 = divider;
+ UCA0BR1 = divider>>8;
+ UCA0MCTL = (unsigned char)(oversampling ? UCOS16:0) | mod;
+#endif
+ UCA0CTL1 &= ~UCSWRST;
+#if defined(__MSP430_HAS_EUSCI_A0__)
+ UCA0IE |= UCRXIE;
+#else
+ UC0IE |= UCA0RXIE;
+#endif
+}
+
+void HardwareSerial::end()
+{
+ // wait for transmission of outgoing data
+ while (_tx_buffer->head != _tx_buffer->tail);
+
+ _rx_buffer->head = _rx_buffer->tail;
+}
+
+int HardwareSerial::available(void)
+{
+ return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE;
+}
+
+int HardwareSerial::peek(void)
+{
+ if (_rx_buffer->head == _rx_buffer->tail) {
+ return -1;
+ } else {
+ return _rx_buffer->buffer[_rx_buffer->tail];
+ }
+}
+
+int HardwareSerial::read(void)
+{
+ // if the head isn't ahead of the tail, we don't have any characters
+ if (_rx_buffer->head == _rx_buffer->tail) {
+ return -1;
+ } else {
+ unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
+ _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
+ return c;
+ }
+}
+
+void HardwareSerial::flush()
+{
+ while (_tx_buffer->head != _tx_buffer->tail);
+}
+
+size_t HardwareSerial::write(uint8_t c)
+{
+ unsigned int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
+
+ // If the output buffer is full, there's nothing for it other than to
+ // wait for the interrupt handler to empty it a bit
+ // ???: return 0 here instead?
+ while (i == _tx_buffer->tail);
+
+ _tx_buffer->buffer[_tx_buffer->head] = c;
+ _tx_buffer->head = i;
+
+#if defined(__MSP430_HAS_EUSCI_A0__)
+ UCA0IE |= UCTXIE;
+#else
+ UC0IE |= UCA0TXIE;
+#endif
+
+ return 1;
+}
+
+void uart_rx_isr(void)
+{
+ unsigned char c = UCA0RXBUF;
+ store_char(c, &rx_buffer);
+}
+
+void uart_tx_isr(void)
+{
+ if (tx_buffer.head == tx_buffer.tail) {
+ // Buffer empty, so disable interrupts
+#if defined(__MSP430_HAS_EUSCI_A0__)
+ UCA0IE &= ~UCTXIE;
+ UCA0IFG |= UCTXIFG; // Set Flag again
+#else
+ UC0IE &= ~UCA0TXIE;
+#endif
+ return;
+ }
+
+ unsigned char c = tx_buffer.buffer[tx_buffer.tail];
+ tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
+ UCA0TXBUF = c;
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+HardwareSerial Serial(&rx_buffer, &tx_buffer);
+
+#endif
diff --git a/lib/msp430/HardwareSerial.h b/lib/msp430/HardwareSerial.h
new file mode 100644
index 0000000..8f3bf39
--- /dev/null
+++ b/lib/msp430/HardwareSerial.h
@@ -0,0 +1,69 @@
+/*
+ ************************************************************************
+ * TimerSerial.h
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ HardwareSerial.cpp - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef HardwareSerial_h
+#define HardwareSerial_h
+
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+#include <inttypes.h>
+
+#include "Stream.h"
+
+struct ring_buffer;
+
+class HardwareSerial : public Stream
+{
+ private:
+ uint8_t lock;
+ ring_buffer *_rx_buffer;
+ ring_buffer *_tx_buffer;
+#if defined(__MSP430_HAS_EUSCI_A0__)
+ static void USCIA0_ISR (void);
+#else
+ static void USCI0RX_ISR (void);
+ static void USCI0TX_ISR (void);
+#endif
+ public:
+ HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer);
+ void begin(unsigned long);
+ void end();
+ virtual int available(void);
+ virtual int peek(void);
+ virtual int read(void);
+ virtual void flush(void);
+ virtual size_t write(uint8_t);
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+};
+
+extern HardwareSerial Serial;
+
+extern void serialEventRun(void) __attribute__((weak));
+
+#endif // __MSP430_HAS_USCI__
+
+#endif
diff --git a/lib/msp430/Print.cpp b/lib/msp430/Print.cpp
new file mode 100644
index 0000000..18c48f1
--- /dev/null
+++ b/lib/msp430/Print.cpp
@@ -0,0 +1,252 @@
+/*
+ Print.cpp - Base class that provides print() and println()
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 23 November 2006 by David A. Mellis
+ Modified for msp403 2012 by Robert Wessels
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "Energia.h"
+
+#include "Print.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+/* default implementation: may be overridden */
+size_t Print::write(const uint8_t *buffer, size_t size)
+{
+ size_t n = 0;
+ while (size--) {
+ n += write(*buffer++);
+ }
+ return n;
+}
+
+size_t Print::print(const String &s)
+{
+ size_t n = 0;
+ for (uint16_t i = 0; i < s.length(); i++) {
+ n += write(s[i]);
+ }
+ return n;
+}
+
+size_t Print::print(const char str[])
+{
+ return write(str);
+}
+
+size_t Print::print(char c)
+{
+ return write(c);
+}
+
+size_t Print::print(unsigned char b, int base)
+{
+ return print((unsigned long) b, base);
+}
+
+size_t Print::print(int n, int base)
+{
+ return print((long) n, base);
+}
+
+size_t Print::print(unsigned int n, int base)
+{
+ return print((unsigned long) n, base);
+}
+
+size_t Print::print(long n, int base)
+{
+ if (base == 0) {
+ return write(n);
+ } else if (base == 10) {
+ if (n < 0) {
+ int t = print('-');
+ n = -n;
+ return printNumber(n, 10) + t;
+ }
+ return printNumber(n, 10);
+ } else {
+ return printNumber(n, base);
+ }
+}
+
+size_t Print::print(unsigned long n, int base)
+{
+ if (base == 0) return write(n);
+ else return printNumber(n, base);
+}
+
+size_t Print::print(double n, int digits)
+{
+ return printFloat(n, digits);
+}
+
+//size_t Print::println(const __FlashStringHelper *ifsh)
+//{
+// size_t n = print(ifsh);
+// n += println();
+// return n;
+//}
+
+size_t Print::print(const Printable& x)
+{
+ return x.printTo(*this);
+}
+
+size_t Print::println(void)
+{
+ size_t n = print('\r');
+ n += print('\n');
+ return n;
+}
+
+size_t Print::println(const String &s)
+{
+ size_t n = print(s);
+ n += println();
+ return n;
+}
+
+size_t Print::println(const char c[])
+{
+ size_t n = print(c);
+ n += println();
+ return n;
+}
+
+size_t Print::println(char c)
+{
+ size_t n = print(c);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned char b, int base)
+{
+ size_t n = print(b, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(int num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned int num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(long num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned long num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(double num, int digits)
+{
+ size_t n = print(num, digits);
+ n += println();
+ return n;
+}
+
+size_t Print::println(const Printable& x)
+{
+ size_t n = print(x);
+ n += println();
+ return n;
+}
+
+// Private Methods /////////////////////////////////////////////////////////////
+
+size_t Print::printNumber(unsigned long n, uint8_t base) {
+ char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
+ char *str = &buf[sizeof(buf) - 1];
+
+ *str = '\0';
+
+ // prevent crash if called with base == 1
+ if (base < 2) base = 10;
+
+ do {
+ unsigned long m = n;
+ n /= base;
+ char c = m - base * n;
+ *--str = c < 10 ? c + '0' : c + 'A' - 10;
+ } while(n);
+
+ return write(str);
+}
+
+size_t Print::printFloat(double number, uint8_t digits)
+{
+ size_t n = 0;
+
+ // Handle negative numbers
+ if (number < 0.0)
+ {
+ n += print('-');
+ number = -number;
+ }
+
+ // Round correctly so that print(1.999, 2) prints as "2.00"
+ double rounding = 0.5;
+ for (uint8_t i=0; i<digits; ++i)
+ rounding /= 10.0;
+
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ n += print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 0) {
+ n += print(".");
+ }
+
+ // Extract digits from the remainder one at a time
+ while (digits-- > 0)
+ {
+ remainder *= 10.0;
+ int toPrint = int(remainder);
+ n += print(toPrint);
+ remainder -= toPrint;
+ }
+
+ return n;
+}
diff --git a/lib/msp430/Print.h b/lib/msp430/Print.h
new file mode 100644
index 0000000..65ca598
--- /dev/null
+++ b/lib/msp430/Print.h
@@ -0,0 +1,85 @@
+/*
+ Print.h - Base class that provides print() and println()
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef Print_h
+#define Print_h
+
+#include <inttypes.h>
+#include <stdio.h> // for size_t
+
+#include "WString.h"
+#include "Printable.h"
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+
+class Print
+{
+ private:
+ int write_error;
+ size_t printNumber(unsigned long, uint8_t);
+ size_t printFloat(double, uint8_t);
+
+ // Prevent heap allocation
+ void * operator new (size_t);
+ void * operator new[] (size_t);
+ void operator delete (void *);
+ void operator delete[] (void*);
+
+ protected:
+ void setWriteError(int err = 1) { write_error = err; }
+ public:
+ Print() : write_error(0) {}
+
+ int getWriteError() { return write_error; }
+ void clearWriteError() { setWriteError(0); }
+
+ virtual size_t write(uint8_t) = 0;
+ size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
+ virtual size_t write(const uint8_t *buffer, size_t size);
+
+ //size_t print(const __FlashStringHelper *);
+ size_t print(const String &);
+ size_t print(const char[]);
+ size_t print(char);
+ size_t print(unsigned char, int = DEC);
+ size_t print(int, int = DEC);
+ size_t print(unsigned int, int = DEC);
+ size_t print(long, int = DEC);
+ size_t print(unsigned long, int = DEC);
+ size_t print(double, int = 2);
+ size_t print(const Printable&);
+
+ //size_t println(const __FlashStringHelper *);
+ size_t println(const String &s);
+ size_t println(const char[]);
+ size_t println(char);
+ size_t println(unsigned char, int = DEC);
+ size_t println(int, int = DEC);
+ size_t println(unsigned int, int = DEC);
+ size_t println(long, int = DEC);
+ size_t println(unsigned long, int = DEC);
+ size_t println(double, int = 2);
+ size_t println(const Printable&);
+ size_t println(void);
+};
+
+#endif
diff --git a/lib/msp430/Printable.h b/lib/msp430/Printable.h
new file mode 100644
index 0000000..d03c9af
--- /dev/null
+++ b/lib/msp430/Printable.h
@@ -0,0 +1,40 @@
+/*
+ Printable.h - Interface class that allows printing of complex types
+ Copyright (c) 2011 Adrian McEwen. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef Printable_h
+#define Printable_h
+
+#include <new.h>
+
+class Print;
+
+/** The Printable class provides a way for new classes to allow themselves to be printed.
+ By deriving from Printable and implementing the printTo method, it will then be possible
+ for users to print out instances of this class by passing them into the usual
+ Print::print and Print::println methods.
+*/
+
+class Printable
+{
+ public:
+ virtual size_t printTo(Print& p) const = 0;
+};
+
+#endif
+
diff --git a/lib/msp430/Stream.cpp b/lib/msp430/Stream.cpp
new file mode 100644
index 0000000..c7d1863
--- /dev/null
+++ b/lib/msp430/Stream.cpp
@@ -0,0 +1,246 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+ */
+
+#include "Energia.h"
+#include "Stream.h"
+
+#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
+#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+ int c;
+ _startMillis = millis();
+ do {
+ c = read();
+ if (c >= 0) return c;
+ } while(millis() - _startMillis < _timeout);
+ return -1; // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+ int c;
+ _startMillis = millis();
+ do {
+ c = peek();
+ if (c >= 0) return c;
+ } while(millis() - _startMillis < _timeout);
+ return -1; // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+ int c;
+ while (1) {
+ c = timedPeek();
+ if (c < 0) return c; // timeout
+ if (c == '-') return c;
+ if (c >= '0' && c <= '9') return c;
+ read(); // discard non-numeric
+ }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
+{
+ _timeout = timeout;
+}
+
+ // find returns true if the target string is found
+bool Stream::find(char *target)
+{
+ return findUntil(target, NULL);
+}
+
+// reads data from the stream until the target string of given length is found
+// returns true if target string is found, false if timed out
+bool Stream::find(char *target, size_t length)
+{
+ return findUntil(target, length, NULL, 0);
+}
+
+// as find but search ends if the terminator string is found
+bool Stream::findUntil(char *target, char *terminator)
+{
+ return findUntil(target, strlen(target), terminator, strlen(terminator));
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
+{
+ size_t index = 0; // maximum target string length is 64k bytes!
+ size_t termIndex = 0;
+ int c;
+
+ if( *target == 0)
+ return true; // return true if target is a null string
+ while( (c = timedRead()) > 0){
+
+ if(c != target[index])
+ index = 0; // reset index if any char does not match
+
+ if( c == target[index]){
+ //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+ if(++index >= targetLen){ // return true if all chars in the target match
+ return true;
+ }
+ }
+
+ if(termLen > 0 && c == terminator[termIndex]){
+ if(++termIndex >= termLen)
+ return false; // return false if terminate string found before target string
+ }
+ else
+ termIndex = 0;
+ }
+ return false;
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+ return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+ boolean isNegative = false;
+ long value = 0;
+ int c;
+
+ c = peekNextDigit();
+ // ignore non numeric leading characters
+ if(c < 0)
+ return 0; // zero returned if timeout
+
+ do{
+ if(c == skipChar)
+ ; // ignore this charactor
+ else if(c == '-')
+ isNegative = true;
+ else if(c >= '0' && c <= '9') // is c a digit?
+ value = value * 10 + c - '0';
+ read(); // consume the character we got with peek
+ c = timedPeek();
+ }
+ while( (c >= '0' && c <= '9') || c == skipChar );
+
+ if(isNegative)
+ value = -value;
+ return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+ return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar){
+ boolean isNegative = false;
+ boolean isFraction = false;
+ long value = 0;
+ char c;
+ float fraction = 1.0;
+
+ c = peekNextDigit();
+ // ignore non numeric leading characters
+ if(c < 0)
+ return 0; // zero returned if timeout
+
+ do{
+ if(c == skipChar)
+ ; // ignore
+ else if(c == '-')
+ isNegative = true;
+ else if (c == '.')
+ isFraction = true;
+ else if(c >= '0' && c <= '9') { // is c a digit?
+ value = value * 10 + c - '0';
+ if(isFraction)
+ fraction *= 0.1;
+ }
+ read(); // consume the character we got with peek
+ c = timedPeek();
+ }
+ while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
+
+ if(isNegative)
+ value = -value;
+ if(isFraction)
+ return value * fraction;
+ else
+ return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+ size_t count = 0;
+ while (count < length) {
+ int c = timedRead();
+ if (c < 0) break;
+ *buffer++ = (char)c;
+ count++;
+ }
+ return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+ if (length < 1) return 0;
+ size_t index = 0;
+ while (index < length) {
+ int c = timedRead();
+ if (c < 0 || c == terminator) break;
+ *buffer++ = (char)c;
+ index++;
+ }
+ return index; // return number of characters, not including null terminator
+}
+
diff --git a/lib/msp430/Stream.h b/lib/msp430/Stream.h
new file mode 100644
index 0000000..13f11be
--- /dev/null
+++ b/lib/msp430/Stream.h
@@ -0,0 +1,94 @@
+/*
+ Stream.h - base class for character-based streams.
+ Copyright (c) 2010 David A. Mellis. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ parsing functions based on TextFinder library by Michael Margolis
+*/
+
+#ifndef Stream_h
+#define Stream_h
+
+#include <inttypes.h>
+#include "Print.h"
+
+// compatability macros for testing
+/*
+#define getInt() parseInt()
+#define getInt(skipChar) parseInt(skipchar)
+#define getFloat() parseFloat()
+#define getFloat(skipChar) parseFloat(skipChar)
+#define getString( pre_string, post_string, buffer, length)
+readBytesBetween( pre_string, terminator, buffer, length)
+*/
+
+class Stream : public Print
+{
+ private:
+ unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
+ unsigned long _startMillis; // used for timeout measurement
+ int timedRead(); // private method to read stream with timeout
+ int timedPeek(); // private method to peek stream with timeout
+ int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
+
+ public:
+ virtual int available() = 0;
+ virtual int read() = 0;
+ virtual int peek() = 0;
+ virtual void flush() = 0;
+
+ Stream() {_timeout=1000;}
+
+// parsing methods
+
+ void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
+
+ bool find(char *target); // reads data from the stream until the target string is found
+ // returns true if target string is found, false if timed out (see setTimeout)
+
+ bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
+ // returns true if target string is found, false if timed out
+
+ bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
+
+ bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
+
+
+ long parseInt(); // returns the first valid (long) integer value from the current position.
+ // initial characters that are not digits (or the minus sign) are skipped
+ // integer is terminated by the first character that is not a digit.
+
+ float parseFloat(); // float version of parseInt
+
+ size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
+ // terminates if length characters have been read or timeout (see setTimeout)
+ // returns the number of characters placed in the buffer (0 means no valid data found)
+
+ size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
+ // terminates if length characters have been read, timeout, or if the terminator character detected
+ // returns the number of characters placed in the buffer (0 means no valid data found)
+
+ // Arduino String functions to be added here
+
+ protected:
+ long parseInt(char skipChar); // as above but the given skipChar is ignored
+ // as above but the given skipChar is ignored
+ // this allows format characters (typically commas) in values to be ignored
+
+ float parseFloat(char skipChar); // as above but the given skipChar is ignored
+};
+
+#endif
diff --git a/lib/msp430/TimerSerial.cpp b/lib/msp430/TimerSerial.cpp
new file mode 100644
index 0000000..e32d902
--- /dev/null
+++ b/lib/msp430/TimerSerial.cpp
@@ -0,0 +1,272 @@
+/*
+ ************************************************************************
+ * TimerSerial.cpp
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ HardwareSerial.cpp - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+ and
+ msp430softserial by Rick Kimball
+ https://github.com/RickKimball
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "Energia.h"
+#include "TimerSerial.h"
+
+#define SERIAL_BUFFER_SIZE 64
+
+#ifndef TIMERA0_VECTOR
+ #define TIMERA0_VECTOR TIMER0_A0_VECTOR
+#endif /* TIMER0_A0_VECTOR */
+
+#ifndef TIMERA1_VECTOR
+ #define TIMERA1_VECTOR TIMER0_A1_VECTOR
+#endif /* TIMERA1_VECTOR */
+
+struct ring_buffer_ts
+{
+ volatile unsigned int head;
+ volatile unsigned int tail;
+ unsigned char buffer[SERIAL_BUFFER_SIZE];
+};
+
+/**
+ * uint8x2_t - optimized structure storage for ISR. Fits our static variables in one register
+ * This tweak allows the ISR to use one less register saving a push and pop
+ * We also save a couple of instructions being able to write to both values with
+ * one mov.w instruction.
+ */
+typedef union uint8x2_t {
+ //---------- word access
+ uint16_t mask_data; // access both as a word: mask is low byte, data is high byte
+ //--- or --- individual byte access
+ struct {
+ uint8_t mask:8; // bit mask to set data bits. Also used as a loop end flag
+ uint8_t data:8; // working value for bits received
+ } b;
+} uint8x2_t;
+
+// --- ---
+static volatile unsigned int USARTTXBUF;
+static uint16_t TICKS_PER_BIT;
+static uint16_t TICKS_PER_BIT_DIV2;
+static ring_buffer_ts rx_buffer;
+
+#if NEEDS_BUFF_PTR
+ static ring_buffer_ts tx_buffer; // required for the g2231, without it we get garbage
+#endif
+
+#if !defined(__MSP430_HAS_USCI__) && !defined(__MSP430_HAS_EUSCI_A0__)
+TimerSerial Serial;
+#endif
+
+void serialEvent() __attribute__((weak));
+void serialEvent() {}
+
+void serialEventRun(void)
+{
+ if (Serial.available()) serialEvent();
+}
+
+TimerSerial::TimerSerial()
+{
+#if NEEDS_BUFF_PTR
+ _rx_buffer = &rx_buffer;
+ _tx_buffer = &tx_buffer;
+#endif
+}
+
+void TimerSerial::begin(register unsigned long baud)
+{
+ pinMode_int(UARTRXD, UARTRXD_SET_MODE);
+ pinMode_int(UARTTXD, UARTTXD_SET_MODE);
+
+ TA0CCTL0 = OUT; // Set TXD Idle state as Mark = '1', +3.3 volts normal
+ TA0CCTL1 = SCS | CM1 | CAP | CCIE; // Sync TACLK and MCLK, Detect Neg Edge, Enable Capture mode and RX Interrupt
+ TA0CTL = TASSEL_2 | MC_2 | TACLR; // Clock TIMERA from SMCLK, run in continuous mode counting from to 0-0xFFFF
+
+#if F_CPU == 1000000
+ baud = (baud<=4800) ? baud : 4800; // force 4800 for slow F_CPU
+#endif
+
+ TICKS_PER_BIT = F_CPU / baud;
+ TICKS_PER_BIT_DIV2 = TICKS_PER_BIT >> 1;
+}
+
+void TimerSerial::end()
+{
+ while (TA0CCTL0 & CCIE) {
+ ; // wait for previous xmit to finish
+ }
+ pinMode(UARTTXD, INPUT);
+}
+
+int TimerSerial::read()
+{
+ register uint16_t temp_tail=rx_buffer.tail;
+
+ if (rx_buffer.head != temp_tail) {
+ uint8_t c = rx_buffer.buffer[temp_tail++];
+ rx_buffer.tail = temp_tail % SERIAL_BUFFER_SIZE;
+ return c;
+ }
+ else {
+ return -1;
+ }
+}
+
+int TimerSerial::available()
+{
+ unsigned cnt = (rx_buffer.head - rx_buffer.tail) % SERIAL_BUFFER_SIZE;
+
+ return cnt;
+}
+
+void TimerSerial::flush()
+{
+ while (TA0CCTL0 & CCIE) {
+ ; // wait for previous xmit to finish
+ }
+}
+
+int TimerSerial::peek()
+{
+ register uint16_t temp_tail=rx_buffer.tail;
+
+ if (rx_buffer.head != temp_tail) {
+ return rx_buffer.buffer[temp_tail];
+ }
+ else {
+ return -1;
+ }
+}
+
+size_t TimerSerial::write(uint8_t c)
+{
+ // TIMERA0 disables the interrupt flag when it has sent
+ // the final stop bit. While a transmit is in progress the
+ // interrupt is enabled
+ while (TA0CCTL0 & CCIE) {
+ ; // wait for previous xmit to finish
+ }
+
+ // make the next output at least TICKS_PER_BIT in the future
+ // so we don't stomp on the the stop bit from our previous xmt
+
+ TA0CCR0 = TA0R; // resync with current TimerA clock
+ TA0CCR0 += TICKS_PER_BIT; // setup the next timer tick
+ TA0CCTL0 = OUTMOD0 + CCIE; // set TX_PIN HIGH and reenable interrupts
+
+ // now that we have set the next interrupt in motion
+ // we quickly need to set the TX data. Hopefully the
+ // next 2 lines happens before the next timer tick.
+
+ // Note: This code makes great use of multiple peripherals
+ //
+ // In the code above, we start with a busy wait on the CCIE
+ // interrupt flag. As soon as it is available, we setup the next
+ // send time and then enable the interrupt. Until that time happens,
+ // we have a few free cycles available to stuff the start and stop bits
+ // into the data buffer before the timer ISR kicks in and handles
+ // the event. Note: if you are using a really slow clock or a really
+ // fast baud rate you could run into problems if the interrupt is
+ // triggered before you have finished with the USARTTXBUF
+
+ register unsigned value = c | 0x100; // add stop bit '1'
+ value <<= 1; // Add the start bit '0'
+ USARTTXBUF=value; // queue up the byte for xmit
+ return 1;
+}
+
+
+#ifndef TIMER0_A0_VECTOR
+#define TIMER0_A0_VECTOR TIMERA0_VECTOR
+#endif /* TIMER0_A0_VECTOR */
+
+#ifndef __GNUC__
+#pragma vector = TIMER0_A0_VECTOR
+__interrupt
+#else
+__attribute__((interrupt(TIMER0_A0_VECTOR)))
+#endif
+//Timer0 A0 interrupt service routine
+static void TimerSerial__TxIsr(void)
+{
+ TA0CCR0 += TICKS_PER_BIT; // setup next time to send a bit, OUT will be set then
+
+ TA0CCTL0 |= OUTMOD2; // reset OUT (set to 0) OUTMOD2|OUTMOD0 (0b101)
+ if ( USARTTXBUF & 0x01 ) { // look at LSB if 1 then set OUT high
+ TA0CCTL0 &= ~OUTMOD2; // set OUT (set to 1) OUTMOD0 (0b001)
+ }
+
+ if (!(USARTTXBUF >>= 1)) { // All bits transmitted ?
+ TA0CCTL0 &= ~CCIE; // disable interrupt, indicates we are done
+ }
+}
+
+#define store_rxchar(c) { \
+ register unsigned int next_head;\
+ next_head = rx_buffer.head;\
+ rx_buffer.buffer[next_head++]=c; \
+ next_head %= SERIAL_BUFFER_SIZE; \
+ if ( next_head != rx_buffer.tail ) { \
+ rx_buffer.head = next_head; \
+ } \
+}
+
+#ifndef TIMER0_A1_VECTOR
+#define TIMER0_A1_VECTOR TIMERA1_VECTOR
+#endif /* TIMER0_A0_VECTOR */
+
+#ifndef __GNUC__
+#pragma vector = TIMER0_A1_VECTOR
+__interrupt
+#else
+__attribute__((interrupt(TIMER0_A1_VECTOR)))
+#endif
+//Timer A1 interrupt service routine
+static void TimerSerial__RxIsr(void)
+{
+ static uint8x2_t rx_bits; // persistent storage for data and mask. fits in one 16 bit register
+ volatile uint16_t resetTAIVIFG; // just reading TAIV will reset the interrupt flag
+ resetTAIVIFG=TA0IV;(void)resetTAIVIFG;
+
+ register uint16_t regCCTL1=TA0CCTL1; // using a temp register provides a slight performance improvement
+
+ TA0CCR1 += TICKS_PER_BIT; // Setup next time to sample
+
+ if (regCCTL1 & CAP) { // Are we in capture mode? If so, this is a start bit
+ TA0CCR1 += TICKS_PER_BIT_DIV2; // adjust sample time, so next sample is in the middle of the bit width
+ rx_bits.mask_data = 0x0001; // initialize both values, set data to 0x00 and mask to 0x01
+ TA0CCTL1 = regCCTL1 & ~CAP; // Switch from capture mode to compare mode
+ }
+ else {
+ if (regCCTL1 & SCCI) { // sampled bit value from receive latch
+ rx_bits.b.data|=rx_bits.b.mask; // if latch is high, then set the bit using the sliding mask
+ }
+
+ if (!(rx_bits.b.mask <<= 1)) { // Are all bits received? Use the mask to end loop
+ store_rxchar(rx_bits.b.data); // Store the bits into the rx_buffer
+ TA0CCTL1 = regCCTL1 | CAP; // Switch back to capture mode and wait for next start bit (HI->LOW)
+ }
+ }
+}
diff --git a/lib/msp430/TimerSerial.h b/lib/msp430/TimerSerial.h
new file mode 100644
index 0000000..58dc660
--- /dev/null
+++ b/lib/msp430/TimerSerial.h
@@ -0,0 +1,78 @@
+/*
+ TimerSerial.h - Timer based serial library for MSP430
+ Copyright (c) 2012 Robert Wessels. All right reserved.
+ Modeled after Nicholas Zambetti's HardwareSerial.
+ and
+ msp430softserial by Rick Kimball
+ https://github.com/RickKimball/msp430softserial/
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef TimerSerial_h
+#define TimerSerial_h
+
+#include <inttypes.h>
+#include <Stream.h>
+
+#define TX_PIN BIT1 // TXD on P1.1
+#define RX_PIN BIT2 // RXD on P1.2
+
+// running at < 3MHz requires a lower baud rate
+#ifndef TIMERSERIAL_BAUD
+#if F_CPU > 1000000
+ #define TIMERSERIAL_BAUD 9600
+#else
+ #define TIMERSERIAL_BAUD 4800
+#endif
+#endif
+
+#if defined(__MSP430G2231__)
+ #define NEEDS_BUFF_PTR 1 // sadly, the g2231 seems to have a problem if we don't use the original structure
+ struct ring_buffer_ts; // forward declaration
+#else
+ #define NEEDS_BUFF_PTR 0 // everything else is happy to run fully optimized
+#endif
+
+class TimerSerial : public Stream
+{
+public:
+ TimerSerial(void);
+
+ void begin(unsigned long baud = TIMERSERIAL_BAUD);
+ void end(void);
+
+ virtual size_t write(uint8_t byte);
+ virtual int read(void);
+ virtual int available(void);
+ virtual void flush(void);
+ virtual int peek(void);
+
+ using Print::write;
+
+private:
+
+#if NEEDS_BUFF_PTR
+ ring_buffer_ts *_rx_buffer; // gcc seems to get confused on the g2231 without this
+ ring_buffer_ts *_tx_buffer;
+#endif
+
+};
+
+#if !defined(__MSP430_HAS_USCI__) && !defined(__MSP430_HAS_EUSCI_A0__)
+extern TimerSerial Serial;
+#endif
+extern void serialEventRun(void) __attribute__((weak));
+#endif
diff --git a/lib/msp430/Tone.cpp b/lib/msp430/Tone.cpp
new file mode 100755
index 0000000..dd4aaeb
--- /dev/null
+++ b/lib/msp430/Tone.cpp
@@ -0,0 +1,223 @@
+/* Tone.cpp
+
+ A Tone Generator Library - Modified for Energia
+ Implements up to 3 (software) PWM outputs using TIMERA0 compare registers and IRQ.
+ Can use any digital output pin for pulse generation
+
+ (c) 2012 - Peter Brier.
+
+ Based on code Originally written by Brett Hagman
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Version Modified By Date Comments
+------- ----------- -------- --------
+0001 B Hagman 09/08/02 Initial coding
+0002 B Hagman 09/08/18 Multiple pins
+0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
+0004 B Hagman 09/09/26 Fixed problems with ATmega8
+0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
+ 09/11/25 Changed pin toggle method to XOR
+ 09/11/25 Fixed timer0 from being excluded
+0006 D Mellis 09/12/29 Replaced objects with functions
+0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
+0008 P Brier 12/05/28 Modified for TI MSP430 processor
+0009 P Brier 12/05/29 Fixed problem with re-init of expired tone
+*************************************************/
+
+#include "wiring_private.h"
+#include "pins_energia.h"
+#include "Energia.h"
+
+// local funcions
+static void initTimers();
+static void setTimer(uint8_t n, unsigned int frequency, unsigned long duration);
+static void stopTimer(uint8_t n);
+
+// timer clock frequency set to clock/8, at F_CPU = 1MHZ this gives an output freq range of ~[1Hz ..65Khz] and at 16Mhz this is ~[16Hz .. 1MHz]
+#define F_TIMER (F_CPU/8L)
+
+#ifdef __MSP430_HAS_TA3__
+#define AVAILABLE_TONE_PINS 3
+#define SETARRAY(a) a,a,a
+#else
+#define AVAILABLE_TONE_PINS 2
+#define SETARRAY(a) a,a
+#endif
+
+
+// tone_duration:
+// > 0 - duration specified
+// = 0 - stopped
+// < 0 - infinitely (until stop() method called, or new play() called)
+
+static uint8_t tone_state = 0; // 0==not initialized, 1==timer running
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { SETARRAY(255) };
+static uint8_t tone_bit[AVAILABLE_TONE_PINS] = { SETARRAY(255) };
+volatile static uint8_t *tone_out[AVAILABLE_TONE_PINS] = { SETARRAY(0) };
+static uint16_t tone_interval[AVAILABLE_TONE_PINS] = { SETARRAY(-1) };
+static int16_t tone_periods[AVAILABLE_TONE_PINS] = { SETARRAY(0) };
+
+
+/**
+*** tone() -- Output a tone (50% Dutycycle PWM signal) on a pin
+*** pin: This pin is selected as output
+*** frequency: [Hertz]
+** duration: [milliseconds], if duration <=0, then we output tone continously, otherwise tone is stopped after this time (output = 0)
+**/
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
+{
+ uint8_t port = digitalPinToPort(_pin);
+ if (port == NOT_A_PORT) return;
+
+ // find if we are using it at the moment, if so: update it
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
+ {
+ if (tone_pins[i] == _pin)
+ {
+ setTimer(i, frequency, duration);
+ return; // we are done, timer reprogrammed
+ }
+ }
+
+ // new tone pin, find empty timer and set it
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
+ {
+ if (tone_pins[i] == 255)
+ {
+ tone_pins[i] = _pin;
+ tone_bit[i] = digitalPinToBitMask(_pin);
+ tone_out[i] = portOutputRegister(port);
+ if ( tone_state == 0 )
+ initTimers();
+ pinMode(_pin, OUTPUT);
+ setTimer(i, frequency, duration);
+ return; // we are done, timer set
+ }
+ }
+ // if we exit here, no unused timer was found, nothing is done
+}
+
+
+/**
+*** noTone() - Stop outputting the tone on a pin
+**/
+void noTone(uint8_t _pin)
+{
+ if ( _pin == 255 ) return; // Should not happen!
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
+ {
+ if (tone_pins[i] == _pin)
+ {
+ tone_pins[i] = 255;
+ stopTimer(i);
+ }
+ }
+}
+
+
+// Initialize the timers - Set mode and Enable IRQ
+static void inline initTimers()
+{
+ // disable IRQs
+ TA0CCTL0 = 0;
+ TA0CCTL1 = 0;
+#ifdef __MSP430_HAS_TA3__
+ TA0CCTL2 = 0;
+#endif
+ TA0CTL = TACLR + TASSEL_2 + ID_3 + MC_2; // clear counter, source=SMCLK/8, mode=continous count up
+ tone_state = 1; // init is done
+}
+
+
+// Set the timer interval and duration
+// frequency in [Hz] and duration in [msec]
+// we initialize the timer match value only if the tone was not running already, to prevent glitches when re-programming a running tone
+static void setTimer(uint8_t n, unsigned int frequency, unsigned long duration)
+{
+ if ( frequency <= 0 )
+ {
+ tone_interval[n] = 0;
+ tone_periods[n] = 0;
+ return;
+ }
+ tone_interval[n] = F_TIMER / (2L*frequency);
+ if ( duration > 0 )
+ tone_periods[n] = (duration * (F_TIMER/2)) / (1000L * tone_interval[n]);
+ else
+ tone_periods[n] = -1;
+ switch( n ) // enable IRQ and set next match time in various timer compare registers (if we where not enabled already)
+ {
+ case 0:
+ if ( ! (TA0CCTL0 & CCIE) ) TA0CCR0 = TA0R + tone_interval[0];
+ TA0CCTL0 = CCIE;
+ break;
+ case 1:
+ if ( !(TA0CCTL1 & CCIE) ) TA0CCR1 = TA0R + tone_interval[1];
+ TA0CCTL1 = CCIE;
+ break;
+#ifdef __MSP430_HAS_TA3__
+ case 2:
+ if ( !(TA0CCTL2 & CCIE) ) TA0CCR2 = TA0R + tone_interval[2];
+ TA0CCTL2 = CCIE;
+ break;
+#endif
+ }
+}
+
+/* stopTimer() - Disable timer IRQ */
+static void inline stopTimer(uint8_t n)
+{
+ switch( n )
+ {
+ case 0: TA0CCTL0 = 0; break;
+ case 1: TA0CCTL1 = 0; break;
+#ifdef __MSP430_HAS_TA3__
+ case 2: TA0CCTL2 = 0; break;
+#endif
+ }
+ *tone_out[n] &= ~tone_bit[n];
+}
+
+
+// Peform the isr magic, toggle output, decrease duation if > 0, and stop if duration == 0, continous if duration < 0
+// set new interval - defined as macro to limit ISR overhead (at the expense of some code size)
+#define isrTimer(n,ccr) do { \
+ *tone_out[n] ^= tone_bit[n]; \
+ if ( tone_periods[n] == 0 ) stopTimer(n);\
+ else if ( tone_periods[n] > 0) tone_periods[n]--; \
+ ccr += tone_interval[n]; \
+} while(0)
+
+
+// TIMERA vector (CCR0)
+__attribute__((interrupt(TIMER0_A0_VECTOR)))
+void TIMER0_A0_ISR(void)
+{
+ isrTimer(0, TA0CCR0);
+}
+
+// TAIV vector (CCR1/CCR2)
+__attribute__((interrupt(TIMER0_A1_VECTOR)))
+void TIMER0_A1_ISR(void)
+{
+ switch ( TA0IV )
+ {
+ case 0x2: isrTimer(1, TA0CCR1); break; // CCR1
+#ifdef __MSP430_HAS_TA3__
+ case 0x4: isrTimer(2, TA0CCR2); break; // CCR2
+#endif
+ }
+}
diff --git a/lib/msp430/WCharacter.h b/lib/msp430/WCharacter.h
new file mode 100644
index 0000000..074539c
--- /dev/null
+++ b/lib/msp430/WCharacter.h
@@ -0,0 +1,170 @@
+/*
+ WCharacter.h - Character utility functions for Wiring & Arduino
+ Copyright (c) 2010 Hernando Barragan. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef Character_h
+#define Character_h
+
+#include <ctype.h>
+
+// WCharacter.h prototypes
+inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
+inline boolean isAlpha(int c) __attribute__((always_inline));
+inline boolean isAscii(int c) __attribute__((always_inline));
+inline boolean isWhitespace(int c) __attribute__((always_inline));
+inline boolean isControl(int c) __attribute__((always_inline));
+inline boolean isDigit(int c) __attribute__((always_inline));
+inline boolean isGraph(int c) __attribute__((always_inline));
+inline boolean isLowerCase(int c) __attribute__((always_inline));
+inline boolean isPrintable(int c) __attribute__((always_inline));
+inline boolean isPunct(int c) __attribute__((always_inline));
+inline boolean isSpace(int c) __attribute__((always_inline));
+inline boolean isUpperCase(int c) __attribute__((always_inline));
+inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
+inline int toAscii(int c) __attribute__((always_inline));
+inline int toLowerCase(int c) __attribute__((always_inline));
+inline int toUpperCase(int c)__attribute__((always_inline));
+
+
+// Checks for an alphanumeric character.
+// It is equivalent to (isalpha(c) || isdigit(c)).
+inline boolean isAlphaNumeric(int c)
+{
+ return ( isalnum(c) == 0 ? false : true);
+}
+
+
+// Checks for an alphabetic character.
+// It is equivalent to (isupper(c) || islower(c)).
+inline boolean isAlpha(int c)
+{
+ return ( isalpha(c) == 0 ? false : true);
+}
+
+
+// Checks whether c is a 7-bit unsigned char value
+// that fits into the ASCII character set.
+inline boolean isAscii(int c)
+{
+ return ( isascii (c) == 0 ? false : true);
+}
+
+
+// Checks for a blank character, that is, a space or a tab.
+inline boolean isWhitespace(int c)
+{
+ return ( isblank (c) == 0 ? false : true);
+}
+
+
+// Checks for a control character.
+inline boolean isControl(int c)
+{
+ return ( iscntrl (c) == 0 ? false : true);
+}
+
+
+// Checks for a digit (0 through 9).
+inline boolean isDigit(int c)
+{
+ return ( isdigit (c) == 0 ? false : true);
+}
+
+
+//TODO: mspgcc does not seem to have isgraph?!?
+
+//// Checks for any printable character except space.
+//inline boolean isGraph(int c)
+//{
+// return ( isgraph (c) == 0 ? false : true);
+//}
+
+
+// Checks for a lower-case character.
+inline boolean isLowerCase(int c)
+{
+ return (islower (c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character including space.
+inline boolean isPrintable(int c)
+{
+ return ( isprint (c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character which is not a space
+// or an alphanumeric character.
+inline boolean isPunct(int c)
+{
+ return ( ispunct (c) == 0 ? false : true);
+}
+
+
+// Checks for white-space characters. For the avr-libc library,
+// these are: space, formfeed ('\f'), newline ('\n'), carriage
+// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
+inline boolean isSpace(int c)
+{
+ return ( isspace (c) == 0 ? false : true);
+}
+
+
+// Checks for an uppercase letter.
+inline boolean isUpperCase(int c)
+{
+ return ( isupper (c) == 0 ? false : true);
+}
+
+
+// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
+// 8 9 a b c d e f A B C D E F.
+inline boolean isHexadecimalDigit(int c)
+{
+ return ( isxdigit (c) == 0 ? false : true);
+}
+
+
+// Converts c to a 7-bit unsigned char value that fits into the
+// ASCII character set, by clearing the high-order bits.
+inline int toAscii(int c)
+{
+ return toascii (c);
+}
+
+
+// Warning:
+// Many people will be unhappy if you use this function.
+// This function will convert accented letters into random
+// characters.
+
+// Converts the letter c to lower case, if possible.
+inline int toLowerCase(int c)
+{
+ return tolower (c);
+}
+
+
+// Converts the letter c to upper case, if possible.
+inline int toUpperCase(int c)
+{
+ return toupper (c);
+}
+
+#endif
diff --git a/lib/msp430/WInterrupts.c b/lib/msp430/WInterrupts.c
new file mode 100644
index 0000000..e0fba17
--- /dev/null
+++ b/lib/msp430/WInterrupts.c
@@ -0,0 +1,138 @@
+/*
+ ************************************************************************
+ * WInterrupts.c
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+
+ WInterrupts.c Part of the Wiring project - http://wiring.uniandes.edu.co
+
+ Copyright (c) 2004-05 Hernando Barragan
+
+ 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
+
+ Modified 24 November 2006 by David A. Mellis
+ Modified 1 August 2010 by Mark Sproul
+*/
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "wiring_private.h"
+
+#ifndef BV
+#define BV(x) (1 << (x))
+#endif
+
+#define bit_pos(A) ((A) == 1u << 0 ? 0 \
+: (A) == 1u << 1 ? 1 \
+: (A) == 1u << 2 ? 2 \
+: (A) == 1u << 3 ? 3 \
+: (A) == 1u << 4 ? 4 \
+: (A) == 1u << 5 ? 5 \
+: (A) == 1u << 6 ? 6 \
+: (A) == 1u << 7 ? 7 \
+: 0)
+
+#define NUM_INTS_PER_PORT 8
+static volatile voidFuncPtr intFuncP1[NUM_INTS_PER_PORT];
+#if defined(__MSP430_HAS_PORT2_R__)
+static volatile voidFuncPtr intFuncP2[NUM_INTS_PER_PORT];
+#endif
+
+void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
+ uint8_t bit = digitalPinToBitMask(interruptNum);
+ uint8_t port = digitalPinToPort(interruptNum);
+
+
+ if ((port == NOT_A_PIN) || !((mode == FALLING) || (mode == RISING))) return;
+
+ __dint();
+
+ switch(port) {
+ case P1:
+ P1IE |= bit;
+ P1IFG &= ~bit;
+ P1IES = mode ? P1IES | bit : P1IES & ~bit;
+ intFuncP1[bit_pos(bit)] = userFunc;
+ break;
+ #if defined(__MSP430_HAS_PORT2_R__)
+ case P2:
+ P2IE |= bit;
+ P2IFG &= ~bit;
+ P2IES = mode ? P2IES | bit : P2IES & ~bit;
+ intFuncP2[bit_pos(bit)] = userFunc;
+ break;
+ #endif
+ default:
+ break;
+ }
+
+ __eint();
+}
+
+void detachInterrupt(uint8_t interruptNum) {
+ uint8_t bit = digitalPinToBitMask(interruptNum);
+ uint8_t port = digitalPinToPort(interruptNum);
+
+ if (port == NOT_A_PIN) return;
+
+ switch(port) {
+ case P1:
+ P1IE &= ~bit;
+ intFuncP1[bit_pos(bit)] = 0;
+ break;
+ #if defined(__MSP430_HAS_PORT2_R__)
+ case P2:
+ P2IE &= ~bit;
+ intFuncP2[bit_pos(bit)] = 0;
+ break;
+ #endif
+ default:
+ break;
+ }
+}
+
+
+__attribute__((interrupt(PORT1_VECTOR)))
+void Port_1(void)
+{
+ uint8_t i;
+ for(i = 0; i < 8; i++) {
+ if((P1IFG & BV(i)) && intFuncP1[i]) {
+ intFuncP1[i]();
+ P1IFG &= ~BV(i);
+ }
+ }
+}
+
+#if defined(__MSP430_HAS_PORT2_R__)
+__attribute__((interrupt(PORT2_VECTOR)))
+void Port_2(void)
+{
+ uint8_t i;
+ for(i = 0; i < 8; i++) {
+ if((P2IFG & BV(i)) && intFuncP2[i]) {
+ intFuncP2[i]();
+ P2IFG &= ~BV(i);
+ }
+ }
+}
+#endif
diff --git a/lib/msp430/WMath.cpp b/lib/msp430/WMath.cpp
new file mode 100644
index 0000000..d754215
--- /dev/null
+++ b/lib/msp430/WMath.cpp
@@ -0,0 +1,65 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ Part of the Wiring project - http://wiring.org.co
+ Copyright (c) 2004-06 Hernando Barragan
+ Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
+
+ 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
+
+ $Id$
+*/
+
+extern "C" {
+ #include "stdlib.h"
+ /* Using interal random and srandom in file random.c
+ * until msp430-libc adds supports for random and srandom */
+ extern long random(void);
+ extern void srandom(unsigned long __seed);
+}
+
+void randomSeed(unsigned int seed)
+{
+ if (seed != 0) {
+ srandom(seed);
+ }
+}
+
+long random(long howbig)
+{
+ if (howbig == 0) {
+ return 0;
+ }
+ return random() % howbig;
+}
+
+long random(long howsmall, long howbig)
+{
+ if (howsmall >= howbig) {
+ return howsmall;
+ }
+ long diff = howbig - howsmall;
+ 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;
+}
+
+unsigned int makeWord(unsigned int w) { return w; }
+unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
diff --git a/lib/msp430/WString.cpp b/lib/msp430/WString.cpp
new file mode 100644
index 0000000..2da6894
--- /dev/null
+++ b/lib/msp430/WString.cpp
@@ -0,0 +1,649 @@
+/*
+ WString.cpp - String library for Wiring & Arduino
+ ...mostly rewritten by Paul Stoffregen...
+ Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
+ Copyright 2011, Paul Stoffregen, paul@pjrc.com
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "WString.h"
+
+
+/*********************************************/
+/* Constructors */
+/*********************************************/
+
+String::String(const char *cstr)
+{
+ init();
+ if (cstr) copy(cstr, strlen(cstr));
+}
+
+String::String(const String &value)
+{
+ init();
+ *this = value;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String::String(String &&rval)
+{
+ init();
+ move(rval);
+}
+String::String(StringSumHelper &&rval)
+{
+ init();
+ move(rval);
+}
+#endif
+
+String::String(char c)
+{
+ init();
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ *this = buf;
+}
+
+String::String(unsigned char value, unsigned char base)
+{
+ init();
+ char buf[9];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(int value, unsigned char base)
+{
+ init();
+ char buf[18];
+ itoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(unsigned int value, unsigned char base)
+{
+ init();
+ char buf[17];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(long value, unsigned char base)
+{
+ init();
+ char buf[34];
+ ltoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(unsigned long value, unsigned char base)
+{
+ init();
+ char buf[33];
+ ultoa(value, buf, base);
+ *this = buf;
+}
+
+String::~String()
+{
+ free(buffer);
+}
+
+/*********************************************/
+/* Memory Management */
+/*********************************************/
+
+inline void String::init(void)
+{
+ buffer = NULL;
+ capacity = 0;
+ len = 0;
+ flags = 0;
+}
+
+void String::invalidate(void)
+{
+ if (buffer) free(buffer);
+ buffer = NULL;
+ capacity = len = 0;
+}
+
+unsigned char String::reserve(unsigned int size)
+{
+ if (buffer && capacity >= size) return 1;
+ if (changeBuffer(size)) {
+ if (len == 0) buffer[0] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+unsigned char String::changeBuffer(unsigned int maxStrLen)
+{
+ //char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
+ char *newbuffer = (char *)malloc(maxStrLen + 1);
+
+ if (newbuffer) {
+ strncpy(newbuffer, buffer, len);
+ free(buffer);
+ buffer = newbuffer;
+ capacity = maxStrLen;
+ return 1;
+ }
+ return 0;
+}
+
+/*********************************************/
+/* Copy and Move */
+/*********************************************/
+
+String & String::copy(const char *cstr, unsigned int length)
+{
+ if (!reserve(length)) {
+ invalidate();
+ return *this;
+ }
+ len = length;
+ strcpy(buffer, cstr);
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+void String::move(String &rhs)
+{
+ if (buffer) {
+ if (capacity >= rhs.len) {
+ strcpy(buffer, rhs.buffer);
+ len = rhs.len;
+ rhs.len = 0;
+ return;
+ } else {
+ free(buffer);
+ }
+ }
+ buffer = rhs.buffer;
+ capacity = rhs.capacity;
+ len = rhs.len;
+ rhs.buffer = NULL;
+ rhs.capacity = 0;
+ rhs.len = 0;
+}
+#endif
+
+String & String::operator = (const String &rhs)
+{
+ if (this == &rhs) return *this;
+
+ if (rhs.buffer) copy(rhs.buffer, rhs.len);
+ else invalidate();
+
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String & String::operator = (String &&rval)
+{
+ if (this != &rval) move(rval);
+ return *this;
+}
+
+String & String::operator = (StringSumHelper &&rval)
+{
+ if (this != &rval) move(rval);
+ return *this;
+}
+#endif
+
+String & String::operator = (const char *cstr)
+{
+ if (cstr) copy(cstr, strlen(cstr));
+ else invalidate();
+
+ return *this;
+}
+
+/*********************************************/
+/* concat */
+/*********************************************/
+
+unsigned char String::concat(const String &s)
+{
+ return concat(s.buffer, s.len);
+}
+
+unsigned char String::concat(const char *cstr, unsigned int length)
+{
+ unsigned int newlen = len + length;
+ if (!cstr) return 0;
+ if (length == 0) return 1;
+ if (!reserve(newlen)) return 0;
+ strcpy(buffer + len, cstr);
+ len = newlen;
+ return 1;
+}
+
+unsigned char String::concat(const char *cstr)
+{
+ if (!cstr) return 0;
+ return concat(cstr, strlen(cstr));
+}
+
+unsigned char String::concat(char c)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ return concat(buf, 1);
+}
+
+unsigned char String::concat(unsigned char num)
+{
+ char buf[4];
+ itoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(int num)
+{
+ char buf[7];
+ itoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned int num)
+{
+ char buf[6];
+ utoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(long num)
+{
+ char buf[12];
+ ltoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned long num)
+{
+ char buf[11];
+ ultoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+/*********************************************/
+/* Concatenate */
+/*********************************************/
+
+StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, char c)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(c)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, int num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, long num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+/*********************************************/
+/* Comparison */
+/*********************************************/
+
+int String::compareTo(const String &s) const
+{
+ if (!buffer || !s.buffer) {
+ if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
+ if (buffer && len > 0) return *(unsigned char *)buffer;
+ return 0;
+ }
+ return strcmp(buffer, s.buffer);
+}
+
+unsigned char String::equals(const String &s2) const
+{
+ return (len == s2.len && compareTo(s2) == 0);
+}
+
+unsigned char String::equals(const char *cstr) const
+{
+ if (len == 0) return (cstr == NULL || *cstr == 0);
+ if (cstr == NULL) return buffer[0] == 0;
+ return strcmp(buffer, cstr) == 0;
+}
+
+unsigned char String::operator<(const String &rhs) const
+{
+ return compareTo(rhs) < 0;
+}
+
+unsigned char String::operator>(const String &rhs) const
+{
+ return compareTo(rhs) > 0;
+}
+
+unsigned char String::operator<=(const String &rhs) const
+{
+ return compareTo(rhs) <= 0;
+}
+
+unsigned char String::operator>=(const String &rhs) const
+{
+ return compareTo(rhs) >= 0;
+}
+
+unsigned char String::equalsIgnoreCase( const String &s2 ) const
+{
+ if (this == &s2) return 1;
+ if (len != s2.len) return 0;
+ if (len == 0) return 1;
+ const char *p1 = buffer;
+ const char *p2 = s2.buffer;
+ while (*p1) {
+ if (tolower(*p1++) != tolower(*p2++)) return 0;
+ }
+ return 1;
+}
+
+unsigned char String::startsWith( const String &s2 ) const
+{
+ if (len < s2.len) return 0;
+ return startsWith(s2, 0);
+}
+
+unsigned char String::startsWith( const String &s2, unsigned int offset ) const
+{
+ if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
+ return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
+}
+
+unsigned char String::endsWith( const String &s2 ) const
+{
+ if ( len < s2.len || !buffer || !s2.buffer) return 0;
+ return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
+}
+
+/*********************************************/
+/* Character Access */
+/*********************************************/
+
+char String::charAt(unsigned int loc) const
+{
+ return operator[](loc);
+}
+
+void String::setCharAt(unsigned int loc, char c)
+{
+ if (loc < len) buffer[loc] = c;
+}
+
+char & String::operator[](unsigned int index)
+{
+ static char dummy_writable_char;
+ if (index >= len || !buffer) {
+ dummy_writable_char = 0;
+ return dummy_writable_char;
+ }
+ return buffer[index];
+}
+
+char String::operator[]( unsigned int index ) const
+{
+ if (index >= len || !buffer) return 0;
+ return buffer[index];
+}
+
+void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
+{
+ if (!bufsize || !buf) return;
+ if (index >= len) {
+ buf[0] = 0;
+ return;
+ }
+ unsigned int n = bufsize - 1;
+ if (n > len - index) n = len - index;
+ strncpy((char *)buf, buffer + index, n);
+ buf[n] = 0;
+}
+
+/*********************************************/
+/* Search */
+/*********************************************/
+
+int String::indexOf(char c) const
+{
+ return indexOf(c, 0);
+}
+
+int String::indexOf( char ch, unsigned int fromIndex ) const
+{
+ if (fromIndex >= len) return -1;
+ const char* temp = strchr(buffer + fromIndex, ch);
+ if (temp == NULL) return -1;
+ return temp - buffer;
+}
+
+int String::indexOf(const String &s2) const
+{
+ return indexOf(s2, 0);
+}
+
+int String::indexOf(const String &s2, unsigned int fromIndex) const
+{
+ if (fromIndex >= len) return -1;
+ const char *found = strstr(buffer + fromIndex, s2.buffer);
+ if (found == NULL) return -1;
+ return found - buffer;
+}
+
+int String::lastIndexOf( char theChar ) const
+{
+ return lastIndexOf(theChar, len - 1);
+}
+
+int String::lastIndexOf(char ch, unsigned int fromIndex) const
+{
+ if (fromIndex >= len) return -1;
+ char tempchar = buffer[fromIndex + 1];
+ buffer[fromIndex + 1] = '\0';
+ char* temp = strrchr( buffer, ch );
+ buffer[fromIndex + 1] = tempchar;
+ if (temp == NULL) return -1;
+ return temp - buffer;
+}
+
+int String::lastIndexOf(const String &s2) const
+{
+ return lastIndexOf(s2, len - s2.len);
+}
+
+int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
+{
+ if (s2.len == 0 || len == 0 || s2.len > len) return -1;
+ if (fromIndex >= len) fromIndex = len - 1;
+ int found = -1;
+ for (char *p = buffer; p <= buffer + fromIndex; p++) {
+ p = strstr(p, s2.buffer);
+ if (!p) break;
+ if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
+ }
+ return found;
+}
+
+String String::substring( unsigned int left ) const
+{
+ return substring(left, len);
+}
+
+String String::substring(unsigned int left, unsigned int right) const
+{
+ if (left > right) {
+ unsigned int temp = right;
+ right = left;
+ left = temp;
+ }
+ String out;
+ if (left > len) return out;
+ if (right > len) right = len;
+ char temp = buffer[right]; // save the replaced character
+ buffer[right] = '\0';
+ out = buffer + left; // pointer arithmetic
+ buffer[right] = temp; //restore character
+ return out;
+}
+
+/*********************************************/
+/* Modification */
+/*********************************************/
+
+void String::replace(char find, char replace)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ if (*p == find) *p = replace;
+ }
+}
+
+void String::replace(const String& find, const String& replace)
+{
+ if (len == 0 || find.len == 0) return;
+ int diff = replace.len - find.len;
+ char *readFrom = buffer;
+ char *foundAt;
+ if (diff == 0) {
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ memcpy(foundAt, replace.buffer, replace.len);
+ readFrom = foundAt + replace.len;
+ }
+ } else if (diff < 0) {
+ char *writeTo = buffer;
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ unsigned int n = foundAt - readFrom;
+ memcpy(writeTo, readFrom, n);
+ writeTo += n;
+ memcpy(writeTo, replace.buffer, replace.len);
+ writeTo += replace.len;
+ readFrom = foundAt + find.len;
+ len += diff;
+ }
+ strcpy(writeTo, readFrom);
+ } else {
+ unsigned int size = len; // compute size needed for result
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ readFrom = foundAt + find.len;
+ size += diff;
+ }
+ if (size == len) return;
+ if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
+ int index = len - 1;
+ while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
+ readFrom = buffer + index + find.len;
+ memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
+ len += diff;
+ buffer[len] = 0;
+ memcpy(buffer + index, replace.buffer, replace.len);
+ index--;
+ }
+ }
+}
+
+void String::toLowerCase(void)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ *p = tolower(*p);
+ }
+}
+
+void String::toUpperCase(void)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ *p = toupper(*p);
+ }
+}
+
+void String::trim(void)
+{
+ if (!buffer || len == 0) return;
+ char *begin = buffer;
+ while (isspace(*begin)) begin++;
+ char *end = buffer + len - 1;
+ while (isspace(*end) && end >= begin) end--;
+ len = end + 1 - begin;
+ if (begin > buffer) memcpy(buffer, begin, len);
+ buffer[len] = 0;
+}
+
+/*********************************************/
+/* Parsing / Conversion */
+/*********************************************/
+
+long String::toInt(void) const
+{
+ if (buffer) return atol(buffer);
+ return 0;
+}
+
+
diff --git a/lib/msp430/WString.h b/lib/msp430/WString.h
new file mode 100644
index 0000000..73d1213
--- /dev/null
+++ b/lib/msp430/WString.h
@@ -0,0 +1,204 @@
+/*
+ WString.h - String library for Wiring & Arduino
+ ...mostly rewritten by Paul Stoffregen...
+ Copyright (c) 2009-10 Hernando Barragan. All right reserved.
+ Copyright 2011, Paul Stoffregen, paul@pjrc.com
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef String_class_h
+#define String_class_h
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+// When compiling programs with this class, the following gcc parameters
+// dramatically increase performance and memory (RAM) efficiency, typically
+// with little or no increase in code size.
+// -felide-constructors
+// -std=c++0x
+
+//class __FlashStringHelper;
+//#define F(string_literal) (reinterpret_cast<__FlashStringHelper *>(PSTR(string_literal)))
+
+// An inherited class for holding the result of a concatenation. These
+// result objects are assumed to be writable by subsequent concatenations.
+class StringSumHelper;
+
+// The string class
+class String
+{
+ // use a function pointer to allow for "if (s)" without the
+ // complications of an operator bool(). for more information, see:
+ // http://www.artima.com/cppsource/safebool.html
+ typedef void (String::*StringIfHelperType)() const;
+ void StringIfHelper() const {}
+
+public:
+ // constructors
+ // creates a copy of the initial value.
+ // if the initial value is null or invalid, or if memory allocation
+ // fails, the string will be marked as invalid (i.e. "if (s)" will
+ // be false).
+ String(const char *cstr = "");
+ String(const String &str);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ String(String &&rval);
+ String(StringSumHelper &&rval);
+ #endif
+ explicit String(char c);
+ explicit String(unsigned char, unsigned char base=10);
+ explicit String(int, unsigned char base=10);
+ explicit String(unsigned int, unsigned char base=10);
+ explicit String(long, unsigned char base=10);
+ explicit String(unsigned long, unsigned char base=10);
+ ~String(void);
+
+ // memory management
+ // return true on success, false on failure (in which case, the string
+ // is left unchanged). reserve(0), if successful, will validate an
+ // invalid string (i.e., "if (s)" will be true afterwards)
+ unsigned char reserve(unsigned int size);
+ inline unsigned int length(void) const {return len;}
+
+ // creates a copy of the assigned value. if the value is null or
+ // invalid, or if the memory allocation fails, the string will be
+ // marked as invalid ("if (s)" will be false).
+ String & operator = (const String &rhs);
+ String & operator = (const char *cstr);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ String & operator = (String &&rval);
+ String & operator = (StringSumHelper &&rval);
+ #endif
+
+ // concatenate (works w/ built-in types)
+
+ // returns true on success, false on failure (in which case, the string
+ // is left unchanged). if the argument is null or invalid, the
+ // concatenation is considered unsucessful.
+ unsigned char concat(const String &str);
+ unsigned char concat(const char *cstr);
+ unsigned char concat(char c);
+ unsigned char concat(unsigned char c);
+ unsigned char concat(int num);
+ unsigned char concat(unsigned int num);
+ unsigned char concat(long num);
+ unsigned char concat(unsigned long num);
+
+ // if there's not enough memory for the concatenated value, the string
+ // will be left unchanged (but this isn't signalled in any way)
+ String & operator += (const String &rhs) {concat(rhs); return (*this);}
+ String & operator += (const char *cstr) {concat(cstr); return (*this);}
+ String & operator += (char c) {concat(c); return (*this);}
+ String & operator += (unsigned char num) {concat(num); return (*this);}
+ String & operator += (int num) {concat(num); return (*this);}
+ String & operator += (unsigned int num) {concat(num); return (*this);}
+ String & operator += (long num) {concat(num); return (*this);}
+ String & operator += (unsigned long num) {concat(num); return (*this);}
+
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
+
+ // comparison (only works w/ Strings and "strings")
+ operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
+ int compareTo(const String &s) const;
+ unsigned char equals(const String &s) const;
+ unsigned char equals(const char *cstr) const;
+ unsigned char operator == (const String &rhs) const {return equals(rhs);}
+ unsigned char operator == (const char *cstr) const {return equals(cstr);}
+ unsigned char operator != (const String &rhs) const {return !equals(rhs);}
+ unsigned char operator != (const char *cstr) const {return !equals(cstr);}
+ unsigned char operator < (const String &rhs) const;
+ unsigned char operator > (const String &rhs) const;
+ unsigned char operator <= (const String &rhs) const;
+ unsigned char operator >= (const String &rhs) const;
+ unsigned char equalsIgnoreCase(const String &s) const;
+ unsigned char startsWith( const String &prefix) const;
+ unsigned char startsWith(const String &prefix, unsigned int offset) const;
+ unsigned char endsWith(const String &suffix) const;
+
+ // character acccess
+ char charAt(unsigned int index) const;
+ void setCharAt(unsigned int index, char c);
+ char operator [] (unsigned int index) const;
+ char& operator [] (unsigned int index);
+ void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
+ void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
+ {getBytes((unsigned char *)buf, bufsize, index);}
+
+ // search
+ int indexOf( char ch ) const;
+ int indexOf( char ch, unsigned int fromIndex ) const;
+ int indexOf( const String &str ) const;
+ int indexOf( const String &str, unsigned int fromIndex ) const;
+ int lastIndexOf( char ch ) const;
+ int lastIndexOf( char ch, unsigned int fromIndex ) const;
+ int lastIndexOf( const String &str ) const;
+ int lastIndexOf( const String &str, unsigned int fromIndex ) const;
+ String substring( unsigned int beginIndex ) const;
+ String substring( unsigned int beginIndex, unsigned int endIndex ) const;
+
+ // modification
+ void replace(char find, char replace);
+ void replace(const String& find, const String& replace);
+ void toLowerCase(void);
+ void toUpperCase(void);
+ void trim(void);
+
+ // parsing/conversion
+ long toInt(void) const;
+
+protected:
+ char *buffer; // the actual char array
+ unsigned int capacity; // the array length minus one (for the '\0')
+ unsigned int len; // the String length (not counting the '\0')
+ unsigned char flags; // unused, for future features
+protected:
+ void init(void);
+ void invalidate(void);
+ unsigned char changeBuffer(unsigned int maxStrLen);
+ unsigned char concat(const char *cstr, unsigned int length);
+
+ // copy and move
+ String & copy(const char *cstr, unsigned int length);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ void move(String &rhs);
+ #endif
+};
+
+class StringSumHelper : public String
+{
+public:
+ StringSumHelper(const String &s) : String(s) {}
+ StringSumHelper(const char *p) : String(p) {}
+ StringSumHelper(char c) : String(c) {}
+ StringSumHelper(unsigned char num) : String(num) {}
+ StringSumHelper(int num) : String(num) {}
+ StringSumHelper(unsigned int num) : String(num) {}
+ StringSumHelper(long num) : String(num) {}
+ StringSumHelper(unsigned long num) : String(num) {}
+};
+
+#endif // __cplusplus
+#endif // String_class_h
diff --git a/lib/msp430/Wire.cpp b/lib/msp430/Wire.cpp
new file mode 100644
index 0000000..d7d74a6
--- /dev/null
+++ b/lib/msp430/Wire.cpp
@@ -0,0 +1,307 @@
+/*
+ ************************************************************************
+ * Wire.cpp
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ TwoWire.cpp - TWI/I2C library for Wiring & Arduino
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
+*/
+
+extern "C" {
+ #include <stdlib.h>
+ #include <string.h>
+ #include <inttypes.h>
+ #include "twi.h"
+}
+
+#include "Wire.h"
+
+// Initialize Class Variables //////////////////////////////////////////////////
+
+uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
+uint8_t TwoWire::rxBufferIndex = 0;
+uint8_t TwoWire::rxBufferLength = 0;
+
+uint8_t TwoWire::txAddress = 0;
+uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
+uint8_t TwoWire::txBufferIndex = 0;
+uint8_t TwoWire::txBufferLength = 0;
+
+uint8_t TwoWire::transmitting = 0;
+void (*TwoWire::user_onRequest)(void);
+void (*TwoWire::user_onReceive)(int);
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+TwoWire::TwoWire()
+{
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void TwoWire::begin(void)
+{
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ twi_init();
+}
+
+void TwoWire::begin(uint8_t address)
+{
+ twi_setAddress(address);
+ twi_attachSlaveTxEvent(onRequestService);
+ twi_attachSlaveRxEvent(onReceiveService);
+ begin();
+}
+
+void TwoWire::begin(int address)
+{
+ begin((uint8_t)address);
+}
+
+uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
+{
+ // clamp to buffer length
+ if(quantity > BUFFER_LENGTH){
+ quantity = BUFFER_LENGTH;
+ }
+ // perform blocking read into buffer
+ uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
+ // set rx buffer iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = read;
+
+ return read;
+}
+
+uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
+{
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
+}
+
+uint8_t TwoWire::requestFrom(int address, int quantity)
+{
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
+}
+
+uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
+{
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
+}
+
+void TwoWire::beginTransmission(uint8_t address)
+{
+ // indicate that we are transmitting
+ transmitting = 1;
+ // set address of targeted slave
+ txAddress = address;
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+}
+
+void TwoWire::beginTransmission(int address)
+{
+ beginTransmission((uint8_t)address);
+}
+
+//
+// Originally, 'endTransmission' was an f(void) function.
+// It has been modified to take one parameter indicating
+// whether or not a STOP should be performed on the bus.
+// Calling endTransmission(false) allows a sketch to
+// perform a repeated start.
+//
+// WARNING: Nothing in the library keeps track of whether
+// the bus tenure has been properly ended with a STOP. It
+// is very possible to leave the bus in a hung state if
+// no call to endTransmission(true) is made. Some I2C
+// devices will behave oddly if they do not see a STOP.
+//
+uint8_t TwoWire::endTransmission(uint8_t sendStop)
+{
+ // transmit buffer (blocking)
+ int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ // indicate that we are done transmitting
+ transmitting = 0;
+ return ret;
+}
+
+// This provides backwards compatibility with the original
+// definition, and expected behaviour, of endTransmission
+//
+uint8_t TwoWire::endTransmission(void)
+{
+ return endTransmission(true);
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+size_t TwoWire::write(uint8_t data)
+{
+ if(transmitting){
+ // in master transmitter mode
+ // don't bother if buffer is full
+ if(txBufferLength >= BUFFER_LENGTH){
+ setWriteError();
+ return 0;
+ }
+ // put byte in tx buffer
+ txBuffer[txBufferIndex] = data;
+ ++txBufferIndex;
+ // update amount in buffer
+ txBufferLength = txBufferIndex;
+ }else{
+ // in slave send mode
+ // reply to master
+ twi_transmit(&data, 1);
+ }
+ return 1;
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+size_t TwoWire::write(const uint8_t *data, size_t quantity)
+{
+ if(transmitting){
+ // in master transmitter mode
+ for(size_t i = 0; i < quantity; ++i){
+ write(data[i]);
+ }
+ }else{
+ // in slave send mode
+ // reply to master
+ twi_transmit(data, quantity);
+ }
+ return quantity;
+}
+
+// must be called in:
+// slave rx event callback
+// or after requestFrom(address, numBytes)
+int TwoWire::available(void)
+{
+ return rxBufferLength - rxBufferIndex;
+}
+
+// must be called in:
+// slave rx event callback
+// or after requestFrom(address, numBytes)
+int TwoWire::read(void)
+{
+ int value = -1;
+
+ // get each successive byte on each call
+ if(rxBufferIndex < rxBufferLength){
+ value = rxBuffer[rxBufferIndex];
+ ++rxBufferIndex;
+ }
+
+ return value;
+}
+
+// must be called in:
+// slave rx event callback
+// or after requestFrom(address, numBytes)
+int TwoWire::peek(void)
+{
+ int value = -1;
+
+ if(rxBufferIndex < rxBufferLength){
+ value = rxBuffer[rxBufferIndex];
+ }
+
+ return value;
+}
+
+void TwoWire::flush(void)
+{
+ // XXX: to be implemented.
+}
+
+// behind the scenes function that is called when data is received
+void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
+{
+ // don't bother if user hasn't registered a callback
+ if(!user_onReceive){
+ return;
+ }
+ // don't bother if rx buffer is in use by a master requestFrom() op
+ // i know this drops data, but it allows for slight stupidity
+ // meaning, they may not have read all the master requestFrom() data yet
+ if(rxBufferIndex < rxBufferLength){
+ return;
+ }
+ // copy twi rx buffer into local read buffer
+ // this enables new reads to happen in parallel
+ for(uint8_t i = 0; i < numBytes; ++i){
+ rxBuffer[i] = inBytes[i];
+ }
+ // set rx iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = numBytes;
+ // alert user program
+ user_onReceive(numBytes);
+}
+
+// behind the scenes function that is called when data is requested
+void TwoWire::onRequestService(void)
+{
+ // don't bother if user hasn't registered a callback
+ if(!user_onRequest){
+ return;
+ }
+ // reset tx buffer iterator vars
+ // !!! this will kill any pending pre-master sendTo() activity
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ // alert user program
+ user_onRequest();
+}
+
+// sets function called on slave write
+void TwoWire::onReceive( void (*function)(int) )
+{
+ user_onReceive = function;
+}
+
+// sets function called on slave read
+void TwoWire::onRequest( void (*function)(void) )
+{
+ user_onRequest = function;
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+TwoWire Wire = TwoWire();
+
diff --git a/lib/msp430/Wire.h b/lib/msp430/Wire.h
new file mode 100644
index 0000000..3f633c4
--- /dev/null
+++ b/lib/msp430/Wire.h
@@ -0,0 +1,94 @@
+/*
+ ************************************************************************
+ * Wire.h
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ TwoWire.h - TWI/I2C library for Arduino & Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
+*/
+
+#ifndef TwoWire_h
+#define TwoWire_h
+
+#include <inttypes.h>
+#include "Stream.h"
+
+#define BUFFER_LENGTH 16
+
+class TwoWire : public Stream
+{
+ private:
+ static uint8_t rxBuffer[];
+ static uint8_t rxBufferIndex;
+ static uint8_t rxBufferLength;
+
+ static uint8_t txAddress;
+ static uint8_t txBuffer[];
+ static uint8_t txBufferIndex;
+ static uint8_t txBufferLength;
+
+ static uint8_t transmitting;
+ static void (*user_onRequest)(void);
+ static void (*user_onReceive)(int);
+ static void onRequestService(void);
+ static void onReceiveService(uint8_t*, int);
+ public:
+ TwoWire();
+ void begin();
+ void begin(uint8_t);
+ void begin(int);
+ void beginTransmission(uint8_t);
+ void beginTransmission(int);
+ uint8_t endTransmission(void);
+ uint8_t endTransmission(uint8_t);
+ uint8_t requestFrom(uint8_t, uint8_t);
+ uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
+ uint8_t requestFrom(int, int);
+ uint8_t requestFrom(int, int, int);
+ virtual size_t write(uint8_t);
+ virtual size_t write(const uint8_t *, size_t);
+ virtual int available(void);
+ virtual int read(void);
+ virtual int peek(void);
+ virtual void flush(void);
+#define USCI_ERROR "\n*********\nI2C Slave is not implemented for this MSP430. \nConsider using using a MSP430 with USCI peripheral e.g. MSP430G2553.\n*********\n"
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+ void onReceive( void (*)(int) );
+ void onRequest( void (*)(void) );
+#else
+ void onReceive( void (*)(int) ) __attribute__ ((error(USCI_ERROR)));
+ void onRequest( void (*)(void) ) __attribute__ ((error(USCI_ERROR)));
+#endif
+
+ inline size_t write(unsigned long n) { return write((uint8_t)n); }
+ inline size_t write(long n) { return write((uint8_t)n); }
+ inline size_t write(unsigned int n) { return write((uint8_t)n); }
+ inline size_t write(int n) { return write((uint8_t)n); }
+ using Print::write;
+};
+
+extern TwoWire Wire;
+
+#endif
+
diff --git a/lib/msp430/binary.h b/lib/msp430/binary.h
new file mode 100644
index 0000000..af14980
--- /dev/null
+++ b/lib/msp430/binary.h
@@ -0,0 +1,515 @@
+#ifndef Binary_h
+#define Binary_h
+
+#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
diff --git a/lib/msp430/main.cpp b/lib/msp430/main.cpp
new file mode 100644
index 0000000..138cc10
--- /dev/null
+++ b/lib/msp430/main.cpp
@@ -0,0 +1,16 @@
+#include <Energia.h>
+
+int main(void)
+{
+ init();
+
+ setup();
+
+ for (;;) {
+ loop();
+ if (serialEventRun) serialEventRun();
+ }
+
+ return 0;
+}
+
diff --git a/lib/msp430/new.cpp b/lib/msp430/new.cpp
new file mode 100644
index 0000000..0f6d422
--- /dev/null
+++ b/lib/msp430/new.cpp
@@ -0,0 +1,18 @@
+#include <new.h>
+
+void * operator new(size_t size)
+{
+ return malloc(size);
+}
+
+void operator delete(void * ptr)
+{
+ free(ptr);
+}
+
+int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
+void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
+void __cxa_guard_abort (__guard *) {};
+
+void __cxa_pure_virtual(void) {};
+
diff --git a/lib/msp430/new.h b/lib/msp430/new.h
new file mode 100644
index 0000000..cd940ce
--- /dev/null
+++ b/lib/msp430/new.h
@@ -0,0 +1,22 @@
+/* Header to define new/delete operators as they aren't provided by avr-gcc by default
+ Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
+ */
+
+#ifndef NEW_H
+#define NEW_H
+
+#include <stdlib.h>
+
+void * operator new(size_t size);
+void operator delete(void * ptr);
+
+__extension__ typedef int __guard __attribute__((mode (__DI__)));
+
+extern "C" int __cxa_guard_acquire(__guard *);
+extern "C" void __cxa_guard_release (__guard *);
+extern "C" void __cxa_guard_abort (__guard *);
+
+extern "C" void __cxa_pure_virtual(void);
+
+#endif
+
diff --git a/lib/msp430/random.c b/lib/msp430/random.c
new file mode 100644
index 0000000..6b46d5e
--- /dev/null
+++ b/lib/msp430/random.c
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
+ *
+ * $Id$
+ */
+
+/*
+ * From:
+static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93";
+*/
+#ifndef RANDOM_MAX
+#define RANDOM_MAX 0x7FFFFFFF
+#endif
+
+#include <stdlib.h>
+
+static long
+do_random(unsigned long *ctx)
+{
+ /*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ * (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+ long hi, lo, x;
+
+ x = *ctx;
+ /* Can't be initialized with 0, so use another value. */
+ if (x == 0)
+ x = 123459876L;
+ hi = x / 127773L;
+ lo = x % 127773L;
+ x = 16807L * lo - 2836L * hi;
+ if (x < 0)
+ x += 0x7fffffffL;
+ return ((*ctx = x) % ((unsigned long)RANDOM_MAX + 1));
+}
+
+
+long
+random_r(unsigned long *ctx)
+{
+ return do_random(ctx);
+}
+
+
+static unsigned long next = 1;
+
+long
+random(void)
+{
+ return do_random(&next);
+}
+
+void
+srandom(unsigned long seed)
+{
+ next = seed;
+}
+
diff --git a/lib/msp430/twi.c b/lib/msp430/twi.c
new file mode 100644
index 0000000..b92a6fe
--- /dev/null
+++ b/lib/msp430/twi.c
@@ -0,0 +1,850 @@
+/*
+ ************************************************************************
+ * twi.c
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ twi.c - TWI/I2C library for Wiring & Arduino
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <math.h>
+#include <stdlib.h>
+#include "Energia.h" // for digitalWrite
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+
+#include "wiring_private.h"
+#include "pins_energia.h"
+#include "twi.h"
+#include "usci_isr_handler.h"
+
+static volatile uint8_t twi_state;
+static volatile uint8_t twi_sendStop; // should the transaction end with a stop
+static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
+
+static void (*twi_onSlaveTransmit)(void);
+static void (*twi_onSlaveReceive)(uint8_t*, int);
+
+static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
+static volatile uint8_t twi_masterBufferIndex;
+static uint8_t twi_masterBufferLength;
+
+static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
+static volatile uint8_t twi_txBufferIndex;
+static volatile uint8_t twi_txBufferLength;
+#if (defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_B0__))
+static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
+static volatile uint8_t twi_rxBufferIndex;
+#endif
+
+static volatile uint8_t twi_error;
+
+#ifdef __MSP430_HAS_USI__
+static uint8_t twi_slarw;
+static uint8_t twi_my_addr;
+
+#endif
+
+#ifdef __MSP430_HAS_USCI__
+#endif
+
+#ifdef __MSP430_HAS_EUSCI_B0__
+#endif
+
+/*
+ * Function twi_init
+ * Desc readys twi pins and sets twi bitrate
+ * Input none
+ * Output none
+ */
+void twi_init(void)
+{
+ // initialize state
+ twi_state = TWI_IDLE;
+ twi_sendStop = true; // default value
+ twi_inRepStart = false;
+
+#ifdef __MSP430_HAS_USI__
+
+ /* 100 KHz for all */
+#if (F_CPU >= 16000000L) || (F_CPU >= 12000000L)
+ USICKCTL = USIDIV_7;
+#elif defined(CALBC1_8MHZ_) && (F_CPU >= 8000000L)
+ USICKCTL = USIDIV_6;
+#elif defined(CALBC1_1MHZ_) && (F_CPU >= 1000000L)
+ USICKCTL = USIDIV_3;
+#endif
+ /* Enable USI I2C mode. */
+ USICTL1 = USII2C;
+ /* SDA/SCL port enable and hold in reset */
+ USICTL0 = (USIPE6 | USIPE7 | USISWRST);
+ /* SMCLK and SCL inactive state is high */
+ USICKCTL |= (USISSEL_2 | USICKPL);
+ /* Disable automatic clear control */
+ USICNT |= USIIFGCC;
+ /* Enable USI */
+ USICTL0 &= ~USISWRST;
+ /* Counter interrupt enable */
+ USICTL1 |= USIIE;
+#endif
+
+#ifdef __MSP430_HAS_USCI__
+ /* Calling this dummy function prevents the linker
+ * from stripping the USCI interupt vectors.*/
+ usci_isr_install();
+
+ P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
+ P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
+
+ //Disable the USCI module and clears the other bits of control register
+ UCB0CTL1 = UCSWRST;
+
+ /*
+ * Configure as I2C Slave.
+ * UCMODE_3 = I2C mode
+ * UCSYNC = Synchronous mode
+ * UCCLK = SMCLK
+ */
+ UCB0CTL0 = UCMODE_3 | UCSYNC;
+ /*
+ * Compute the clock divider that achieves less than or
+ * equal to 100kHz. The numerator is biased to favor a larger
+ * clock divider so that the resulting clock is always less than or equal
+ * to the desired clock, never greater.
+ */
+ UCB0BR0 = (unsigned char)((F_CPU / TWI_FREQ) & 0xFF);
+ UCB0BR1 = (unsigned char)((F_CPU / TWI_FREQ) >> 8);
+
+ UCB0CTL1 &= ~(UCSWRST);
+
+ /* Set I2C state change interrupt mask */
+ UCB0I2CIE |= (UCALIE|UCNACKIE|UCSTTIE|UCSTPIE);
+ /* Enable state change and TX/RX interrupts */
+ UC0IE |= UCB0RXIE | UCB0TXIE;
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+
+ P1SEL1 |= BIT6 + BIT7; // Pin init
+
+ //Disable the USCI module and clears the other bits of control register
+ UCB0CTLW0 = UCSWRST;
+
+ //Configure Automatic STOP condition generation
+ UCB0CTLW1 &= ~UCASTP_3;
+ //UCB0CTLW1 |= autoSTOPGeneration;
+
+ //Byte Count Threshold
+ //UCB0TBCNT = byteCounterThreshold;
+ /*
+ * Configure as I2C master mode.
+ * UCMST = Master mode
+ * UCMODE_3 = I2C mode
+ * UCSYNC = Synchronous mode
+ * UCCLK = SMCLK
+ */
+ UCB0CTLW0 = UCMODE_3 | UCSSEL__SMCLK | UCSYNC | UCSWRST;
+
+ /*
+ * Compute the clock divider that achieves the fastest speed less than or
+ * equal to the desired speed. The numerator is biased to favor a larger
+ * clock divider so that the resulting clock is always less than or equal
+ * to the desired clock, never greater.
+ */
+ UCB0BRW = (unsigned short)(F_CPU / 400000);
+ UCB0CTLW0 &= ~(UCSWRST);
+ UCB0IE |= (UCRXIE0|UCTXIE0|UCSTTIE|UCSTPIE); // Enable I2C interrupts
+#endif
+}
+
+/*
+ * Function twi_setAddress
+ * Desc sets slave address and enables interrupt
+ * Input none
+ * Output none
+ */
+void twi_setAddress(uint8_t address)
+{
+#ifdef __MSP430_HAS_USI__
+ twi_my_addr = address << 1;
+#endif
+#ifdef __MSP430_HAS_USCI__
+ /* UCGCEN = respond to general Call */
+ UCB0I2COA = (address | UCGCEN);
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+ /* UCGCEN = respond to general Call */
+ UCB0I2COA0 = (address | UCOAEN | UCGCEN);
+#endif
+}
+
+/*
+ * Function twi_readFrom
+ * Desc attempts to become twi bus master and read a
+ * series of bytes from a device on the bus
+ * Input address: 7bit i2c device address
+ * data: pointer to byte array
+ * length: number of bytes to read into array
+ * Output number of bytes read
+ */
+uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)
+{
+ uint8_t i;
+
+#ifdef __MSP430_HAS_USI__
+ /* Disable START condition interrupt */
+ USICTL1 &= ~USISTTIE;
+ /* I2C master mode */
+ USICTL0 |= USIMST;
+#endif
+#ifdef __MSP430_HAS_USCI__
+ UCB0CTL1 = UCSWRST; // Enable SW reset
+ UCB0CTL1 |= (UCSSEL_2); // I2C Master, synchronous mode
+ UCB0CTL0 |= (UCMST | UCMODE_3 | UCSYNC); // I2C Master, synchronous mode
+ UCB0CTL1 &= ~(UCTR); // Configure in receive mode
+ UCB0I2CSA = address; // Set Slave Address
+ UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
+ UCB0I2CIE |= (UCALIE|UCNACKIE|UCSTPIE); // Enable I2C interrupts
+ UC0IE |= (UCB0RXIE | UCB0TXIE); // Enable I2C interrupts
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+ UCB0CTLW0 = UCSWRST; // Enable SW reset
+ UCB0CTLW0 |= (UCMST | UCMODE_3 | UCSYNC | UCSSEL__SMCLK); // I2C Master, synchronous mode
+ UCB0CTLW0 &= ~(UCTR); // Configure in receive mode
+ UCB0I2CSA = address; // Set Slave Address
+ UCB0CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
+ UCB0IE |= (UCRXIE0|UCALIE|UCNACKIFG|UCSTTIFG|UCSTPIFG); // Enable I2C interrupts
+#endif
+ // ensure data will fit into buffer
+ if(TWI_BUFFER_LENGTH < length){
+ return 0;
+ }
+
+ // initialize buffer iteration vars
+ twi_masterBufferIndex = 0;
+ twi_masterBufferLength = length-1; // This is not intuitive, read on...
+ // On receive, the previously configured ACK/NACK setting is transmitted in
+ // response to the received byte before the interrupt is signalled.
+ // Therefor we must actually set NACK when the _next_ to last byte is
+ // received, causing that NACK to be sent in response to receiving the last
+ // expected byte of data.
+
+#ifdef __MSP430_HAS_USI__
+ /* build sla+w, slave device address + w bit */
+ twi_slarw = 1;
+ twi_slarw |= address << 1;
+
+ // send start condition
+ twi_state = TWI_SND_START;
+ // this will trigger an interrupt kicking off the state machine in the isr
+ USICTL1 |= USIIFG;
+#endif
+#ifdef __MSP430_HAS_USCI__
+ twi_state = TWI_MRX; // Master receive mode
+ UCB0CTL1 |= UCTXSTT; // I2C start condition
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+ twi_state = TWI_MRX; // Master receive mode
+ while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
+ UCB0CTLW0 |= UCTXSTT; // I2C start condition
+#endif
+
+ /* Wait in low power mode for read operation to complete */
+ while(twi_state != TWI_IDLE){
+ __bis_SR_register(LPM0_bits);
+ }
+
+ if (twi_masterBufferIndex < length)
+ length = twi_masterBufferIndex;
+
+ for(i = 0; i < length; ++i){
+ data[i] = twi_masterBuffer[i];
+ }
+
+#ifdef __MSP430_HAS_USCI__
+ /* Ensure stop condition got sent before we exit. */
+ while (UCB0CTL1 & UCTXSTP);
+#endif
+ return length;
+}
+
+/*
+ * Function twi_writeTo
+ * Desc attempts to become twi bus master and write a
+ * series of bytes to a device on the bus
+ * Input address: 7bit i2c device address
+ * data: pointer to byte array
+ * length: number of bytes in array
+ * wait: boolean indicating to wait for write or not
+ * Output 0 .. success
+ * 1 .. length to long for buffer
+ * 2 .. address send, NACK received
+ * 3 .. data send, NACK received
+ * 4 .. other twi error (lost bus arbitration, bus error, ..)
+ */
+uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
+{
+ uint8_t i;
+ twi_error = TWI_ERRROR_NO_ERROR;
+ twi_sendStop = sendStop;
+
+#ifdef __MSP430_HAS_USI__
+ /* Disable START condition interrupt */
+ USICTL1 &= ~USISTTIE;
+ /* I2C master mode */
+ USICTL0 |= USIMST;
+#endif
+#ifdef __MSP430_HAS_USCI__
+ UCB0CTL1 = UCSWRST; // Enable SW reset
+ UCB0CTL1 |= UCSSEL_2; // SMCLK
+ UCB0CTL0 |= (UCMST | UCMODE_3 | UCSYNC); // I2C Master, synchronous mode
+ UCB0CTL1 |= UCTR; // Configure in transmit mode
+ UCB0I2CSA = address; // Set Slave Address
+ UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
+ UCB0I2CIE |= (UCALIE|UCNACKIE|UCSTPIE); // Enable I2C interrupts
+ UC0IE |= UCB0TXIE; // Enable I2C interrupts
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+ UCB0CTLW0 = UCSWRST; // Enable SW reset
+ UCB0CTLW0 |= (UCMST | UCMODE_3 | UCSSEL__SMCLK | UCSYNC); // I2C Master, synchronous mode
+ UCB0CTLW0 |= UCTR; // Configure in transmit mode
+ UCB0I2CSA = address; // Set Slave Address
+ UCB0CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
+ UCB0IE |= (UCTXIE0|UCALIE|UCNACKIE|UCSTPIE); // Enable I2C interrupts
+#endif
+ if(length == 0) {
+ return 0;
+ }
+
+ /* Ensure data will fit into buffer */
+ if(length > TWI_BUFFER_LENGTH){
+ return TWI_ERROR_BUF_TO_LONG;
+ }
+
+
+ /* initialize buffer iteration vars */
+ twi_masterBufferIndex = 0;
+ twi_masterBufferLength = length;
+
+ for(i = 0; i < length; ++i){
+ twi_masterBuffer[i] = data[i];
+ }
+
+#ifdef __MSP430_HAS_USI__
+ /* build sla+w, slave device address + w bit */
+ twi_slarw = 0;
+ twi_slarw |= address << 1;
+
+ twi_state = TWI_SND_START;
+ /* This will trigger an interrupt kicking off the state machine in the isr */
+ USICTL1 |= USIIFG;
+#endif
+#ifdef __MSP430_HAS_USCI__
+ twi_state = TWI_MTX; // Master Transmit mode
+ UCB0CTL1 |= UCTXSTT; // I2C start condition
+#endif
+#ifdef __MSP430_HAS_EUSCI_B0__
+ twi_state = TWI_MTX; // Master Transmit mode
+ while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
+ UCB0CTLW0 |= UCTXSTT; // I2C start condition
+#endif
+
+ /* Wait for the transaction to complete */
+ while(twi_state != TWI_IDLE) {
+ __bis_SR_register(LPM0_bits);
+ }
+
+#ifdef __MSP430_HAS_USCI__
+ /* Ensure stop condition got sent before we exit. */
+ while (UCB0CTL1 & UCTXSTP);
+#endif
+
+ return twi_error;
+}
+
+/*
+ * Function twi_transmit
+ * Desc fills slave tx buffer with data
+ * must be called in slave tx event callback
+ * Input data: pointer to byte array
+ * length: number of bytes in array
+ * Output 1 length too long for buffer
+ * 2 not slave transmitter
+ * 0 ok
+ */
+uint8_t twi_transmit(const uint8_t* data, uint8_t length)
+{
+ uint8_t i;
+
+ twi_state = TWI_STX; // Slave transmit mode
+
+ // ensure data will fit into buffer
+ if(TWI_BUFFER_LENGTH < length){
+ return 1;
+ }
+ // set length and copy data into tx buffer
+ twi_txBufferLength = length;
+ for(i = 0; i < length; ++i){
+ twi_txBuffer[i] = data[i];
+ }
+
+ return 0;
+}
+
+/*
+ * Function twi_attachSlaveRxEvent
+ * Desc sets function called before a slave read operation
+ * Input function: callback function to use
+ * Output none
+ */
+void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) )
+{
+ twi_onSlaveReceive = function;
+}
+
+/*
+ * Function twi_attachSlaveTxEvent
+ * Desc sets function called before a slave write operation
+ * Input function: callback function to use
+ * Output none
+ */
+void twi_attachSlaveTxEvent( void (*function)(void) )
+{
+ twi_onSlaveTransmit = function;
+}
+
+void send_start()
+{
+#ifdef __MSP430_HAS_USI__
+ USISRL = 0x00;
+ USICTL0 |= USIGE+USIOE;
+ USICTL0 &= ~USIGE;
+ USISRL = twi_slarw;
+ USICNT = (USICNT & 0xE0) + 0x08;
+#endif
+}
+
+#ifdef __MSP430_HAS_USI__
+__attribute__((interrupt(USI_VECTOR)))
+void USI_ISR(void)
+{
+ if (!(USICTL0 & USIMST) && (USICTL1 & USISTTIFG)) {
+ twi_state = TWI_SL_START;
+ }
+
+ switch(twi_state){
+ /* Master transmit / receive */
+ case TWI_SND_START:
+ send_start();
+ twi_state = TWI_PREP_SLA_ADDR_ACK;
+ break;
+ case TWI_PREP_SLA_ADDR_ACK: // reveive (N)ACK
+ USICTL0 &= ~USIOE; // SDA = input
+ USICNT |= 0x01; // Bit counter=1
+ twi_state = TWI_MT_PROC_ADDR_ACK;
+ break;
+ case TWI_MT_PROC_ADDR_ACK:
+ if (USISRL & 0x01) {
+ twi_error = TWI_ERROR_ADDR_NACK;
+ USICTL0 |= USIOE;
+ USISRL = 0x00;
+ USICNT |= 0x01;
+ twi_state = TWI_EXIT;
+ break;
+ }
+
+ if(twi_slarw & 1)
+ goto mtre;
+ else
+ goto mtpd;
+
+ break;
+ /* Prepare to receive data (N)ACK */
+ case TWI_MT_PREP_DATA_ACK:
+ /* SDA = input */
+ USICTL0 &= ~USIOE;
+ /* Bit counter = 1 */
+ USICNT |= 0x01;
+ twi_state = TWI_MT_PROC_DATA_ACK;
+ break;
+ case TWI_MT_PROC_DATA_ACK:
+mtpd:
+ if (USISRL & 0x01) {
+ twi_error = TWI_ERROR_DATA_NACK;
+ USICTL0 |= USIOE;
+ USISRL = 0x00;
+ USICNT |= 0x01;
+ twi_state = TWI_EXIT;
+ break;
+ }
+
+ if(twi_masterBufferIndex == twi_masterBufferLength) {
+ USICTL0 |= USIOE;
+ USISRL = 0x00;
+ USICNT |= 0x01;
+ twi_state = TWI_EXIT;
+ break;
+ }
+
+ USICTL0 |= USIOE;
+ USISRL = twi_masterBuffer[twi_masterBufferIndex++];
+ USICNT |= 0x08;
+ twi_state = TWI_MT_PREP_DATA_ACK;
+ break;
+ // Master receiver
+mtre:
+ case TWI_MR_PREP_DATA_RECV:
+ /* SDA input */
+ USICTL0 &= ~USIOE;
+ /* bit counter = 8 */
+ USICNT |= 0x08;
+ twi_state = TWI_MR_PROC_DATA_RECV;
+ break;
+ case TWI_MR_PROC_DATA_RECV:
+ /* SDA output */
+ USICTL0 |= USIOE;
+
+ twi_masterBuffer[twi_masterBufferIndex++] = USISRL;
+ if(twi_masterBufferIndex > twi_masterBufferLength ) {
+ USISRL = 0xFF; // that was the last byte send NACK
+ twi_state = TWI_MR_PREP_STOP;
+ } else {
+ USISRL = 0x00; // keep on receiving and send ACK
+ twi_state = TWI_MR_PREP_DATA_RECV;
+ }
+
+ USICNT |= 0x01;
+ break;
+ case TWI_MR_PREP_STOP:
+ USICTL0 |= USIOE;
+ USISRL = 0x00;
+ USICNT |= 0x01;
+ twi_state = TWI_EXIT;
+ break;
+ /* All */
+ case TWI_EXIT:
+ /* Load FF into output shift register */
+ USISRL = 0x0FF;
+ /* Output latch transparant. MSB of USISR to the SDO pin. */
+ USICTL0 |= USIGE;
+ /* Latch disabled and make SDA input */
+ USICTL0 &= ~(USIGE+USIOE);
+ twi_state = TWI_IDLE;
+ break;
+ case TWI_IDLE:
+ /* Nothing to do. Fall thru and clear interrupt flag. */
+ default:
+ break;
+ }
+
+ /* Clear counter interrupt */
+ USICTL1 &= ~USIIFG;
+
+}
+#endif /* __MSP430_HAS_USI__ */
+
+#ifdef __MSP430_HAS_USCI__
+void i2c_txrx_isr(void) // RX/TX Service
+{
+ /* USCI I2C mode. USCI_B0 receive interrupt flag.
+ * UCB0RXIFG is set when UCB0RXBUF has received a complete character. */
+ if (UC0IFG & UCB0RXIFG){
+ /* Master receive mode. */
+ if (twi_state == TWI_MRX) {
+ twi_masterBuffer[twi_masterBufferIndex++] = UCB0RXBUF;
+ if(twi_masterBufferIndex == twi_masterBufferLength )
+ /* Only one byte left. Generate STOP condition.
+ * In master mode a STOP is preceded by a NACK */
+ UCB0CTL1 |= UCTXSTP;
+ if(twi_masterBufferIndex > twi_masterBufferLength ) {
+ /* All bytes received. We are idle*/
+ __bic_SR_register(LPM0_bits);
+ twi_state = TWI_IDLE;
+ }
+ /* Slave receive mode. (twi_state = TWI_SRX) */
+ } else {
+ // if there is still room in the rx buffer
+ if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
+ // put byte in buffer and ack
+ twi_rxBuffer[twi_rxBufferIndex++] = UCB0RXBUF;
+ }else{
+ // otherwise nack
+ UCB0CTL1 |= UCTXNACK; // Generate NACK condition
+ }
+ }
+ }
+ /* USCI I2C mode. USCI_B0 transmit interrupt flag.
+ * UCB0TXIFG is set when UCB0TXBUF is empty.*/
+ if (UC0IFG & UCB0TXIFG){
+ /* Master transmit mode */
+ if (twi_state == TWI_MTX) {
+ // if there is data to send, send it, otherwise stop
+ if(twi_masterBufferIndex < twi_masterBufferLength){
+ // Copy data to output register and ack.
+ UCB0TXBUF = twi_masterBuffer[twi_masterBufferIndex++];
+ }else{
+ if (twi_sendStop) {
+ /* All done. Generate STOP condition and IDLE */
+ UCB0CTL1 |= UCTXSTP;
+ twi_state = TWI_IDLE;
+ __bic_SR_register(LPM0_bits);
+ } else {
+ twi_inRepStart = true; // we're gonna send the START
+ // don't enable the interrupt. We'll generate the start, but we
+ // avoid handling the interrupt until we're in the next transaction,
+ // at the point where we would normally issue the start.
+ UCB0CTL1 |= UCTXSTT;
+ twi_state = TWI_IDLE;
+ __bic_SR_register(LPM0_bits);
+ }
+ }
+ /* Slave transmit mode (twi_state = TWI_STX) */
+ } else {
+ // copy data to output register
+ UCB0TXBUF = twi_txBuffer[twi_txBufferIndex++];
+ // if there is more to send, ack, otherwise nack
+ if(twi_txBufferIndex < twi_txBufferLength){
+ }else{
+ UCB0CTL1 |= UCTXNACK; // Generate NACK condition
+ }
+ }
+ }
+}
+
+void i2c_state_isr(void) // I2C Service
+{
+ /* Arbitration lost interrupt flag */
+ if (UCB0STAT & UCALIFG) {
+ UCB0STAT &= ~UCALIFG;
+ /* TODO: Handle bus arbitration lost */
+ }
+ /* Not-acknowledge received interrupt flag.
+ * UCNACKIFG is automatically cleared when a START condition is received.*/
+ if (UCB0STAT & UCNACKIFG) {
+ UCB0STAT &= ~UCNACKIFG;
+ UCB0CTL1 |= UCTXSTP;
+ twi_state = TWI_IDLE;
+ /* TODO: This can just as well be an address NACK.
+ * Figure out a way to distinguish between ANACK and DNACK */
+ twi_error = TWI_ERROR_DATA_NACK;
+ __bic_SR_register(LPM0_bits);
+ }
+ /* Start condition interrupt flag.
+ * UCSTTIFG is automatically cleared if a STOP condition is received. */
+ if (UCB0STAT & UCSTTIFG) {
+ UCB0STAT &= ~UCSTTIFG;
+ /* UCTR is automagically set by the USCI module upon a START condition. */
+ if (UCB0CTL1 & UCTR) {
+ /* Slave TX mode. */
+ twi_state = TWI_STX;
+ /* Ready the tx buffer index for iteration. */
+ twi_txBufferIndex = 0;
+ /* Set tx buffer length to be zero, to verify if user changes it. */
+ twi_txBufferLength = 0;
+ /* Request for txBuffer to be filled and length to be set. */
+ /* note: user must call twi_transmit(bytes, length) to do this */
+ twi_onSlaveTransmit();
+ /* If they didn't change buffer & length, initialize it
+ * TODO: Is this right? Shouldn't we reply with a NACK if there is no data to send? */
+ if (0 == twi_txBufferLength) {
+ twi_txBufferLength = 1;
+ twi_txBuffer[0] = 0x00;
+ }
+ } else {
+ /* Slave receive mode. */
+ twi_state = TWI_SRX;
+ /* Indicate that rx buffer can be overwritten and ACK */
+ twi_rxBufferIndex = 0;
+ }
+ }
+ /* Stop condition interrupt flag.
+ * UCSTPIFG is automatically cleared when a START condition is received. */
+ if (UCB0STAT & UCSTPIFG) {
+ UCB0STAT &= ~UCSTPIFG;
+ if (twi_state == TWI_SRX) {
+ /* Callback to user defined callback */
+ twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
+ }
+ twi_state = TWI_IDLE;
+ }
+}
+#endif
+
+#ifdef __MSP430_HAS_EUSCI_B0__
+__attribute__((interrupt(USCI_B0_VECTOR)))
+void USCI_B0_ISR(void)
+{
+// switch(twi_state){
+ switch(UCB0IV){
+ case USCI_NONE: // No Interrupt pending
+ break;
+ case USCI_I2C_UCALIFG: // USCI I2C Mode: UCALIFG
+ // enter slave transmitter mode
+ twi_state = TWI_STX;
+ // ready the tx buffer index for iteration
+ twi_txBufferIndex = 0;
+ // set tx buffer length to be zero, to verify if user changes it
+ twi_txBufferLength = 0;
+ // request for txBuffer to be filled and length to be set
+ // note: user must call twi_transmit(bytes, length) to do this
+ twi_onSlaveTransmit();
+ // if they didn't change buffer & length, initialize it
+ if(0 == twi_txBufferLength){
+ twi_txBufferLength = 1;
+ twi_txBuffer[0] = 0x00;
+ }
+ // transmit first byte from buffer, fall
+ // copy data to output register
+ UCB0TXBUF = twi_txBuffer[twi_txBufferIndex++];
+ // if there is more to send, ack, otherwise nack
+ if(twi_txBufferIndex < twi_txBufferLength){
+ //twi_reply(1);
+ }else{
+ UCB0CTLW0 |= UCTXNACK; // Generate NACK condition
+ }
+ // leave slave receiver state
+ twi_state = TWI_IDLE;
+
+ break;
+ case USCI_I2C_UCNACKIFG: // USCI I2C Mode: UCNACKIFG
+ // leave slave receiver state
+ twi_state = TWI_IDLE;
+ twi_error = TWI_ERROR_DATA_NACK;
+ __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
+ break;
+ case USCI_I2C_UCSTTIFG: // USCI I2C Mode: UCSTTIFG
+ UCB0IFG &= ~UCSTTIFG;
+ if (twi_state == TWI_IDLE){
+ if (UCB0CTLW0 & UCTR){
+ twi_state = TWI_STX; // Slave Transmit mode
+ // ready the tx buffer index for iteration
+ twi_txBufferIndex = 0;
+ // set tx buffer length to be zero, to verify if user changes it
+ twi_txBufferLength = 0;
+ // request for txBuffer to be filled and length to be set
+ // note: user must call twi_transmit(bytes, length) to do this
+ twi_onSlaveTransmit();
+ // if they didn't change buffer & length, initialize it
+ if(0 == twi_txBufferLength){
+ twi_txBufferLength = 1;
+ twi_txBuffer[0] = 0x00;
+ }
+ }else{
+ twi_state = TWI_SRX; // Slave receive mode
+ // indicate that rx buffer can be overwritten and ack
+ twi_rxBufferIndex = 0;
+ }
+ }
+ break;
+ case USCI_I2C_UCSTPIFG: // USCI I2C Mode: UCSTPIFG
+ UCB0IFG &= ~UCSTPIFG;
+ if (twi_state == TWI_SRX){
+ // callback to user defined callback
+ twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
+ }
+ twi_state = TWI_IDLE; // IDLE mode
+ /* Work around for:
+ * If the master does a read and then a write the START interrupt occurs
+ * but the RX interrupt never fires. Clearing bit 4 and 5 of UCB0CTLW0 solves this.
+ * bit 4 and 5 are however marked as reserved in the datasheet.
+ */
+ UCB0CTLW0 &= ~0x18;
+
+ __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
+ break;
+ case USCI_I2C_UCRXIFG3: // USCI I2C Mode: UCRXIFG3
+ break;
+ case USCI_I2C_UCTXIFG3: // USCI I2C Mode: UCTXIFG3
+ break;
+ case USCI_I2C_UCRXIFG2: // USCI I2C Mode: UCRXIFG2
+ break;
+ case USCI_I2C_UCTXIFG2: // USCI I2C Mode: UCTXIFG2
+ break;
+ case USCI_I2C_UCRXIFG1: // USCI I2C Mode: UCRXIFG1
+ break;
+ case USCI_I2C_UCTXIFG1: // USCI I2C Mode: UCTXIFG1
+ break;
+ case USCI_I2C_UCRXIFG0: // USCI I2C Mode: UCRXIFG0
+ UCB0IFG &= ~UCRXIFG; // Clear USCI_B0 TX int flag
+ if (twi_state == TWI_MRX) { // Master receive mode
+ twi_masterBuffer[twi_masterBufferIndex++] = UCB0RXBUF; // Get RX data
+ if(twi_masterBufferIndex == twi_masterBufferLength )
+ UCB0CTLW0 |= UCTXSTP; // Generate I2C stop condition
+ if(twi_masterBufferIndex > twi_masterBufferLength ) {
+ twi_state = TWI_IDLE; //Idle
+ } else {
+ }
+ } else {
+ // if there is still room in the rx buffer
+ if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
+ // put byte in buffer and ack
+ twi_rxBuffer[twi_rxBufferIndex++] = UCB0RXBUF;
+ }else{
+ // otherwise nack
+ UCB0CTLW0 |= UCTXNACK; // Generate NACK condition
+ }
+ }
+ break;
+ case USCI_I2C_UCTXIFG0: // USCI I2C Mode: UCTXIFG0
+ UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
+ if (twi_state == TWI_MTX) { // Master receive mode
+ // if there is data to send, send it, otherwise stop
+ if(twi_masterBufferIndex < twi_masterBufferLength){
+ // copy data to output register and ack
+ UCB0TXBUF = twi_masterBuffer[twi_masterBufferIndex++]; // Transmit data at address PTxData
+ }else{
+ if (twi_sendStop)
+ UCB0CTLW0 |= UCTXSTP; // Generate I2C stop condition
+ else {
+ twi_inRepStart = true; // we're gonna send the START
+ // don't enable the interrupt. We'll generate the start, but we
+ // avoid handling the interrupt until we're in the next transaction,
+ // at the point where we would normally issue the start.
+ UCB0CTLW0 |= UCTXSTT;
+ twi_state = TWI_IDLE;
+ }
+ }
+ } else {
+ // copy data to output register
+ UCB0TXBUF = twi_txBuffer[twi_txBufferIndex++];
+ // if there is more to send, ack, otherwise nack
+ if(twi_txBufferIndex < twi_txBufferLength){
+ }else{
+ UCB0CTLW0 |= UCTXNACK; // Generate NACK condition
+ }
+ }
+ break;
+ case USCI_I2C_UCBCNTIFG: // USCI I2C Mode: UCBCNTIFG
+ break;
+ case USCI_I2C_UCCLTOIFG: // USCI I2C Mode: UCCLTOIFG/
+ break;
+ case USCI_I2C_UCBIT9IFG: // USCI I2C Mode: UCBIT9IFG
+ break;
+ }
+}
+#endif
+
diff --git a/lib/msp430/twi.h b/lib/msp430/twi.h
new file mode 100644
index 0000000..ea383b6
--- /dev/null
+++ b/lib/msp430/twi.h
@@ -0,0 +1,104 @@
+/*
+ ************************************************************************
+ * twi.h
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ twi.h - TWI/I2C library for Wiring & Arduino
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef twi_h
+#define twi_h
+
+#include <msp430.h>
+
+#if !defined (__MSP430_HAS_USI__) && !defined (__MSP430_HAS_USCI__) && !defined (__MSP430_HAS_EUSCI_B0__)
+#ifndef __MSP430_HAS_USI__
+#error "********** USI not available"
+#endif
+
+#if !defined (__MSP430_HAS_USCI__) && !defined (__MSP430_HAS_EUSCI_B0__)
+#error "********** USCI not available"
+#endif
+#endif
+
+
+#include <inttypes.h>
+
+#ifndef TWI_FREQ
+#define TWI_FREQ 100000L
+#endif
+
+#ifndef TWI_BUFFER_LENGTH
+#define TWI_BUFFER_LENGTH 16
+#endif
+
+
+#define TWI_READY 0
+#define TWI_MRX 1
+#define TWI_MTX 2
+#define TWI_SRX 3
+#define TWI_STX 4
+
+
+#define TWI_SND_START 0
+#define TWI_PREP_SLA_ADDR_ACK 1
+#define TWI_MT_PROC_ADDR_ACK 2
+#define TWI_MT_PREP_DATA_ACK 3
+#define TWI_MT_PROC_DATA_ACK 4
+#define TWI_MR_PREP_DATA_RECV 5
+#define TWI_MR_PROC_DATA_RECV 6
+#define TWI_MR_PREP_STOP 7
+
+#define TWI_SL_START 8
+#define TWI_SL_PROC_ADDR 9
+#define TWI_SL_SEND_BYTE 10
+#define TWI_SL_PREP_DATA_ACK 11
+#define TWI_SL_PROC_DATA_ACK 12
+#define TWI_SL_RECV_BYTE 13
+#define TWI_SL_PROC_BYTE 14
+#define TWI_SL_RESET 15
+#define TWI_EXIT 16
+#define TWI_IDLE 17
+
+
+#define TWI_ERRROR_NO_ERROR 0
+#define TWI_ERROR_BUF_TO_LONG 1
+#define TWI_ERROR_ADDR_NACK 2
+#define TWI_ERROR_DATA_NACK 3
+#define TWI_ERROR_OTHER 4
+
+
+
+void twi_init(void);
+void twi_setAddress(uint8_t);
+uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
+uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
+uint8_t twi_transmit(const uint8_t*, uint8_t);
+void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
+void twi_attachSlaveTxEvent( void (*)(void) );
+void twi_reply(uint8_t);
+void twi_stop(void);
+void twi_releaseBus(void);
+
+#endif
+
diff --git a/lib/msp430/usci_isr_handler.c b/lib/msp430/usci_isr_handler.c
new file mode 100644
index 0000000..a112ce7
--- /dev/null
+++ b/lib/msp430/usci_isr_handler.c
@@ -0,0 +1,59 @@
+#include "Energia.h"
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+#include "usci_isr_handler.h"
+
+/* This dummy function ensures that, when called from any module that
+ * is interested in having the USCIAB0TX_VECTOR and USCIAB0TX_VECTOR
+ * installed, the linker won't strip the vectors.*/
+void usci_isr_install(){}
+
+
+
+#if defined(__MSP430_HAS_EUSCI_A0__)
+__attribute__((interrupt(USCI_A0_VECTOR)))
+void USCIA0_ISR(void)
+{
+ switch ( UCA0IV )
+ {
+ case USCI_UART_UCRXIFG: uart_rx_isr(); break;
+ case USCI_UART_UCTXIFG: uart_tx_isr(); break;
+ }
+}
+
+#else // #if defined(__MSP430_HAS_EUSCI_A0__)
+/* USCI_Ax and USCI_Bx share the same TX interrupt vector.
+ * UART:
+ * USCIAB0TX_VECTOR services the UCA0TXIFG set in UC0IFG.
+ * USCIAB0RX_VECTOR services the UCA0RXIFG set in UC0IFG.
+ * I2C:
+ * USCIAB0TX_VECTOR services both UCB0TXIFG and UCB0RXIFG
+ * set in UC0IFG.
+ * USCIAB0RX_VECTOR services the state change interrupts
+ * UCSTTIFG, UCSTPIFG, UCIFG, UCALIFG set in UCB0STAT.*/
+
+__attribute__((interrupt(USCIAB0TX_VECTOR)))
+void USCIAB0TX_ISR(void)
+{
+ /* USCI_A0 UART interrupt? */
+ if (UC0IFG & UCA0TXIFG)
+ uart_tx_isr();
+
+ /* USCI_B0 I2C TX RX interrupt. */
+ if ((UC0IFG & (UCB0TXIFG | UCB0RXIFG)) != 0)
+ i2c_txrx_isr();
+
+}
+
+__attribute__((interrupt(USCIAB0RX_VECTOR)))
+void USCIAB0RX_ISR(void)
+{
+ /* USCI_A0 UART interrupt? */
+ if (UC0IFG & UCA0RXIFG)
+ uart_rx_isr();
+
+ /* USCI_B0 I2C state change interrupt. */
+ if ((UCB0STAT & (UCALIFG | UCNACKIFG | UCSTTIFG | UCSTPIFG)) != 0)
+ i2c_state_isr();
+}
+#endif // #if defined(__MSP430_HAS_EUSCI_A0__)
+#endif // if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
diff --git a/lib/msp430/usci_isr_handler.h b/lib/msp430/usci_isr_handler.h
new file mode 100644
index 0000000..19f427d
--- /dev/null
+++ b/lib/msp430/usci_isr_handler.h
@@ -0,0 +1,18 @@
+#ifndef usci_isr_handler_h
+#define usci_isr_handler_h
+
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_EUSCI_A0__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void uart_tx_isr(void);
+void uart_rx_isr(void);
+void i2c_txrx_isr(void);
+void i2c_state_isr(void);
+void usci_isr_install(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MSP430_HAS_USCI__ */
+#endif /* usci_isr_handler_h */
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);
+}
diff --git a/lib/msp430/wiring_analog.c b/lib/msp430/wiring_analog.c
new file mode 100644
index 0000000..1451ad7
--- /dev/null
+++ b/lib/msp430/wiring_analog.c
@@ -0,0 +1,297 @@
+/*
+ ************************************************************************
+ * wiring_analog.c
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ wiring_analog.c - analog input and output
+ 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 "wiring_private.h"
+#include "pins_energia.h"
+
+#if defined(__MSP430_HAS_ADC10__) && !defined(ADC10ENC)
+#define ADC10ENC ENC
+#endif
+#if defined(__MSP430_HAS_ADC10__) && !defined(ADC10MEM0)
+#define ADC10MEM0 ADC10MEM
+#endif
+#if defined(__MSP430_HAS_ADC10_B__)
+#define REFV_MASK 0x70
+#define REF_MASK 0x31;
+#endif
+
+#if defined(__MSP430_HAS_ADC10__) || defined(__MSP430_HAS_ADC10_B__)
+uint16_t analog_reference = DEFAULT, analog_period = F_CPU/490, analog_div = 0, analog_res=255; // devide clock with 0, 2, 4, 8
+#endif
+
+void analogReference(uint16_t mode)
+{
+ // can't actually set the register here because the default setting
+ // will connect AVCC and the AREF pin, which would cause a short if
+ // there's something connected to AREF.
+ analog_reference = mode;
+}
+
+//TODO: Can be a lot more efficiant.
+// - lower clock rated / input devider to conserve Energia.
+// - pin configuration logic.
+
+// Note set frequency before sending analog value
+// Lowest fequency is defined by clock frequency F_CPU, and max counter value 2^16-1
+// fmin = F_CPU / 2^16
+void analogFrequency(uint32_t freq)
+{
+ if ( freq <= F_CPU/(4*65334L) ) { analog_div = ID_3; freq *=8; }
+ else if ( freq <= F_CPU/(2*65334L) ) { analog_div = ID_2; freq *=4; }
+ else if ( freq <= F_CPU/(4*65334L) ) { analog_div = ID_1; freq *=2; }
+ analog_period = F_CPU/freq;
+}
+
+// Set the resulution (nr of counts for 100%), default = 255, large values may not work at all frequencies
+void analogResolution(uint16_t res)
+{
+ analog_res = res;
+}
+
+//Arduino specifies ~490 Hz for analog out PWM so we follow suit.
+#define PWM_PERIOD analog_period // F_CPU/490
+#define PWM_DUTY(x) ( (unsigned long)x*PWM_PERIOD / (unsigned long)analog_res )
+void analogWrite(uint8_t pin, int val)
+{
+ pinMode(pin, OUTPUT); // pin as output
+
+ if (val == 0)
+ {
+ digitalWrite(pin, LOW); // set pin to LOW when duty cycle is 0
+ // digitalWrite will take care of invalid pins
+ }
+ else if (val == analog_res)
+ {
+ digitalWrite(pin, HIGH); // set pin HIGH when duty cycle is 255
+ // digitalWrite will take care of invalid pins
+ }
+ else
+ {
+
+ uint8_t bit = digitalPinToBitMask(pin); // get pin bit
+ uint8_t port = digitalPinToPort(pin); // get pin port
+ volatile uint8_t *sel;
+
+ if (port == NOT_A_PORT) return; // pin on timer?
+
+ sel = portSelRegister(port); // get the port function select register address
+ *sel |= bit; // set bit in pin function select register
+
+ switch(digitalPinToTimer(pin)) { // which timer and CCR?
+ //case: T0A0 // CCR0 used as period register
+ case T0A1: // TimerA0 / CCR1
+ TA0CCR0 = PWM_PERIOD; // PWM Period
+ TA0CCTL1 = OUTMOD_7; // reset/set
+ TA0CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TA0CTL = TASSEL_2 + MC_1 + analog_div; // SMCLK, up mode
+ break;
+#if defined(__MSP430_HAS_TA3__) || defined(__MSP430_HAS_T0A3__)
+ case T0A2: // TimerA0 / CCR2
+ TA0CCR0 = PWM_PERIOD; // PWM Period
+ TA0CCTL2 = OUTMOD_7; // reset/set
+ TA0CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TA0CTL = TASSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+#if defined(__MSP430_HAS_T1A3__)
+ //case: T1A0 // CCR0 used as period register
+ case T1A1: // TimerA1 / CCR1
+ TA1CCR0 = PWM_PERIOD; // PWM Period
+ TA1CCTL1 = OUTMOD_7; // reset/set
+ TA1CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TA1CTL = TASSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+ case T1A2: // TimerA1 / CCR2
+ TA1CCR0 = PWM_PERIOD; // PWM Period
+ TA1CCTL2 = OUTMOD_7; // reset/set
+ TA1CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TA1CTL = TASSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+#if defined(__MSP430_HAS_T2A3__)
+ //case: T2A0 // CCR0 used as period register
+ case T2A1: // TimerA2 / CCR1
+ TA2CCR0 = PWM_PERIOD; // PWM Period
+ TA2CCTL1 = OUTMOD_7; // reset/set
+ TA2CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TA2CTL = TASSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+ case T2A2: // TimerA2 / CCR2
+ TA2CCR0 = PWM_PERIOD; // PWM Period
+ TA2CCTL2 = OUTMOD_7; // reset/set
+ TA2CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TA2CTL = TASSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+#if defined(__MSP430_HAS_T0B3__)
+ //case: T0B0 // CCR0 used as period register
+ case T0B1: // TimerB0 / CCR1
+ TB0CCR0 = PWM_PERIOD; // PWM Period
+ TB0CCTL1 = OUTMOD_7; // reset/set
+ TB0CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TB0CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+ case T0B2: // TimerB0 / CCR1
+ TB0CCR0 = PWM_PERIOD; // PWM Period
+ TB0CCTL2 = OUTMOD_7; // reset/set
+ TB0CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TB0CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+#if defined(__MSP430_HAS_T1B3__)
+ //case: T1B0 // CCR0 used as period register
+ case T1B1: // TimerB0 / CCR1
+ TB1CCR0 = PWM_PERIOD; // PWM Period
+ TB1CCTL1 = OUTMOD_7; // reset/set
+ TB1CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TB1CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+ case T1B2: // TimerB0 / CCR1
+ TB1CCR0 = PWM_PERIOD; // PWM Period
+ TB1CCTL2 = OUTMOD_7; // reset/set
+ TB1CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TB1CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+#if defined(__MSP430_HAS_T2B3__)
+ //case: T1B0 // CCR0 used as period register
+ case T2B1: // TimerB0 / CCR1
+ TB2CCR0 = PWM_PERIOD; // PWM Period
+ TB2CCTL1 = OUTMOD_7; // reset/set
+ TB2CCR1 = PWM_DUTY(val); // PWM duty cycle
+ TB2CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+ case T2B2: // TimerB0 / CCR1
+ TB2CCR0 = PWM_PERIOD; // PWM Period
+ TB2CCTL2 = OUTMOD_7; // reset/set
+ TB2CCR2 = PWM_DUTY(val); // PWM duty cycle
+ TB2CTL = TBSSEL_2 + MC_1+ analog_div; // SMCLK, up mode
+ break;
+#endif
+
+ case NOT_ON_TIMER: // not on a timer output pin
+ default: // or TxA0 pin
+ if (val <= (analog_res >> 1)) {
+ digitalWrite(pin, LOW); //
+ } else {
+ digitalWrite(pin, HIGH);
+ }
+ }
+ }
+}
+
+uint16_t analogRead(uint8_t pin)
+{
+// make sure we have an ADC
+#if defined(__MSP430_HAS_ADC10__) || defined(__MSP430_HAS_ADC10_B__)
+ // 0000 A0
+ // 0001 A1
+ // 0010 A2
+ // 0011 A3
+ // 0100 A4
+ // 0101 A5
+ // 0110 A6
+ // 0111 A7
+ // 1010 Internal temperature sensor
+
+ //TODO: Only int. temp. sensor requires Tsample > 30us.
+ // The below ADC configuration applies this rule to all channels right now.
+ // ADC10CLK = 5MHz / 5 = 1Mhz
+ // Tsample = S&H / ADC10CLK = 64 / 1 MHz = 64 us
+ // Tconvert = 13 / ADC10CLK = 13 / 1 MHz = 13 us
+ // Total time per sample = Tconvert + Tsample = 64 + 13 = 67 us = ~15k samples / sec
+
+ ADC10CTL0 &= ~ADC10ENC; // disable ADC
+ ADC10CTL1 = ADC10SSEL_0 | ADC10DIV_5; // ADC10OSC as ADC10CLK (~5MHz) / 5
+#if defined(__MSP430_HAS_ADC10__)
+ ADC10CTL0 = analog_reference | // set analog reference
+ ADC10ON | ADC10SHT_3 | ADC10IE; // turn ADC ON; sample + hold @ 64 × ADC10CLKs; Enable interrupts
+ ADC10CTL1 |= (pin << 12); // select channel
+ ADC10AE0 = (1 << pin); // Disable input/output buffer on pin
+#endif
+#if defined(__MSP430_HAS_ADC10_B__)
+ while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
+ REFCTL0 |= analog_reference & REF_MASK; // Set reference using masking off the SREF bits. See Energia.h.
+ ADC10MCTL0 = pin | (analog_reference & REFV_MASK); // set channel and reference
+ ADC10CTL0 = ADC10ON | ADC10SHT_4; // turn ADC ON; sample + hold @ 64 × ADC10CLKs
+ ADC10CTL1 |= ADC10SHP; // ADCCLK = MODOSC; sampling timer
+ ADC10CTL2 |= ADC10RES; // 10-bit resolution
+ ADC10IFG = 0; // Clear Flags
+ ADC10IE |= ADC10IE0; // Enable interrupts
+#endif
+ __delay_cycles(128); // Delay to allow Ref to settle
+ ADC10CTL0 |= ADC10ENC | ADC10SC; // enable ADC and start conversion
+ while (ADC10CTL1 & ADC10BUSY) { // sleep and wait for completion
+ __bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled
+ }
+
+#if defined(__MSP430_HAS_ADC10__)
+ /* POWER: Turn ADC and reference voltage off to conserve power */
+ ADC10CTL0 &= ~(ADC10ON | REFON);
+#endif
+
+#if defined(__MSP430_HAS_ADC10_B__)
+ /* POWER: Turn ADC and reference voltage off to conserve power */
+ ADC10CTL0 &= ~(ADC10ON);
+ REFCTL0 &= ~REFON;
+#endif
+ return ADC10MEM0; // return sampled value after returning to active mode in ADC10_ISR
+#else
+ // no ADC
+ return 0;
+#endif
+}
+
+__attribute__((interrupt(ADC10_VECTOR)))
+void ADC10_ISR(void)
+{
+#if defined(__MSP430_HAS_ADC10)
+ __bic_SR_register_on_exit(CPUOFF); // return to active mode
+#endif
+
+#if defined(__MSP430_HAS_ADC10_B__)
+
+ switch(ADC10IV,12) {
+ case 0: break; // No interrupt
+ case 2: break; // conversion result overflow
+ case 4: break; // conversion time overflow
+ case 6: break; // ADC10HI
+ case 8: break; // ADC10LO
+ case 10: break; // ADC10IN
+ case 12:
+ __bic_SR_register_on_exit(CPUOFF); // return to active mode
+ break; // Clear CPUOFF bit from 0(SR)
+ default: break;
+ }
+
+ ADC10IFG = 0; // Clear Flags
+#endif
+}
diff --git a/lib/msp430/wiring_digital.c b/lib/msp430/wiring_digital.c
new file mode 100644
index 0000000..cf851b3
--- /dev/null
+++ b/lib/msp430/wiring_digital.c
@@ -0,0 +1,181 @@
+/*
+ ************************************************************************
+ * HardwareSerial.cpp
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ wiring_digital.c - digital input and output functions
+ 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
+*/
+
+#define ARDUINO_MAIN
+#include "wiring_private.h"
+#include "pins_energia.h"
+
+void pinMode(uint8_t pin, uint8_t mode)
+{
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+
+ volatile uint8_t *dir;
+ volatile uint8_t *ren;
+ volatile uint8_t *out;
+
+ if (port == NOT_A_PORT) return;
+
+ dir = portDirRegister(port);
+ ren = portRenRegister(port);
+ out = portOutputRegister(port);
+
+ if (mode == INPUT) {
+ *dir &= ~bit;
+ } else if (mode == INPUT_PULLUP) {
+ *dir &= ~bit;
+ *out |= bit;
+ *ren |= bit;
+ } else if (mode == INPUT_PULLDOWN) {
+ *dir &= ~bit;
+ *out &= ~bit;
+ *ren |= bit;
+ } else {
+ *dir |= bit;
+ }
+}
+
+void pinMode_int(uint8_t pin, uint8_t mode)
+{
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+
+ volatile uint8_t *dir;
+ volatile uint8_t *ren;
+ volatile uint8_t *out;
+ volatile uint8_t *sel;
+
+ if (port == NOT_A_PORT) return;
+
+ dir = portDirRegister(port);
+ ren = portRenRegister(port);
+ out = portOutputRegister(port);
+
+ if (mode & OUTPUT) {
+ *dir |= bit;
+ } else {
+ *dir &= ~bit;
+ if (mode & INPUT_PULLUP) {
+ *out |= bit;
+ *ren |= bit;
+ } else if (mode & INPUT_PULLDOWN) {
+ *out &= ~bit;
+ *ren |= bit;
+ }
+ }
+
+ #if (defined(P1SEL_) || defined(P1SEL))
+ sel = portSel0Register(port); /* get the port function select register address */
+ if (mode & PORT_SELECTION0) {
+ *sel |= bit;
+ } else {
+ *sel &= ~bit;
+ }
+ #if (defined(P1SEL2_) || defined(P1SEL2))
+ sel = portSel2Register(port); /* get the port function select register address */
+ if (mode & PORT_SELECTION1) {
+ *sel |= bit;
+ } else {
+ *sel &= ~bit;
+ }
+ #endif
+ #endif
+
+ #if (defined(P1SEL0_) || defined(P1SEL0))
+ sel = portSel0Register(port); /* get the port function select register address */
+ if (mode & PORT_SELECTION0) {
+ *sel |= bit;
+ } else {
+ *sel &= ~bit;
+ }
+ #if (defined(P1SEL1_) || defined(P1SEL1))
+ sel = portSel1Register(port); /* get the port function select register address */
+ if (mode & PORT_SELECTION1) {
+ *sel |= bit;
+ } else {
+ *sel &= ~bit;
+ }
+ #endif
+ #endif
+
+}
+
+int digitalRead(uint8_t pin)
+{
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+
+ if (port == NOT_A_PORT) return LOW;
+
+ if (*portInputRegister(port) & bit) return HIGH;
+ return LOW;
+}
+
+void digitalWrite(uint8_t pin, uint8_t val)
+{
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ volatile uint8_t *out;
+ volatile uint8_t *sel;
+
+ if (port == NOT_A_PORT) return;
+
+ /*
+ * Clear bit in PxSEL register to select GPIO function. Other functions like analogWrite(...)
+ * will set this bit so need to clear it.
+ */
+ #if (defined(P1SEL_) || defined(P1SEL))
+ sel = portSel0Register(port); /* get the port function select register address */
+ *sel &= ~bit; /* clear bit in pin function select register */
+ #if (defined(P1SEL2_) || defined(P1SEL2))
+ sel = portSel2Register(port); /* get the port function select register address */
+ *sel &= ~bit; /* clear bit in pin function select register */
+ #endif
+ #endif
+
+ #if (defined(P1SEL0_) || defined(P1SEL0))
+ sel = portSel0Register(port); /* get the port function select register address */
+ *sel &= ~bit; /* clear bit in pin function select register */
+ #if (defined(P1SEL1_) || defined(P1SEL1))
+ sel = portSel1Register(port); /* get the port function select register address */
+ *sel &= ~bit; /* clear bit in pin function select register */
+ #endif
+ #endif
+
+
+ out = portOutputRegister(port);
+
+ if (val == LOW) {
+ *out &= ~bit;
+ } else {
+ *out |= bit;
+ }
+}
diff --git a/lib/msp430/wiring_private.h b/lib/msp430/wiring_private.h
new file mode 100644
index 0000000..9ed8c6f
--- /dev/null
+++ b/lib/msp430/wiring_private.h
@@ -0,0 +1,60 @@
+/*
+ ************************************************************************
+ * wiring_private.h
+ *
+ * Arduino core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ wiring_private.h - Internal header file.
+ 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
+
+ $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
+*/
+
+#ifndef WiringPrivate_h
+#define WiringPrivate_h
+
+#include "Energia.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// TODO: This is a hack and needs cleaning up. Not all pins are available on the board
+//.Change this to a more intelligent number of interrupt selection
+
+#if defined(__MSP430_HAS_PORT1_R__)
+#define EXTERNAL_NUM_INTERRUPTS 8
+#elif defined(__MSP430_HAS_PORT2_R__)
+#define EXTERNAL_NUM_INTERRUPTS 16
+#else
+#define EXTERNAL_NUM_INTERRUPTS 8
+#endif
+
+typedef void (*voidFuncPtr)(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/lib/msp430/wiring_pulse.c b/lib/msp430/wiring_pulse.c
new file mode 100755
index 0000000..6375717
--- /dev/null
+++ b/lib/msp430/wiring_pulse.c
@@ -0,0 +1,76 @@
+/*
+ ************************************************************************
+ * wiring_pulse.c
+ *
+ * Energia core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ wiring_pulse.c - pulseIn() function
+ 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 "wiring_private.h"
+#include "pins_energia.h"
+
+/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
+ * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
+ * to 3 minutes in length, but must be called at least a few dozen microseconds
+ * before the start of the pulse. */
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
+{
+ // cache the port and bit of the pin in order to speed up the
+ // pulse width measuring loop and achieve finer resolution. calling
+ // digitalRead() instead yields much coarser resolution.
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ uint8_t stateMask = (state ? bit : 0);
+ unsigned long width = 0; // keep initialization out of time critical area
+
+ // convert the timeout from microseconds to a number of times through
+ // the initial loop; it takes 11 clock cycles per iteration.
+ unsigned long numloops = 0;
+ unsigned long maxloops = microsecondsToClockCycles(timeout) / 11;
+
+ // wait for any previous pulse to end
+ while ((*portInputRegister(port) & bit) == stateMask)
+ if (numloops++ == maxloops)
+ return 0;
+
+ // wait for the pulse to start
+ while ((*portInputRegister(port) & bit) != stateMask)
+ if (numloops++ == maxloops)
+ return 0;
+
+ // wait for the pulse to stop
+ while ((*portInputRegister(port) & bit) == stateMask) {
+ if (numloops++ == maxloops)
+ return 0;
+ width++;
+ }
+
+ // convert the reading to microseconds. The loop has been determined
+ // to be 13 clock cycles long and have about 11 clocks between the edge
+ // and the start of the loop. There will be some error introduced by
+ // the interrupt handlers.
+ return clockCyclesToMicroseconds(width * 13 + 11);
+}
diff --git a/lib/msp430/wiring_shift.c b/lib/msp430/wiring_shift.c
new file mode 100755
index 0000000..30d2b56
--- /dev/null
+++ b/lib/msp430/wiring_shift.c
@@ -0,0 +1,63 @@
+/*
+ ************************************************************************
+ * wiring_shift.c
+ *
+ * Energia core files for MSP430
+ * Copyright (c) 2012 Robert Wessels. All right reserved.
+ *
+ *
+ ***********************************************************************
+ Derived from:
+ wiring_shift.c - shiftOut() function
+ 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 "wiring_private.h"
+
+uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
+ uint8_t value = 0;
+ uint8_t i;
+
+ for (i = 0; i < 8; ++i) {
+ digitalWrite(clockPin, HIGH);
+ if (bitOrder == LSBFIRST)
+ value |= digitalRead(dataPin) << i;
+ else
+ value |= digitalRead(dataPin) << (7 - i);
+ digitalWrite(clockPin, LOW);
+ }
+ return value;
+}
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
+{
+ uint8_t i;
+
+ for (i = 0; i < 8; i++) {
+ if (bitOrder == LSBFIRST)
+ digitalWrite(dataPin, !!(val & (1 << i)));
+ else
+ digitalWrite(dataPin, !!(val & (1 << (7 - i))));
+
+ digitalWrite(clockPin, HIGH);
+ digitalWrite(clockPin, LOW);
+ }
+}