aboutsummaryrefslogtreecommitdiff
path: root/msp430/libraries/SPI
diff options
context:
space:
mode:
Diffstat (limited to 'msp430/libraries/SPI')
-rw-r--r--msp430/libraries/SPI/SPI.cpp43
-rw-r--r--msp430/libraries/SPI/SPI.h60
-rw-r--r--msp430/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino146
-rw-r--r--msp430/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino73
-rw-r--r--msp430/libraries/SPI/keywords.txt36
-rw-r--r--msp430/libraries/SPI/utility/spi_430.h50
-rw-r--r--msp430/libraries/SPI/utility/usci_spi.cpp133
-rw-r--r--msp430/libraries/SPI/utility/usi_spi.cpp164
8 files changed, 705 insertions, 0 deletions
diff --git a/msp430/libraries/SPI/SPI.cpp b/msp430/libraries/SPI/SPI.cpp
new file mode 100644
index 0000000..bcb7323
--- /dev/null
+++ b/msp430/libraries/SPI/SPI.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ * SPI Master library for arduino.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ *
+ * 2012-04-29 rick@kimballsoftware.com - added msp430 support.
+ *
+ */
+
+#include <Energia.h>
+
+#include "SPI.h"
+
+SPIClass SPI;
+
+void SPIClass::begin()
+{
+ spi_initialize();
+}
+
+void SPIClass::end()
+{
+ spi_disable();
+}
+
+void SPIClass::setBitOrder(uint8_t bitOrder)
+{
+ spi_set_bitorder(bitOrder);
+}
+
+void SPIClass::setDataMode(uint8_t mode)
+{
+ spi_set_datamode(mode);
+}
+
+void SPIClass::setClockDivider(uint8_t rate)
+{
+ spi_set_divisor(rate);
+}
diff --git a/msp430/libraries/SPI/SPI.h b/msp430/libraries/SPI/SPI.h
new file mode 100644
index 0000000..28b47eb
--- /dev/null
+++ b/msp430/libraries/SPI/SPI.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ * SPI Master library for arduino.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ *
+ * 2012-04-29 rick@kimballsoftware.com - added msp430 support.
+ *
+ */
+
+#ifndef _SPI_H_INCLUDED
+#define _SPI_H_INCLUDED
+
+#include <Energia.h>
+#include <inttypes.h>
+
+#if defined(__MSP430_HAS_USCI__) || defined(__MSP430_HAS_USI__)
+#include "utility/spi_430.h"
+#endif
+
+#define SPI_MODE0 0
+#define SPI_MODE1 1
+#define SPI_MODE2 2
+#define SPI_MODE3 4
+
+class SPIClass {
+public:
+ inline static uint8_t transfer(uint8_t _data);
+
+ // SPI Configuration methods
+
+ static void begin(); // Default
+ static void end();
+
+ static void setBitOrder(uint8_t);
+ static void setDataMode(uint8_t);
+ static void setClockDivider(uint8_t);
+
+ inline static void attachInterrupt();
+ inline static void detachInterrupt();
+};
+
+extern SPIClass SPI;
+
+uint8_t SPIClass::transfer(uint8_t _data) {
+ return spi_send(_data);
+}
+
+void SPIClass::attachInterrupt() {
+ /* undocumented in Arduino 1.0 */
+}
+
+void SPIClass::detachInterrupt() {
+ /* undocumented in Arduino 1.0 */
+}
+
+#endif
diff --git a/msp430/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/msp430/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino
new file mode 100644
index 0000000..66568ea
--- /dev/null
+++ b/msp430/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino
@@ -0,0 +1,146 @@
+/*
+ SCP1000 Barometric Pressure Sensor Display
+
+ Shows the output of a Barometric Pressure Sensor on a
+ Uses the SPI library. For details on the sensor, see:
+ http://www.sparkfun.com/commerce/product_info.php?products_id=8161
+ http://www.vti.fi/en/support/obsolete_products/pressure_sensors/
+
+ This sketch adapted from Nathan Seidle's SCP1000 example for PIC:
+ http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip
+
+ Circuit:
+ SCP1000 sensor attached to pins 6, 7, 10 - 13:
+ DRDY: pin 6
+ CSB: pin 8
+ MOSI: pin 14/15
+ MISO: pin 15/14 * need to level convert this
+ SCK: pin 7
+
+ created 31 July 2010
+ modified 14 August 2010
+ by Tom Igoe
+
+ modified 2 May 2012
+ Rick Kimball - changed pin # for msp430
+
+ */
+
+// the sensor communicates using SPI, so include the library:
+#include <SPI.h>
+
+//Sensor's memory register addresses:
+const int PRESSURE = 0x1F; // 3 most significant bits of pressure
+const int PRESSURE_LSB = 0x20; // 16 least significant bits of pressure
+const int TEMPERATURE = 0x21; // 16 bit temperature reading
+const byte READ = 0b11111100; // SCP1000's read command
+const byte WRITE = 0b00000010; // SCP1000's write command
+
+// pins used for the connection with the sensor
+// the other you need are controlled by the SPI library):
+const int dataReadyPin = 9; // P2.1
+const int chipSelectPin = 8; // P2.0
+
+void setup() {
+ Serial.begin(9600);
+
+ // start the SPI library:
+ SPI.begin();
+
+ // initialize the data ready and chip select pins:
+ pinMode(dataReadyPin, INPUT);
+ pinMode(chipSelectPin, OUTPUT);
+
+ //Configure SCP1000 for low noise configuration:
+ writeRegister(0x02, 0x2D);
+ writeRegister(0x01, 0x03);
+ writeRegister(0x03, 0x02);
+ // give the sensor time to set up:
+ delay(100);
+}
+
+void loop() {
+ //Select High Resolution Mode
+ writeRegister(0x03, 0x0A);
+
+ // don't do anything until the data ready pin is high:
+ if (digitalRead(dataReadyPin) == HIGH) {
+ //Read the temperature data
+ int tempData = readRegister(0x21, 2);
+
+ // convert the temperature to celsius and display it:
+ float realTemp = (float)tempData / 20.0;
+ Serial.print("Temp[C]=");
+ Serial.print(realTemp);
+
+
+ //Read the pressure data highest 3 bits:
+ byte pressure_data_high = readRegister(0x1F, 1);
+ pressure_data_high &= 0b00000111; //you only needs bits 2 to 0
+
+ //Read the pressure data lower 16 bits:
+ unsigned int pressure_data_low = readRegister(0x20, 2);
+ //combine the two parts into one 19-bit number:
+ long pressure = ((pressure_data_high << 16) | pressure_data_low)/4;
+
+ // display the temperature:
+ Serial.println("\tPressure [Pa]=" + String(pressure));
+ }
+}
+
+//Read from or write to register from the SCP1000:
+unsigned int readRegister(byte thisRegister, int bytesToRead ) {
+ byte inByte = 0; // incoming byte from the SPI
+ unsigned int result = 0; // result to return
+ Serial.print(thisRegister, BIN);
+ Serial.print("\t");
+ // SCP1000 expects the register name in the upper 6 bits
+ // of the byte. So shift the bits left by two bits:
+ thisRegister = thisRegister << 2;
+ // now combine the address and the command into one byte
+ byte dataToSend = thisRegister & READ;
+ Serial.println(thisRegister, BIN);
+ // take the chip select low to select the device:
+ digitalWrite(chipSelectPin, LOW);
+ // send the device the register you want to read:
+ SPI.transfer(dataToSend);
+ // send a value of 0 to read the first byte returned:
+ result = SPI.transfer(0x00);
+ // decrement the number of bytes left to read:
+ bytesToRead--;
+ // if you still have another byte to read:
+ if (bytesToRead > 0) {
+ // shift the first byte left, then get the second byte:
+ result = result << 8;
+ inByte = SPI.transfer(0x00);
+ // combine the byte you just got with the previous one:
+ result = result | inByte;
+ // decrement the number of bytes left to read:
+ bytesToRead--;
+ }
+ // take the chip select high to de-select:
+ digitalWrite(chipSelectPin, HIGH);
+ // return the result:
+ return(result);
+}
+
+
+//Sends a write command to SCP1000
+
+void writeRegister(byte thisRegister, byte thisValue) {
+
+ // SCP1000 expects the register address in the upper 6 bits
+ // of the byte. So shift the bits left by two bits:
+ thisRegister = thisRegister << 2;
+ // now combine the register address and the command into one byte:
+ byte dataToSend = thisRegister | WRITE;
+
+ // take the chip select low to select the device:
+ digitalWrite(chipSelectPin, LOW);
+
+ SPI.transfer(dataToSend); //Send register location
+ SPI.transfer(thisValue); //Send value to record into register
+
+ // take the chip select high to de-select:
+ digitalWrite(chipSelectPin, HIGH);
+}
diff --git a/msp430/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/msp430/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino
new file mode 100644
index 0000000..d808a68
--- /dev/null
+++ b/msp430/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino
@@ -0,0 +1,73 @@
+/*
+ Digital Pot Control
+
+ This example controls an Analog Devices AD5206 digital potentiometer.
+ The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
+ A - connect this to voltage
+ W - this is the pot's wiper, which changes when you set it
+ B - connect this to ground.
+
+ The AD5206 is SPI-compatible,and to command it, you send two bytes,
+ one with the channel number (0 - 5) and one with the resistance value for the
+ channel (0 - 255).
+
+ The circuit:
+ * All A pins of AD5206 connected to +5V
+ * All B pins of AD5206 connected to ground
+ * An LED and a 220-ohm resisor in series connected from each W pin to ground
+ * CS - to digital pin 8 (SS pin) P2.0
+ * SDI - to digital pin 14/15 (MOSI pin USI/USCI) P1.6/P1.7
+ * CLK - to digital pin 7 (SCK pin) P1.5
+
+ created 10 Aug 2010
+ by Tom Igoe
+
+ modified 2 May 2012 - changed SS pin
+ by Rick Kimball
+
+ Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
+
+*/
+
+
+// include the SPI library:
+#include <SPI.h>
+
+// set pin 8 as the slave select for the digital pot:
+const int slaveSelectPin = SS;
+
+void setup() {
+ // set the slaveSelectPin as an output:
+ pinMode (slaveSelectPin, OUTPUT);
+ // initialize SPI:
+ SPI.begin();
+}
+
+void loop() {
+ // go through the six channels of the digital pot:
+ for (int channel = 0; channel < 6; channel++) {
+ // change the resistance on this channel from min to max:
+ for (int level = 0; level < 255; level++) {
+ digitalPotWrite(channel, level);
+ delay(10);
+ }
+ // wait a second at the top:
+ delay(100);
+ // change the resistance on this channel from max to min:
+ for (int level = 0; level < 255; level++) {
+ digitalPotWrite(channel, 255 - level);
+ delay(10);
+ }
+ }
+
+}
+
+int digitalPotWrite(int address, int value) {
+ // take the SS pin low to select the chip:
+ digitalWrite(slaveSelectPin,LOW);
+ // send in the address and value via SPI:
+ SPI.transfer(address);
+ SPI.transfer(value);
+ // take the SS pin high to de-select the chip:
+ digitalWrite(slaveSelectPin,HIGH);
+} \ No newline at end of file
diff --git a/msp430/libraries/SPI/keywords.txt b/msp430/libraries/SPI/keywords.txt
new file mode 100644
index 0000000..fa76165
--- /dev/null
+++ b/msp430/libraries/SPI/keywords.txt
@@ -0,0 +1,36 @@
+#######################################
+# Syntax Coloring Map SPI
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+SPI KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+begin KEYWORD2
+end KEYWORD2
+transfer KEYWORD2
+setBitOrder KEYWORD2
+setDataMode KEYWORD2
+setClockDivider KEYWORD2
+
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+SPI_CLOCK_DIV4 LITERAL1
+SPI_CLOCK_DIV16 LITERAL1
+SPI_CLOCK_DIV64 LITERAL1
+SPI_CLOCK_DIV128 LITERAL1
+SPI_CLOCK_DIV2 LITERAL1
+SPI_CLOCK_DIV8 LITERAL1
+SPI_CLOCK_DIV32 LITERAL1
+SPI_CLOCK_DIV64 LITERAL1
+SPI_MODE0 LITERAL1
+SPI_MODE1 LITERAL1
+SPI_MODE2 LITERAL1
+SPI_MODE3 LITERAL1 \ No newline at end of file
diff --git a/msp430/libraries/SPI/utility/spi_430.h b/msp430/libraries/SPI/utility/spi_430.h
new file mode 100644
index 0000000..262759a
--- /dev/null
+++ b/msp430/libraries/SPI/utility/spi_430.h
@@ -0,0 +1,50 @@
+/*
+ * spi_430.h - common function declarations for different SPI implementations
+ *
+ * Copyright (c) 2012 by Rick Kimball <rick@kimballsoftware.com>
+ * spi abstraction api for msp430
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _SPI_430_H_
+#define _SPI_430_H_
+
+#if defined(__MSP430_HAS_USCI__)
+
+#define SPI_CLOCK_DIV1 1
+#define SPI_CLOCK_DIV2 2
+#define SPI_CLOCK_DIV4 4
+#define SPI_CLOCK_DIV8 8
+#define SPI_CLOCK_DIV16 16
+#define SPI_CLOCK_DIV32 32
+#define SPI_CLOCK_DIV64 64
+#define SPI_CLOCK_DIV128 128
+
+#elif defined(__MSP430_HAS_USI__)
+
+#define SPI_CLOCK_DIV1 0
+#define SPI_CLOCK_DIV2 USIDIV_1
+#define SPI_CLOCK_DIV4 USIDIV_2
+#define SPI_CLOCK_DIV8 USIDIV_3
+#define SPI_CLOCK_DIV16 USIDIV_4
+#define SPI_CLOCK_DIV32 USIDIV_5
+#define SPI_CLOCK_DIV64 USIDIV_6
+#define SPI_CLOCK_DIV128 USIDIV_7
+
+#else
+ #error "SPI not supported by hardware on this chip"
+#endif
+
+void spi_initialize(void);
+void spi_disable(void);
+uint8_t spi_send(const uint8_t);
+void spi_set_bitorder(const uint8_t);
+void spi_set_datamode(const uint8_t);
+void spi_set_divisor(const uint16_t clkdivider);
+
+#endif /*_SPI_430_H_*/
diff --git a/msp430/libraries/SPI/utility/usci_spi.cpp b/msp430/libraries/SPI/utility/usci_spi.cpp
new file mode 100644
index 0000000..25d7157
--- /dev/null
+++ b/msp430/libraries/SPI/utility/usci_spi.cpp
@@ -0,0 +1,133 @@
+/**
+ * File: usci_spi.c - msp430 USCI SPI implementation
+ *
+ * Copyright (c) 2012 by Rick Kimball <rick@kimballsoftware.com>
+ * spi abstraction api for msp430
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <msp430.h>
+#include <stdint.h>
+#include "spi_430.h"
+
+#ifdef __MSP430_HAS_USCI__
+
+/**
+ * USCI flags for various the SPI MODEs
+ *
+ * Note: The msp430 UCCKPL tracks the CPOL value. However,
+ * the UCCKPH flag is inverted when compared to the CPHA
+ * value described in Motorola documentation.
+ */
+
+#define SPI_MODE_0 (UCCKPH) /* CPOL=0 CPHA=0 */
+#define SPI_MODE_1 (0) /* CPOL=0 CPHA=1 */
+#define SPI_MODE_2 (UCCKPL | UCCKPH) /* CPOL=1 CPHA=0 */
+#define SPI_MODE_3 (UCCKPL) /* CPOL=1 CPHA=1 */
+
+#define SPI_MODE_MASK (UCCKPL | UCCKPH)
+
+/**
+ * spi_initialize() - Configure USCI UCB0 for SPI mode
+ *
+ * P2.0 - CS (active low)
+ * P1.5 - SCLK
+ * P1.6 - MISO aka SOMI
+ * P1.7 - MOSI aka SIMO
+ *
+ */
+void spi_initialize(void)
+{
+ UCB0CTL1 = UCSWRST | UCSSEL_2; // Put USCI in reset mode, source USCI clock from SMCLK
+ UCB0CTL0 = SPI_MODE_0 | UCMSB | UCSYNC | UCMST; // Use SPI MODE 0 - CPOL=0 CPHA=0
+
+ P1OUT |= (BIT5 | BIT7); // SPI output pins low
+ P1SEL |= BIT5 | BIT6 | BIT7; // configure P1.5, P1.6, P1.7 for USCI
+ P1SEL2 |= BIT5 | BIT6 | BIT7; // more required SPI configuration
+
+ UCB0BR0 = SPI_CLOCK_DIV4 & 0xFF; // set initial speed to 4MHz
+ UCB0BR1 = (SPI_CLOCK_DIV4 >> 8 ) & 0xFF;
+
+ UCB0CTL1 &= ~UCSWRST; // release USCI for operation
+}
+
+/**
+ * spi_disable() - put USCI into reset mode
+ */
+void spi_disable(void)
+{
+ UCB0CTL1 |= UCSWRST; // Put USCI in reset mode
+}
+
+/**
+ * spi_send() - send a byte and recv response
+ */
+uint8_t spi_send(const uint8_t _data)
+{
+ while (!(UC0IFG & UCB0TXIFG))
+ ; // wait for previous tx to complete
+
+ UCB0TXBUF = _data; // setting TXBUF clears the TXIFG flag
+
+ while (!(UC0IFG & UCB0RXIFG))
+ ; // wait for an rx character?
+
+ return UCB0RXBUF; // reading clears RXIFG flag
+}
+
+/***SPI_MODE_0
+ * spi_set_divisor() - set new clock divider for USCI
+ *
+ * USCI speed is based on the SMCLK divided by BR0 and BR1
+ *
+ */
+void spi_set_divisor(const uint16_t clkdiv)
+{
+ UCB0CTL1 |= UCSWRST; // go into reset state
+ UCB0BR0 = clkdiv & 0xFF;
+ UCB0BR1 = (clkdiv >> 8 ) & 0xFF;
+ UCB0CTL1 &= ~UCSWRST; // release for operation
+}
+
+/**
+ * spi_set_bitorder(LSBFIRST=0 | MSBFIRST=1)
+ */
+void spi_set_bitorder(const uint8_t order)
+{
+ UCB0CTL1 |= UCSWRST; // go into reset state
+ UCB0CTL0 = (UCB0CTL0 & ~UCMSB) | ((order == 1 /*MSBFIRST*/) ? UCMSB : 0); /* MSBFIRST = 1 */
+ UCB0CTL1 &= ~UCSWRST; // release for operation
+}
+
+/**
+ * spi_set_datamode() - mode 0 - 3
+ */
+void spi_set_datamode(const uint8_t mode)
+{
+ UCB0CTL1 |= UCSWRST; // go into reset state
+ switch(mode) {
+ case 0: /* SPI_MODE0 */
+ UCB0CTL0 = (UCB0CTL0 & ~SPI_MODE_MASK) | SPI_MODE_0;
+ break;
+ case 1: /* SPI_MODE1 */
+ UCB0CTL0 = (UCB0CTL0 & ~SPI_MODE_MASK) | SPI_MODE_1;
+ break;
+ case 2: /* SPI_MODE2 */
+ UCB0CTL0 = (UCB0CTL0 & ~SPI_MODE_MASK) | SPI_MODE_2;
+ break;
+ case 4: /* SPI_MODE3 */
+ UCB0CTL0 = (UCB0CTL0 & ~SPI_MODE_MASK) | SPI_MODE_3;
+ break;
+ default:
+ break;
+ }
+ UCB0CTL1 &= ~UCSWRST; // release for operation
+}
+#else
+ //#error "Error! This device doesn't have a USCI peripheral"
+#endif
diff --git a/msp430/libraries/SPI/utility/usi_spi.cpp b/msp430/libraries/SPI/utility/usi_spi.cpp
new file mode 100644
index 0000000..a03fd6a
--- /dev/null
+++ b/msp430/libraries/SPI/utility/usi_spi.cpp
@@ -0,0 +1,164 @@
+/**
+ * File: usi_spi.c - msp430 USI SPI implementation
+ *
+ * Copyright (c) 2012 by Rick Kimball <rick@kimballsoftware.com>
+ * spi abstraction api for msp430
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ *
+ * 07-14-2012 - rick@kimballsoftware.com
+ * Fixed MODE2/MODE3 phase problems. Added logic to deal with USI5 errata.
+ */
+
+#include <msp430.h>
+#include <stdint.h>
+#include "spi_430.h"
+
+#ifdef __MSP430_HAS_USI__
+/**
+ * USI flags for various the SPI MODEs
+ *
+ * Note: The msp430 USICKPL tracks the CPOL value. However,
+ * the USICKPH flag is inverted when compared to the CPHA
+ * value described in Motorola documentation.
+ */
+#define SPI_DIV_MASK (USIDIV0 | USIDIV1 | USIDIV2)
+#define SPI_LSBMSB_MASK (USILSB)
+
+/* deal with USI5 errata see: document slaz061b */
+enum USI5 {
+ USI5_NO_ADJUST=0,
+ USI5_ADJUST=1,
+ USI5_SENT=2,
+};
+static enum USI5 bResetAdjust;
+
+/**
+ * spi_initialize() - Configure USI for SPI mode
+ *
+ * P2.0 - CS (active low)
+ * P1.5 - SCLK
+ * P1.6 - MOSI aka SIMO
+ * P1.7 - MISO aka SOMI
+ */
+
+void spi_initialize(void)
+{
+ USICTL0 |= USISWRST; // put USI in reset mode, source USI clock from SMCLK
+ USICTL0 |= USIPE5 | USIPE6 | USIPE7 | USIMST | USIOE;
+ USICKCTL |= USIDIV_2 | USISSEL_2; // default speed 4MHz 16MHz/4
+ USICTL1 = USICKPH; // SPI_MODE_0
+
+ P1OUT |= BIT5 | BIT6; // SPI OUTPUT PINS LOW
+ P1DIR = (P1DIR & ~BIT7) | BIT5 | BIT6; // configure P1.5, P1.6, P1.7 for USI
+
+ USICTL0 &= ~USISWRST; // release USI for operation
+
+ bResetAdjust = USI5_ADJUST;
+}
+
+void spi_disable(void) {
+ USICTL0 |= USISWRST; // put USI in reset mode
+}
+
+/**
+ * spi_send() - send a byte and recv response
+ */
+uint8_t spi_send(const uint8_t _data)
+{
+ USISRL = _data;
+
+ // SPI master generates one additional clock after module reset if USICKPH is set.
+ if ( bResetAdjust == USI5_ADJUST ) {
+ USICNT=7; // adjust first time send
+ bResetAdjust = USI5_SENT;
+ }
+ else {
+ USICNT = 8;
+ }
+
+ while (!(USICTL1 & USIIFG)) {
+ ; // wait for an USICNT to decrement to 0
+ }
+
+ return USISRL; // reading clears RXIFG flag
+}
+
+/**
+ * spi_set_divisor() - set new clock divider for USI
+ *
+ * There are a fixed set of valid values for clock divisors
+ * see the slau144 for details. DIV by 2/4/8 .. 128
+ */
+
+void spi_set_divisor(const uint16_t clkdiv)
+{
+ USICTL0 |= USISWRST; // put USI in reset mode
+ USICKCTL = (USICKCTL & ~SPI_DIV_MASK) | clkdiv;
+ USICTL0 &= ~USISWRST; // release for operation
+}
+
+/**
+ * spi_set_bitorder (enum LSBFIRST=0|MSBFIRST=1)
+ *
+ * Note: this should use the LSBFIRST/MSBFIRST defines however
+ * it doesn't to allow this code to compile without Energia.
+ *
+ */
+void spi_set_bitorder(const uint8_t order)
+{
+ USICTL0 |= USISWRST; // put USI in reset mode
+ USICTL0 = (USICTL0 & ~SPI_LSBMSB_MASK) | ((order == 1 /*MSBFIRST*/) ? 0 : USILSB); /* MSBFIRST = 1 */
+ USICTL0 &= ~USISWRST; // release for operation
+}
+
+/**
+ * spi_set_datamode() - Motorola SPI Mode 0 ... 3
+ *
+ * mode is really an enum SPI_MODE0 ... SPI_MODE3 as defined in
+ * the Energia header file.
+ */
+void spi_set_datamode(const uint8_t mode)
+{
+ USICTL0 |= USISWRST; // put USI in reset mode while we make changes
+ switch(mode) {
+ case 0: /* SPI_MODE0 */
+ USICKCTL &= ~USICKPL; /* CPOL=0 */
+ USICTL1 |= USICKPH; /* CPHA=0 */
+ break;
+
+ case 1: /* SPI_MODE1 */
+ USICKCTL &= ~USICKPL; /* CPOL=0 */
+ USICTL1 &= ~USICKPH; /* CPHA=1 */
+ break;
+
+ case 2: /* SPI_MODE2 */
+ USICKCTL |= USICKPL; /* CPOL=1 */
+ USICTL1 |= USICKPH; /* CPHA=0 */
+ break;
+
+ case 4: /* SPI_MODE3 */
+ USICKCTL |= USICKPL; /* CPOL=1 */
+ USICTL1 &= ~USICKPH; /* CPHA=1 */
+ break;
+
+ default:
+ break;
+ }
+ USICTL0 &= ~USISWRST; // release for operation
+
+ if ( USICTL1 & USICKPH ) {
+ if ( bResetAdjust != USI5_SENT ) {
+ bResetAdjust = USI5_ADJUST;
+ }
+ }
+ else {
+ bResetAdjust = USI5_NO_ADJUST;
+ }
+}
+#else
+ //#warning "Error! This device doesn't have a USI peripheral"
+#endif