SPI or I2C to UART Bridge

Dependents:   SC16IS750_Test mbed_SC16IS750 Xadow_SC16IS750_Test Xadow_MPU9150AHRS

Committer:
wim
Date:
Sun Feb 09 14:58:06 2014 +0000
Revision:
1:0440152c5387
Parent:
0:d64854a60f95
Child:
2:76cb93b511f2
working proto, tested on BOB

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wim 0:d64854a60f95 1 /* SC16IS750 interface
wim 1:0440152c5387 2 * v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods
wim 0:d64854a60f95 3 *
wim 0:d64854a60f95 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
wim 0:d64854a60f95 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
wim 0:d64854a60f95 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
wim 0:d64854a60f95 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
wim 0:d64854a60f95 8 * furnished to do so, subject to the following conditions:
wim 0:d64854a60f95 9 *
wim 0:d64854a60f95 10 * The above copyright notice and this permission notice shall be included in all copies or
wim 0:d64854a60f95 11 * substantial portions of the Software.
wim 0:d64854a60f95 12 *
wim 0:d64854a60f95 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
wim 0:d64854a60f95 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
wim 0:d64854a60f95 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
wim 0:d64854a60f95 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 0:d64854a60f95 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
wim 0:d64854a60f95 18 */
wim 0:d64854a60f95 19 #include "mbed.h"
wim 0:d64854a60f95 20 #include "SC16IS750.h"
wim 0:d64854a60f95 21
wim 0:d64854a60f95 22
wim 0:d64854a60f95 23 /** Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port
wim 1:0440152c5387 24 * Constructor for this Abstract Class is protected
wim 0:d64854a60f95 25 * Supports both SPI and I2C interfaces through derived classes
wim 0:d64854a60f95 26 *
wim 0:d64854a60f95 27 * @code
wim 0:d64854a60f95 28 *
wim 0:d64854a60f95 29 * @endcode
wim 0:d64854a60f95 30 */
wim 0:d64854a60f95 31 //SC16IS750::SC16IS750() : Serial(NC, NC) { //Fout ???
wim 0:d64854a60f95 32 SC16IS750::SC16IS750() {
wim 1:0440152c5387 33 // Dont call _init() here since the SPI or I2C port have not yet been configured...
wim 1:0440152c5387 34 //_init(); // initialise UART registers
wim 0:d64854a60f95 35 }
wim 0:d64854a60f95 36
wim 0:d64854a60f95 37
wim 0:d64854a60f95 38 /** Set baudrate of the serial port.
wim 0:d64854a60f95 39 * @param baud integer baudrate (4800, 9600 etc)
wim 0:d64854a60f95 40 * @return none
wim 0:d64854a60f95 41 */
wim 0:d64854a60f95 42 void SC16IS750::baud(int baudrate) {
wim 0:d64854a60f95 43 unsigned long divisor = BAUD_RATE_DIVISOR(baudrate);
wim 0:d64854a60f95 44 char lcr_tmp;
wim 0:d64854a60f95 45
wim 0:d64854a60f95 46 _config.baudrate = baudrate; // Save baudrate
wim 0:d64854a60f95 47
wim 0:d64854a60f95 48 lcr_tmp = this->readRegister(LCR); // Read current LCR register
wim 1:0440152c5387 49 this->writeRegister(LCR, lcr_tmp | LCR_ENABLE_DIV); // Enable Divisor registers
wim 0:d64854a60f95 50 this->writeRegister(DLL, ( divisor & 0xFF)); // write divisor LSB
wim 0:d64854a60f95 51 this->writeRegister(DLH, ((divisor >> 8) & 0xFF)); // write divisor MSB
wim 0:d64854a60f95 52 this->writeRegister(LCR, lcr_tmp); // Restore LCR register, activate regular RBR, THR and IER registers
wim 1:0440152c5387 53
wim 0:d64854a60f95 54 }
wim 0:d64854a60f95 55
wim 0:d64854a60f95 56
wim 0:d64854a60f95 57 /** Set the transmission format used by the serial port.
wim 0:d64854a60f95 58 * @param bits The number of bits in a word (5-8; default = 8)
wim 0:d64854a60f95 59 * @param parity The parity used (Serial::None, Serial::Odd, Serial::Even, Serial::Forced1, Serial::Forced0; default = Serial::None)
wim 0:d64854a60f95 60 * @param stop_bits The number of stop bits (1 or 2; default = 1)
wim 0:d64854a60f95 61 */
wim 0:d64854a60f95 62 void SC16IS750::format(int bits, Serial::Parity parity, int stop_bits) {
wim 0:d64854a60f95 63 char lcr_tmp = 0x00;
wim 0:d64854a60f95 64
wim 0:d64854a60f95 65 switch (bits) {
wim 0:d64854a60f95 66 case 5: lcr_tmp |= LCR_BITS5;
wim 0:d64854a60f95 67 break;
wim 0:d64854a60f95 68 case 6: lcr_tmp |= LCR_BITS6;
wim 0:d64854a60f95 69 break;
wim 0:d64854a60f95 70 case 7: lcr_tmp |= LCR_BITS7;
wim 0:d64854a60f95 71 break;
wim 0:d64854a60f95 72 case 8: lcr_tmp |= LCR_BITS8;
wim 0:d64854a60f95 73 break;
wim 0:d64854a60f95 74 default: lcr_tmp |= LCR_BITS8;
wim 0:d64854a60f95 75 }
wim 0:d64854a60f95 76
wim 0:d64854a60f95 77 switch (parity) {
wim 0:d64854a60f95 78 case Serial::None: lcr_tmp |= LCR_NONE;
wim 0:d64854a60f95 79 break;
wim 0:d64854a60f95 80 case Serial::Odd: lcr_tmp |= LCR_ODD;
wim 0:d64854a60f95 81 break;
wim 0:d64854a60f95 82 case Serial::Even: lcr_tmp |= LCR_EVEN;
wim 0:d64854a60f95 83 break;
wim 0:d64854a60f95 84 case Serial::Forced1: lcr_tmp |= LCR_FORCED1;
wim 0:d64854a60f95 85 break;
wim 0:d64854a60f95 86 case Serial::Forced0: lcr_tmp |= LCR_FORCED0;
wim 0:d64854a60f95 87 break;
wim 0:d64854a60f95 88 default: lcr_tmp |= LCR_NONE;
wim 0:d64854a60f95 89 }
wim 0:d64854a60f95 90
wim 0:d64854a60f95 91 switch (stop_bits) {
wim 0:d64854a60f95 92 case 1: lcr_tmp |= LCR_BITS1;
wim 0:d64854a60f95 93 break;
wim 0:d64854a60f95 94 case 2: lcr_tmp |= LCR_BITS2;
wim 0:d64854a60f95 95 break;
wim 0:d64854a60f95 96 default: lcr_tmp |= LCR_BITS1;
wim 0:d64854a60f95 97 }
wim 0:d64854a60f95 98
wim 0:d64854a60f95 99 _config.dataformat = lcr_tmp; // Save dataformat
wim 0:d64854a60f95 100
wim 0:d64854a60f95 101 this->writeRegister(LCR, lcr_tmp); // Set LCR register, activate regular RBR, THR and IER registers
wim 0:d64854a60f95 102
wim 0:d64854a60f95 103 };
wim 0:d64854a60f95 104
wim 1:0440152c5387 105 /** Generate a break condition on the serial line
wim 1:0440152c5387 106 */
wim 1:0440152c5387 107 void SC16IS750::send_break() {
wim 1:0440152c5387 108 // Wait for 1.5 frames before clearing the break condition
wim 1:0440152c5387 109 // This will have different effects on our platforms, but should
wim 1:0440152c5387 110 // ensure that we keep the break active for at least one frame.
wim 1:0440152c5387 111 // We consider a full frame (1 start bit + 8 data bits bits +
wim 1:0440152c5387 112 // 1 parity bit + 2 stop bits = 12 bits) for computation.
wim 1:0440152c5387 113 // One bit time (in us) = 1000000/_baud
wim 1:0440152c5387 114 // Twelve bits: 12000000/baud delay
wim 1:0440152c5387 115 // 1.5 frames: 18000000/baud delay
wim 1:0440152c5387 116 set_break(true);
wim 1:0440152c5387 117 wait_us(18000000/_config.baudrate);
wim 1:0440152c5387 118 set_break(false);
wim 1:0440152c5387 119 };
wim 1:0440152c5387 120
wim 1:0440152c5387 121 /** Set a break condition on the serial line
wim 1:0440152c5387 122 * @param enable break condition
wim 1:0440152c5387 123 */
wim 1:0440152c5387 124 void SC16IS750::set_break(bool enable) {
wim 0:d64854a60f95 125
wim 1:0440152c5387 126 if (enable) {
wim 1:0440152c5387 127 _config.dataformat |= LCR_BRK_ENA; // Save dataformat
wim 1:0440152c5387 128 }
wim 1:0440152c5387 129 else {
wim 1:0440152c5387 130 _config.dataformat &= ~LCR_BRK_ENA; // Save dataformat
wim 1:0440152c5387 131 }
wim 1:0440152c5387 132
wim 1:0440152c5387 133 this->writeRegister(LCR, _config.dataformat); // Set LCR register
wim 1:0440152c5387 134 }
wim 1:0440152c5387 135
wim 1:0440152c5387 136 /** Set the flow control type on the serial port
wim 1:0440152c5387 137 * Added for compatibility with Serial Class.
wim 1:0440152c5387 138 * SC16IS750 supports only Flow, Pins can not be selected.
wim 0:d64854a60f95 139 *
wim 1:0440152c5387 140 * @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
wim 1:0440152c5387 141 * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
wim 1:0440152c5387 142 * @param flow2 the second flow control pin (CTS for RTSCTS)
wim 0:d64854a60f95 143 */
wim 1:0440152c5387 144 void SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) {
wim 1:0440152c5387 145 char lcr_tmp;
wim 1:0440152c5387 146 char efr_tmp = 0x00;
wim 1:0440152c5387 147
wim 1:0440152c5387 148 // We need to enable flow control to prevent overflow of buffers and
wim 1:0440152c5387 149 // lose data when used with fast devices like the WiFly.
wim 1:0440152c5387 150
wim 1:0440152c5387 151 switch (type) {
wim 1:0440152c5387 152 case Disabled :
wim 1:0440152c5387 153 break;
wim 1:0440152c5387 154 case RTS: efr_tmp = EFR_ENABLE_RTS;
wim 1:0440152c5387 155 break;
wim 1:0440152c5387 156 case CTS: efr_tmp = EFR_ENABLE_CTS;
wim 1:0440152c5387 157 break;
wim 1:0440152c5387 158 case RTSCTS: efr_tmp = EFR_ENABLE_RTS | EFR_ENABLE_CTS;
wim 1:0440152c5387 159 break;
wim 1:0440152c5387 160 default: ;
wim 1:0440152c5387 161
wim 1:0440152c5387 162 }
wim 1:0440152c5387 163
wim 1:0440152c5387 164 //Save flowcontrol state
wim 1:0440152c5387 165 //enable enhanced functions
wim 1:0440152c5387 166 _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS,
wim 1:0440152c5387 167
wim 1:0440152c5387 168 lcr_tmp = this->readRegister(LCR); // save LRC register
wim 1:0440152c5387 169 this->writeRegister(LCR, LCR_ENABLE_ENHANCED_FUNCTIONS); // write magic number 0xBF to enable access to EFR register
wim 1:0440152c5387 170 this->writeRegister(EFR, _config.flowctrl); // set flow and enable enhanced functions
wim 1:0440152c5387 171 this->writeRegister(LCR, lcr_tmp); // restore LCR register
wim 1:0440152c5387 172 }
wim 1:0440152c5387 173
wim 1:0440152c5387 174
wim 1:0440152c5387 175 /** Initialise internal registers
wim 1:0440152c5387 176 * Should be in protection section. Public for testing purposes
wim 1:0440152c5387 177 * If initialisation fails this method does not return.
wim 1:0440152c5387 178 * @param none
wim 1:0440152c5387 179 * @return none
wim 1:0440152c5387 180 */
wim 1:0440152c5387 181 void SC16IS750::_init() {
wim 0:d64854a60f95 182
wim 0:d64854a60f95 183 // Initialise SC16IS750
wim 0:d64854a60f95 184
wim 1:0440152c5387 185 // Software reset, assuming there is no access to the HW Reset pin
wim 1:0440152c5387 186 swReset();
wim 1:0440152c5387 187
wim 0:d64854a60f95 188 // Set default baudrate and save in _config
wim 1:0440152c5387 189 // LCR, DLL/DLH
wim 0:d64854a60f95 190 baud();
wim 0:d64854a60f95 191
wim 0:d64854a60f95 192 // Set dataflow and save in _config
wim 1:0440152c5387 193 // LCR, EFR
wim 1:0440152c5387 194 set_flow_control();
wim 0:d64854a60f95 195
wim 0:d64854a60f95 196 // Set default dataformat and save in _config
wim 1:0440152c5387 197 // LCR
wim 0:d64854a60f95 198 format();
wim 0:d64854a60f95 199
wim 1:0440152c5387 200 // Set default break condition and save in _config
wim 1:0440152c5387 201 // LCR
wim 1:0440152c5387 202 //set_break();
wim 1:0440152c5387 203
wim 0:d64854a60f95 204 // Set default fifoformat and save in _config
wim 1:0440152c5387 205 // FCR
wim 1:0440152c5387 206 _config.fifoenable = true;
wim 1:0440152c5387 207 _config.fifoformat = FCR_RX_IRQ_NONE | FCR_ENA_FIFO_64;
wim 1:0440152c5387 208 flush();
wim 0:d64854a60f95 209
wim 0:d64854a60f95 210 // The UART bridge should now be successfully initialised.
wim 0:d64854a60f95 211
wim 0:d64854a60f95 212 // Test if UART bridge is present and initialised
wim 0:d64854a60f95 213 if(!connected()){
wim 0:d64854a60f95 214 #if(0)
wim 0:d64854a60f95 215 // Lock up if we fail to initialise UART bridge.
wim 1:0440152c5387 216 while(1) {};
wim 0:d64854a60f95 217 #else
wim 0:d64854a60f95 218 printf("Failed to initialise UART bridge\r\n");
wim 1:0440152c5387 219 #endif
wim 1:0440152c5387 220 }
wim 1:0440152c5387 221 else {
wim 1:0440152c5387 222 printf("Initialised UART bridge!\r\n");
wim 1:0440152c5387 223 }
wim 1:0440152c5387 224
wim 1:0440152c5387 225 }
wim 1:0440152c5387 226
wim 1:0440152c5387 227 /**
wim 1:0440152c5387 228 * Flush the UART FIFOs while maintaining current FIFO mode.
wim 1:0440152c5387 229 * @param none
wim 1:0440152c5387 230 * @return none
wim 1:0440152c5387 231 */
wim 1:0440152c5387 232 void SC16IS750::flush() {
wim 1:0440152c5387 233
wim 1:0440152c5387 234 // reset TXFIFO, reset RXFIFO, non FIFO mode
wim 1:0440152c5387 235 this->writeRegister(FCR, FCR_TXFIFO_RST | FCR_RXFIFO_RST);
wim 1:0440152c5387 236
wim 1:0440152c5387 237 if (_config.fifoenable)
wim 1:0440152c5387 238 // enable FIFO mode and set FIFO control values
wim 1:0440152c5387 239 this->writeRegister(FCR, _config.fifoformat | FCR_ENABLE_FIFO);
wim 1:0440152c5387 240 else
wim 1:0440152c5387 241 // disable FIFO mode and set FIFO control values
wim 1:0440152c5387 242 this->writeRegister(FCR, _config.fifoformat);
wim 1:0440152c5387 243
wim 1:0440152c5387 244 #if(0)
wim 1:0440152c5387 245 //original
wim 1:0440152c5387 246 /*
wim 1:0440152c5387 247 * Flush characters from SC16IS750 receive buffer.
wim 1:0440152c5387 248 */
wim 1:0440152c5387 249
wim 1:0440152c5387 250 // Note: This may not be the most appropriate flush approach.
wim 1:0440152c5387 251 // It might be better to just flush the UART's buffer
wim 1:0440152c5387 252 // rather than the buffer of the connected device
wim 1:0440152c5387 253 // which is essentially what this does.
wim 1:0440152c5387 254 while(readable() > 0) {
wim 1:0440152c5387 255 getc();
wim 0:d64854a60f95 256 }
wim 0:d64854a60f95 257 #endif
wim 0:d64854a60f95 258
wim 0:d64854a60f95 259 }
wim 0:d64854a60f95 260
wim 0:d64854a60f95 261
wim 1:0440152c5387 262
wim 0:d64854a60f95 263 /**
wim 0:d64854a60f95 264 * Check that UART is connected and operational.
wim 0:d64854a60f95 265 * @param none
wim 0:d64854a60f95 266 * @return bool true when connected, false otherwise
wim 0:d64854a60f95 267 */
wim 0:d64854a60f95 268 bool SC16IS750::connected() {
wim 0:d64854a60f95 269 // Perform read/write test to check if UART is working
wim 0:d64854a60f95 270 const char TEST_CHARACTER = 'H';
wim 0:d64854a60f95 271
wim 0:d64854a60f95 272 this->writeRegister(SPR, TEST_CHARACTER);
wim 0:d64854a60f95 273
wim 0:d64854a60f95 274 return (this->readRegister(SPR) == TEST_CHARACTER);
wim 0:d64854a60f95 275 }
wim 0:d64854a60f95 276
wim 0:d64854a60f95 277
wim 0:d64854a60f95 278
wim 0:d64854a60f95 279 /** Determine if there is a character available to read.
wim 0:d64854a60f95 280 * @return 1 if there is a character available to read, 0 otherwise
wim 0:d64854a60f95 281 */
wim 0:d64854a60f95 282 int SC16IS750::readable() {
wim 0:d64854a60f95 283 return (this->readRegister(LSR) & 0x01);
wim 0:d64854a60f95 284 }
wim 0:d64854a60f95 285
wim 1:0440152c5387 286 /** Determine how many characters are available to read.
wim 0:d64854a60f95 287 * @return int Characters available to read
wim 0:d64854a60f95 288 */
wim 0:d64854a60f95 289 int SC16IS750::readableCount() {
wim 0:d64854a60f95 290 /*
wim 0:d64854a60f95 291 * Get the number of chars (characters) available for reading.
wim 0:d64854a60f95 292 *
wim 0:d64854a60f95 293 * This is data that's already arrived and stored in the receive
wim 0:d64854a60f95 294 * buffer (which holds 64 chars).
wim 0:d64854a60f95 295 */
wim 0:d64854a60f95 296
wim 0:d64854a60f95 297 return (this->readRegister(RXLVL));
wim 0:d64854a60f95 298 }
wim 0:d64854a60f95 299
wim 0:d64854a60f95 300 /** Determine if there is space available to write a character.
wim 0:d64854a60f95 301 * @return 1 if there is a space for a character to write, 0 otherwise
wim 0:d64854a60f95 302 */
wim 0:d64854a60f95 303 int SC16IS750::writable() {
wim 0:d64854a60f95 304 return (this->writableCount() > 0); // Check datasheet for faster version
wim 0:d64854a60f95 305 }
wim 0:d64854a60f95 306
wim 1:0440152c5387 307 /** Determine how much space available for writing characters.
wim 1:0440152c5387 308 * @return int character space available to write
wim 0:d64854a60f95 309 */
wim 0:d64854a60f95 310 int SC16IS750::writableCount() {
wim 0:d64854a60f95 311 /*
wim 1:0440152c5387 312 * Get the available space for writing characters.
wim 0:d64854a60f95 313 *
wim 0:d64854a60f95 314 * This is data that's already stored in the transmit
wim 0:d64854a60f95 315 * buffer (which holds 64 chars).
wim 0:d64854a60f95 316 */
wim 0:d64854a60f95 317
wim 0:d64854a60f95 318 return (this->readRegister(TXLVL));
wim 0:d64854a60f95 319 // return (readRegister(64 - TXLVL)); //Check datasheet
wim 0:d64854a60f95 320 }
wim 0:d64854a60f95 321
wim 0:d64854a60f95 322
wim 1:0440152c5387 323 /**
wim 1:0440152c5387 324 * Read char from UART Bridge.
wim 1:0440152c5387 325 * Acts in the same manner as 'Serial.read()'.
wim 1:0440152c5387 326 * @param none
wim 1:0440152c5387 327 * @return char read or -1 if no data available.
wim 1:0440152c5387 328 */
wim 1:0440152c5387 329 int SC16IS750::getc() {
wim 0:d64854a60f95 330
wim 0:d64854a60f95 331 if (!readable()) {
wim 0:d64854a60f95 332 return -1;
wim 0:d64854a60f95 333 }
wim 0:d64854a60f95 334
wim 0:d64854a60f95 335 return this->readRegister(RHR);
wim 0:d64854a60f95 336 }
wim 0:d64854a60f95 337
wim 1:0440152c5387 338 /**
wim 1:0440152c5387 339 * Write char to UART Bridge. Blocking when no free space in FIFO
wim 1:0440152c5387 340 * @param value char to be written
wim 1:0440152c5387 341 * @return value written
wim 1:0440152c5387 342 */
wim 1:0440152c5387 343 int SC16IS750::putc(int value) {
wim 0:d64854a60f95 344 while (this->readRegister(TXLVL) == 0) {
wim 0:d64854a60f95 345 // Wait for space in TX buffer
wim 1:0440152c5387 346 wait_us(10);
wim 0:d64854a60f95 347 };
wim 0:d64854a60f95 348 this->writeRegister(THR, value);
wim 1:0440152c5387 349
wim 1:0440152c5387 350 return value;
wim 0:d64854a60f95 351 }
wim 0:d64854a60f95 352
wim 0:d64854a60f95 353
wim 0:d64854a60f95 354 void SC16IS750::write(const char *str) {
wim 0:d64854a60f95 355 /*
wim 0:d64854a60f95 356 * Write string to UART.
wim 0:d64854a60f95 357 */
wim 0:d64854a60f95 358 write((const uint8_t *) str, strlen(str));
wim 0:d64854a60f95 359 while (this->readRegister(TXLVL) < 64) {
wim 0:d64854a60f95 360 // Wait for empty TX buffer (slow)
wim 1:0440152c5387 361 wait_us(10);
wim 0:d64854a60f95 362 // (But apparently still not slow enough to ensure delivery.)
wim 0:d64854a60f95 363 };
wim 0:d64854a60f95 364 }
wim 0:d64854a60f95 365
wim 0:d64854a60f95 366 #if ENABLE_BULK_TRANSFERS
wim 0:d64854a60f95 367 void SC16IS750::write(const uint8_t *buffer, size_t size) {
wim 0:d64854a60f95 368 /*
wim 0:d64854a60f95 369
wim 0:d64854a60f95 370 Write buffer to UART.
wim 0:d64854a60f95 371
wim 0:d64854a60f95 372 */
wim 0:d64854a60f95 373 //select();
wim 0:d64854a60f95 374 //transfer(THR); // TODO: Change this when we modify register addresses? (Even though it's 0x00.)
wim 0:d64854a60f95 375
wim 0:d64854a60f95 376 while(size > 16) {
wim 0:d64854a60f95 377 //transfer_bulk(buffer, 16); //ringbuffer?
wim 0:d64854a60f95 378 size -= 16;
wim 0:d64854a60f95 379 buffer += 16;
wim 0:d64854a60f95 380 }
wim 0:d64854a60f95 381 //transfer_bulk(buffer, size);
wim 0:d64854a60f95 382
wim 0:d64854a60f95 383 //deselect();
wim 0:d64854a60f95 384 }
wim 0:d64854a60f95 385 #endif
wim 0:d64854a60f95 386
wim 1:0440152c5387 387 /** Set direction of I/O port pins.
wim 1:0440152c5387 388 * This method is specific to the SPI-I2C UART and not found on the 16750
wim 1:0440152c5387 389 * @param bits Bitpattern for I/O (1=output, 0=input)
wim 1:0440152c5387 390 * @return none
wim 1:0440152c5387 391 */
wim 0:d64854a60f95 392 void SC16IS750::ioSetDirection(unsigned char bits) {
wim 0:d64854a60f95 393 this->writeRegister(IODIR, bits);
wim 0:d64854a60f95 394 }
wim 0:d64854a60f95 395
wim 1:0440152c5387 396 /** Set bits of I/O port pins.
wim 1:0440152c5387 397 * This method is specific to the SPI-I2C UART and not found on the 16750
wim 1:0440152c5387 398 * @param bits Bitpattern for I/O (1= set output bit, 0 = clear output bit)
wim 1:0440152c5387 399 * @return none
wim 1:0440152c5387 400 */
wim 0:d64854a60f95 401 void SC16IS750::ioSetState(unsigned char bits) {
wim 0:d64854a60f95 402 this->writeRegister(IOSTATE, bits);
wim 0:d64854a60f95 403 }
wim 0:d64854a60f95 404
wim 1:0440152c5387 405 /** Get bits of I/O port pins.
wim 1:0440152c5387 406 * This method is specific to the SPI-I2C UART and not found on the 16750
wim 1:0440152c5387 407 * @param none
wim 1:0440152c5387 408 * @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
wim 1:0440152c5387 409 */
wim 1:0440152c5387 410 unsigned char SC16IS750::ioGetState() {
wim 1:0440152c5387 411 return this->readRegister(IOSTATE) ;
wim 1:0440152c5387 412 }
wim 0:d64854a60f95 413
wim 0:d64854a60f95 414
wim 1:0440152c5387 415 /** Software Reset SC16IS750 device.
wim 1:0440152c5387 416 * This method is specific to the SPI-I2C UART and not found on the 16750
wim 1:0440152c5387 417 * @param none
wim 1:0440152c5387 418 * @return none
wim 1:0440152c5387 419 */
wim 1:0440152c5387 420 void SC16IS750::swReset() {
wim 1:0440152c5387 421 this->writeRegister(IOCTRL, IOC_SW_RST);
wim 1:0440152c5387 422 }
wim 1:0440152c5387 423
wim 1:0440152c5387 424
wim 1:0440152c5387 425 //
wim 1:0440152c5387 426 // End Abstract Class Implementation
wim 0:d64854a60f95 427 //
wim 0:d64854a60f95 428
wim 1:0440152c5387 429
wim 1:0440152c5387 430
wim 0:d64854a60f95 431 /** Class SC16IS750_SPI for a converter between SPI and a Serial port
wim 0:d64854a60f95 432 *
wim 1:0440152c5387 433 * @code
wim 1:0440152c5387 434 *
wim 1:0440152c5387 435 * @endcode
wim 1:0440152c5387 436 *
wim 0:d64854a60f95 437 */
wim 0:d64854a60f95 438 SC16IS750_SPI::SC16IS750_SPI (SPI *spi, PinName cs) : _spi(spi), _cs(cs) {
wim 0:d64854a60f95 439 _cs = 1; // deselect
wim 0:d64854a60f95 440
wim 0:d64854a60f95 441 _spi->format(8, 0);
wim 0:d64854a60f95 442 _spi->frequency(1000000);
wim 1:0440152c5387 443 // _spi->frequency(100000); //test
wim 1:0440152c5387 444
wim 1:0440152c5387 445 // Dont call _init() until SPI port has been configured.
wim 1:0440152c5387 446 // That is why _init() is not called in parent Constructor
wim 1:0440152c5387 447 _init();
wim 1:0440152c5387 448
wim 0:d64854a60f95 449 };
wim 0:d64854a60f95 450
wim 0:d64854a60f95 451 /** Write value to internal register.
wim 0:d64854a60f95 452 * Pure virtual, must be declared in derived class.
wim 1:0440152c5387 453 * @param registerAddress The address of the Register (enum RegisterName)
wim 0:d64854a60f95 454 * @param data The 8bit value to write
wim 0:d64854a60f95 455 * @return none
wim 0:d64854a60f95 456 */
wim 0:d64854a60f95 457 void SC16IS750_SPI::writeRegister(RegisterName registerAddress, char data) {
wim 0:d64854a60f95 458
wim 0:d64854a60f95 459 _cs = 0; // select;
wim 0:d64854a60f95 460 _spi->write(registerAddress);
wim 0:d64854a60f95 461 _spi->write(data);
wim 0:d64854a60f95 462 _cs = 1; // deselect;
wim 1:0440152c5387 463
wim 1:0440152c5387 464 #if(0)
wim 0:d64854a60f95 465 //Test only
wim 0:d64854a60f95 466 DigitalOut myled2(LED_GREEN);
wim 0:d64854a60f95 467 myled2 = 0; //LED On
wim 0:d64854a60f95 468 wait(0.2);
wim 0:d64854a60f95 469 myled2 = 1; //LED Off
wim 0:d64854a60f95 470 wait(0.6);
wim 1:0440152c5387 471 #endif
wim 0:d64854a60f95 472 }
wim 0:d64854a60f95 473
wim 0:d64854a60f95 474
wim 0:d64854a60f95 475 /** Read value from internal register.
wim 1:0440152c5387 476 * @param registerAddress The address of the Register (enum RegisterName)
wim 0:d64854a60f95 477 * @return char The 8bit value read from the register
wim 0:d64854a60f95 478 */
wim 0:d64854a60f95 479 char SC16IS750_SPI::readRegister(RegisterName registerAddress) {
wim 0:d64854a60f95 480
wim 0:d64854a60f95 481 // Used in SPI read operations to flush slave's shift register
wim 1:0440152c5387 482 const char SPI_DUMMY_CHAR = 0xFF;
wim 0:d64854a60f95 483
wim 0:d64854a60f95 484 char result;
wim 0:d64854a60f95 485
wim 0:d64854a60f95 486 _cs = 0; // select;
wim 0:d64854a60f95 487 _spi->write(SPI_READ_MODE_FLAG | registerAddress);
wim 1:0440152c5387 488 result = _spi->write(SPI_DUMMY_CHAR);
wim 0:d64854a60f95 489 _cs = 1; // deselect;
wim 0:d64854a60f95 490
wim 0:d64854a60f95 491 return result;
wim 0:d64854a60f95 492 }
wim 0:d64854a60f95 493
wim 0:d64854a60f95 494 //
wim 0:d64854a60f95 495 // End SPI Implementation
wim 1:0440152c5387 496 //
wim 0:d64854a60f95 497
wim 0:d64854a60f95 498
wim 0:d64854a60f95 499 /** Class SC16IS750_I2C for a converter between I2C and a Serial port
wim 0:d64854a60f95 500 *
wim 1:0440152c5387 501 * @code
wim 1:0440152c5387 502 *
wim 1:0440152c5387 503 * @endcode
wim 1:0440152c5387 504 *
wim 0:d64854a60f95 505 */
wim 0:d64854a60f95 506 SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c), _slaveAddress(deviceAddress) {
wim 0:d64854a60f95 507
wim 1:0440152c5387 508 _i2c->frequency(400000);
wim 0:d64854a60f95 509
wim 1:0440152c5387 510 // Dont call _init() until I2C port has been configured.
wim 1:0440152c5387 511 // That is why _init() is not called in parent Constructor
wim 1:0440152c5387 512 _init();
wim 0:d64854a60f95 513 }
wim 0:d64854a60f95 514
wim 0:d64854a60f95 515
wim 0:d64854a60f95 516 /** Write value to internal register.
wim 1:0440152c5387 517 * @param registerAddress The address of the Register (enum RegisterName)
wim 0:d64854a60f95 518 * @param data The 8bit value to write
wim 0:d64854a60f95 519 * @return none
wim 0:d64854a60f95 520 */
wim 0:d64854a60f95 521 void SC16IS750_I2C::writeRegister(RegisterName registerAddress, char data) {
wim 0:d64854a60f95 522 char w[2];
wim 0:d64854a60f95 523
wim 0:d64854a60f95 524 w[0] = registerAddress;
wim 0:d64854a60f95 525 w[1] = data;
wim 0:d64854a60f95 526
wim 0:d64854a60f95 527 _i2c->write( _slaveAddress, w, 2 );
wim 0:d64854a60f95 528 }
wim 0:d64854a60f95 529
wim 0:d64854a60f95 530
wim 0:d64854a60f95 531 /** Read value from internal register.
wim 1:0440152c5387 532 * @param registerAddress The address of the Register (enum RegisterName)
wim 0:d64854a60f95 533 * @return char The 8bit value read from the register
wim 0:d64854a60f95 534 */
wim 0:d64854a60f95 535 char SC16IS750_I2C::readRegister(RegisterName registerAddress) {
wim 0:d64854a60f95 536 /*
wim 0:d64854a60f95 537 * Read char from SC16IS750 register at <registerAddress>.
wim 0:d64854a60f95 538 */
wim 0:d64854a60f95 539 char w[1];
wim 0:d64854a60f95 540 char r[1];
wim 0:d64854a60f95 541
wim 0:d64854a60f95 542 w[0] = registerAddress;
wim 0:d64854a60f95 543
wim 0:d64854a60f95 544 _i2c->write( _slaveAddress, w, 1 );
wim 0:d64854a60f95 545 _i2c->read( _slaveAddress, r, 1 );
wim 0:d64854a60f95 546
wim 0:d64854a60f95 547 return ( r[0] );
wim 0:d64854a60f95 548 }
wim 0:d64854a60f95 549
wim 0:d64854a60f95 550
wim 0:d64854a60f95 551 //
wim 1:0440152c5387 552 // End I2C Implementation
wim 1:0440152c5387 553 //