YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
i2c_msp432.cpp
1/*
2 * spi_msp432.cpp
3 *
4 * Created on: 14.06.2016
5 * Author: Andreas Terstegge
6 */
7
8#include <cassert>
9#include "i2c_msp432.h"
10
11// If existing, use the global SubsystemMasterClock. If not, use our own
12// copy of the SystemCoreClock, assuming that MCLK equals SMCLK ...
13uint32_t I2C_CLK = SystemCoreClock;
14extern uint32_t SubsystemMasterClock __attribute__((weak,alias("I2C_CLK")));
15
16
17i2c_msp432::i2c_msp432(EUSCI_B_Type *mod, uint16_t mode)
18: _initialized(false), _EUSCI(mod), _mode(mode)
19{
20 // Configure hardware characteristics
22 if (mod==EUSCI_B0) {
23 _sda.setGpio (PORT_PIN(1, 6));
24 _scl.setGpio (PORT_PIN(1, 7));
25 } else if (mod==EUSCI_B1) {
26 _sda.setGpio (PORT_PIN(6, 4));
27 _scl.setGpio (PORT_PIN(6, 5));
28 } else if (mod==EUSCI_B2) {
29 _sda.setGpio (PORT_PIN(3, 6));
30 _scl.setGpio (PORT_PIN(3, 7));
31 } else if (mod==EUSCI_B3) {
32 _sda.setGpio (PORT_PIN(10, 2));
33 _scl.setGpio (PORT_PIN(10, 3));
34 }
35 else assert(false);
36}
37
38
39i2c_msp432::~i2c_msp432() {
40 // Wait for pending operations
42 while (_EUSCI->STATW & EUSCI_B_STATW_BBUSY);
43
44 // Reset CTLW0 register to default values
45 // (EUSCI_B is in reset state)
47 _EUSCI->CTLW0 = EUSCI_B_CTLW0_SWRST;
48
49 // De-configure the digital lines
51 _sda.setSEL(0); _sda.setMode(GPIO::INPUT);
52 _scl.setSEL(0); _scl.setMode(GPIO::INPUT);
53}
54
55void i2c_msp432::initialize() {
56 // Reset CTLW0 register to default values
57 // (EUSCI is in reset state)
59 _EUSCI->CTLW0 = EUSCI_B_CTLW0_SWRST;
60
61 // Configure I2C port
63 _EUSCI->CTLW0 |= (_mode | EUSCI_B_CTLW0_MODE_3);
64 _EUSCI->CTLW1 = 0;
65
66 // Set i2c clock to default 100 kHz
68 _EUSCI->BRW = SubsystemMasterClock / 100000;
69
70 // Disable interrupts
72 _EUSCI->IE = 0;
73
74 // Configure the digital RX/TX lines
76 _sda.setMode(GPIO::INPUT | GPIO::PULLUP); _sda.setSEL(1);
77 _scl.setMode(GPIO::INPUT | GPIO::PULLUP); _scl.setSEL(1);
78
79 // Finally enable EUSCI module
81 _EUSCI->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;
82
83 // Set 'initialized' flag
85 _initialized = true;
86}
87
88int16_t i2c_msp432::i2cRead (uint16_t addr, uint8_t *rxbuf, uint16_t len, bool sendStop) {
89 if (!_initialized) initialize();
90 // Check for len 0 because the sendStart/Stop
91 // routines might hang in this case.
92 if (!len) return 0;
93 // clear interrupt status and set slave address
94 int16_t i = _EUSCI->RXBUF;
95 _EUSCI->IFG = 0;
96 _EUSCI->I2CSA = addr;
97 set_receiver();
98 send_START();
99 for (i=0; i < len; ++i) {
100 // check for last byte to receive
101 if ((i+1) == len) {
102 if (sendStop) send_STOP();
103 else _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXSTT;
104 }
105 // Wait until data available
106 while(!(_EUSCI->IFG & (EUSCI_B_IFG_RXIFG0 | EUSCI_B_IFG_NACKIFG)));
107 // Check NAK condition
108 if (_EUSCI->IFG & EUSCI_B_IFG_NACKIFG) {
109 if (sendStop) send_STOP();
110 return i-1;
111 }
112 // read the data
113 rxbuf[i] = _EUSCI->RXBUF;
114 }
115 return i;
116}
117
118int16_t i2c_msp432::i2cWrite(uint16_t addr, uint8_t *txbuf, uint16_t len, bool sendStop) {
119 if (!_initialized) initialize();
120 // Check for len 0 because the sendStart/Stop
121 // routines might hang in this case.
122 if (!len) return 0;
123 // clear interrupt status and set slave address
124 _EUSCI->IFG = 0;
125 _EUSCI->I2CSA = addr;
126 set_transmitter();
127 send_START();
128 int16_t i = 0;
129 for (i=0; i < len; ++i) {
130 // Place character in buffer
131 _EUSCI->TXBUF = txbuf[i];
132 // Wait until byte has been sent or NACK
133 while(!(_EUSCI->IFG & (EUSCI_B_IFG_TXIFG0 | EUSCI_B_IFG_NACKIFG)));
134 // Check NAK condition (also if wrong address!)
135 if (_EUSCI->IFG & EUSCI_B_IFG_NACKIFG) {
136 if (sendStop) send_STOP();
137 return i-1;
138 }
139 }
140 if (sendStop) send_STOP();
141 return i;
142}
143
144void i2c_msp432::setSpeed(uint32_t baud) {
145 if (!_initialized) initialize();
146 _EUSCI->BRW = SubsystemMasterClock / baud;
147}
148
149//void i2c_msp432::send_ADR_ACK() {
150// _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXACK;
151//}
152//
153//void i2c_msp432::send_ADR_NACK() {
154// _EUSCI->CTLW0 &= ~EUSCI_B_CTLW0_TXACK;
155//}
156
157void i2c_msp432::set_receiver() {
158 _EUSCI->CTLW0 &= ~EUSCI_B_CTLW0_TR;
159}
160
161void i2c_msp432::set_transmitter() {
162 _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TR;
163}
164
165//void i2c_msp432::send_ACK() {
166// _EUSCI->CTLW0 &= ~EUSCI_B_CTLW0_TXNACK;
167//}
168//
169//void i2c_msp432::send_NACK() {
170// _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXNACK;
171//}
172
173void i2c_msp432::send_START() {
174 _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXSTT;
175 // Wait until the START condition has been sent
176 while(_EUSCI->CTLW0 & EUSCI_B_CTLW0_TXSTT) ;
177}
178
179void i2c_msp432::send_STOP() {
180 _EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
181 // Wait until the STOP condition has been sent
182 while (_EUSCI->CTLW0 & EUSCI_B_CTLW0_TXSTP);
183}
184
__IO uint16_t CTLW0
__IO uint16_t I2CSA
#define EUSCI_B_CTLW0_MODE_3
#define EUSCI_B_STATW_BBUSY
#define EUSCI_B_CTLW0_TXSTP
__I uint16_t RXBUF
__IO uint16_t IFG
__IO uint16_t IE
__IO uint16_t STATW
#define EUSCI_B_IFG_TXIFG0
#define EUSCI_B_CTLW0_TXSTT
#define EUSCI_B_CTLW0_TR
__IO uint16_t TXBUF
#define EUSCI_B_IFG_NACKIFG
#define EUSCI_B_CTLW0_SWRST
#define EUSCI_B_IFG_RXIFG0
__IO uint16_t BRW
__IO uint16_t CTLW1
void __attribute__((noreturn))(*rom_reset_usb_boot_fn)(uint32_t
Reboot the device into BOOTSEL mode.
Definition bootrom.h:66