RETRO ROBOT E

Dependents:   RETRO_ROBOT_SC16IS750E

Fork of SC16IS750 by Wim Huiskamp

Committer:
RLRiedinger
Date:
Mon Mar 02 04:20:07 2015 +0000
Revision:
6:b57b71c0879a
Parent:
5:ff3e57bebb6a
RETRO ROBOT E

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RLRiedinger 6:b57b71c0879a 1 /*
RLRiedinger 6:b57b71c0879a 2 * SC16IS750 I2C or SPI to UART bridge
wim 3:9783b6bde958 3 * v0.1 WH, Nov 2013, Sparkfun WiFly Shield code library alpha 0 used as example, Added I2C I/F and many more methods.
wim 3:9783b6bde958 4 * https://forum.sparkfun.com/viewtopic.php?f=13&t=21846
wim 4:12446ee9f9c8 5 * v0.2 WH, Feb 2014, Added Doxygen Documentation, Added Hardware Reset pin methods.
wim 4:12446ee9f9c8 6 * v0.3 WH, Dec 2014, Added support for SC16IS752 dual UART.
wim 5:ff3e57bebb6a 7 * v0.4 WH, Dec 2014, Added Repeated Start for I2C readRegister(). Set I2C clock at 100kb/s. Fixed and added some comments.
wim 0:d64854a60f95 8 *
wim 0:d64854a60f95 9 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
wim 0:d64854a60f95 10 * and associated documentation files (the "Software"), to deal in the Software without restriction,
wim 0:d64854a60f95 11 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
wim 0:d64854a60f95 12 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
wim 0:d64854a60f95 13 * furnished to do so, subject to the following conditions:
wim 0:d64854a60f95 14 *
wim 0:d64854a60f95 15 * The above copyright notice and this permission notice shall be included in all copies or
wim 0:d64854a60f95 16 * substantial portions of the Software.
wim 0:d64854a60f95 17 *
wim 0:d64854a60f95 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
wim 0:d64854a60f95 19 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
wim 0:d64854a60f95 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
wim 0:d64854a60f95 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 0:d64854a60f95 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
wim 0:d64854a60f95 23 */
RLRiedinger 6:b57b71c0879a 24
RLRiedinger 6:b57b71c0879a 25 #include "mbed.h"
RLRiedinger 6:b57b71c0879a 26 #include "SC16IS750.h"
wim 0:d64854a60f95 27
wim 3:9783b6bde958 28 #define ENABLE_BULK_TRANSFERS 1
wim 3:9783b6bde958 29 #define BULK_BLOCK_LEN 16
RLRiedinger 6:b57b71c0879a 30
RLRiedinger 6:b57b71c0879a 31 /*
RLRiedinger 6:b57b71c0879a 32 * Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port
RLRiedinger 6:b57b71c0879a 33 * Constructor for this Abstract Class is protected
RLRiedinger 6:b57b71c0879a 34 * Supports both SPI and I2C interfaces through derived classes
RLRiedinger 6:b57b71c0879a 35 *
RLRiedinger 6:b57b71c0879a 36 * @code
RLRiedinger 6:b57b71c0879a 37 *
RLRiedinger 6:b57b71c0879a 38 * @endcode
RLRiedinger 6:b57b71c0879a 39 */
wim 0:d64854a60f95 40
RLRiedinger 6:b57b71c0879a 41 SC16IS750::SC16IS750() {
RLRiedinger 6:b57b71c0879a 42
RLRiedinger 6:b57b71c0879a 43 // SC16IS750::SC16IS750() : Serial(NC, NC) { //Fout, mag geen NC zijn
RLRiedinger 6:b57b71c0879a 44 // SC16IS750::SC16IS750() : SerialBase(NC, NC) { //Fout, mag geen NC zijn
RLRiedinger 6:b57b71c0879a 45 // Dont call _init() here since the SPI or I2C port have not yet been configured...
RLRiedinger 6:b57b71c0879a 46 // _init(); // initialize UART registers
wim 1:0440152c5387 47
wim 0:d64854a60f95 48 }
RLRiedinger 6:b57b71c0879a 49
RLRiedinger 6:b57b71c0879a 50 /*
RLRiedinger 6:b57b71c0879a 51 * Set baudrate of the serial port.
RLRiedinger 6:b57b71c0879a 52 * @param baud integer baudrate (4800, 9600 etc)
RLRiedinger 6:b57b71c0879a 53 * @return none
RLRiedinger 6:b57b71c0879a 54 */
wim 0:d64854a60f95 55
RLRiedinger 6:b57b71c0879a 56 void SC16IS750::baud(unsigned long SC16IS750_XTAL_FREQ, int baudrate) {
RLRiedinger 6:b57b71c0879a 57
RLRiedinger 6:b57b71c0879a 58 /*
RLRiedinger 6:b57b71c0879a 59 #define SC16IS750_XTAL_FREQ 14745600UL // On-board crystal (New mid-2010 Version)
RLRiedinger 6:b57b71c0879a 60 #define SC16IS750_XTAL_FREQ 12288000UL // On-board crystal (New mid-2010 Version)
RLRiedinger 6:b57b71c0879a 61 #define SC16IS750_BAUDRATE_DIVISOR(baud) ((SC16IS750_XTAL_FREQ / SC16IS750_PRESCALER)/(baud * 16UL))
RLRiedinger 6:b57b71c0879a 62 */
RLRiedinger 6:b57b71c0879a 63
RLRiedinger 6:b57b71c0879a 64 unsigned long divisor = (SC16IS750_XTAL_FREQ / SC16IS750_PRESCALER) / (baudrate * 16UL);
RLRiedinger 6:b57b71c0879a 65
RLRiedinger 6:b57b71c0879a 66 char lcr_tmp;
RLRiedinger 6:b57b71c0879a 67
RLRiedinger 6:b57b71c0879a 68 _config.baudrate = baudrate; // Save baudrate
RLRiedinger 6:b57b71c0879a 69
RLRiedinger 6:b57b71c0879a 70 lcr_tmp = this->readRegister(LCR); // Read current LCR register
RLRiedinger 6:b57b71c0879a 71 this->writeRegister(LCR, lcr_tmp | LCR_ENABLE_DIV); // Enable Divisor registers
RLRiedinger 6:b57b71c0879a 72 this->writeRegister(DLL, ( divisor & 0xFF)); // write divisor LSB
RLRiedinger 6:b57b71c0879a 73 this->writeRegister(DLH, ((divisor >> 8) & 0xFF)); // write divisor MSB
RLRiedinger 6:b57b71c0879a 74 this->writeRegister(LCR, lcr_tmp); // Restore LCR register, activate regular RBR, THR and IER registers
wim 0:d64854a60f95 75
RLRiedinger 6:b57b71c0879a 76 }
RLRiedinger 6:b57b71c0879a 77
RLRiedinger 6:b57b71c0879a 78 /*
RLRiedinger 6:b57b71c0879a 79 * Set the transmission format used by the serial port.
RLRiedinger 6:b57b71c0879a 80 * @param bits The number of bits in a word (5-8; default = 8)
RLRiedinger 6:b57b71c0879a 81 * @param parity The parity used (Serial::None, Serial::Odd, Serial::Even, Serial::Forced1, Serial::Forced0; default = Serial::None)
RLRiedinger 6:b57b71c0879a 82 * @param stop_bits The number of stop bits (1 or 2; default = 1)
RLRiedinger 6:b57b71c0879a 83 * @return none
RLRiedinger 6:b57b71c0879a 84 */
RLRiedinger 6:b57b71c0879a 85
RLRiedinger 6:b57b71c0879a 86 void SC16IS750::format(int bits, Serial::Parity parity, int stop_bits) {
RLRiedinger 6:b57b71c0879a 87
RLRiedinger 6:b57b71c0879a 88 char lcr_tmp = 0x00;
RLRiedinger 6:b57b71c0879a 89
RLRiedinger 6:b57b71c0879a 90 switch (bits) {
RLRiedinger 6:b57b71c0879a 91
RLRiedinger 6:b57b71c0879a 92 case 5:
RLRiedinger 6:b57b71c0879a 93 lcr_tmp |= LCR_BITS5;
RLRiedinger 6:b57b71c0879a 94 break;
RLRiedinger 6:b57b71c0879a 95
RLRiedinger 6:b57b71c0879a 96 case 6:
RLRiedinger 6:b57b71c0879a 97 lcr_tmp |= LCR_BITS6;
RLRiedinger 6:b57b71c0879a 98 break;
RLRiedinger 6:b57b71c0879a 99
RLRiedinger 6:b57b71c0879a 100 case 7:
RLRiedinger 6:b57b71c0879a 101 lcr_tmp |= LCR_BITS7;
RLRiedinger 6:b57b71c0879a 102 break;
RLRiedinger 6:b57b71c0879a 103
RLRiedinger 6:b57b71c0879a 104 case 8:
RLRiedinger 6:b57b71c0879a 105 lcr_tmp |= LCR_BITS8;
RLRiedinger 6:b57b71c0879a 106 break;
RLRiedinger 6:b57b71c0879a 107
RLRiedinger 6:b57b71c0879a 108 default:
RLRiedinger 6:b57b71c0879a 109 lcr_tmp |= LCR_BITS8;
RLRiedinger 6:b57b71c0879a 110 break;
RLRiedinger 6:b57b71c0879a 111
RLRiedinger 6:b57b71c0879a 112 }
RLRiedinger 6:b57b71c0879a 113
RLRiedinger 6:b57b71c0879a 114 switch (parity) {
RLRiedinger 6:b57b71c0879a 115
RLRiedinger 6:b57b71c0879a 116 case Serial::None:
RLRiedinger 6:b57b71c0879a 117 lcr_tmp |= LCR_NONE;
RLRiedinger 6:b57b71c0879a 118 break;
RLRiedinger 6:b57b71c0879a 119
RLRiedinger 6:b57b71c0879a 120 case Serial::Odd:
RLRiedinger 6:b57b71c0879a 121 lcr_tmp |= LCR_ODD;
RLRiedinger 6:b57b71c0879a 122 break;
RLRiedinger 6:b57b71c0879a 123
RLRiedinger 6:b57b71c0879a 124 case Serial::Even:
RLRiedinger 6:b57b71c0879a 125 lcr_tmp |= LCR_EVEN;
RLRiedinger 6:b57b71c0879a 126 break;
RLRiedinger 6:b57b71c0879a 127
RLRiedinger 6:b57b71c0879a 128 case Serial::Forced1:
RLRiedinger 6:b57b71c0879a 129 lcr_tmp |= LCR_FORCED1;
RLRiedinger 6:b57b71c0879a 130 break;
RLRiedinger 6:b57b71c0879a 131
RLRiedinger 6:b57b71c0879a 132 case Serial::Forced0:
RLRiedinger 6:b57b71c0879a 133 lcr_tmp |= LCR_FORCED0;
RLRiedinger 6:b57b71c0879a 134 break;
RLRiedinger 6:b57b71c0879a 135
RLRiedinger 6:b57b71c0879a 136 default:
RLRiedinger 6:b57b71c0879a 137 lcr_tmp |= LCR_NONE;
RLRiedinger 6:b57b71c0879a 138 break;
RLRiedinger 6:b57b71c0879a 139
RLRiedinger 6:b57b71c0879a 140 }
RLRiedinger 6:b57b71c0879a 141
RLRiedinger 6:b57b71c0879a 142 switch (stop_bits) {
RLRiedinger 6:b57b71c0879a 143
RLRiedinger 6:b57b71c0879a 144 case 1:
RLRiedinger 6:b57b71c0879a 145 lcr_tmp |= LCR_BITS1;
RLRiedinger 6:b57b71c0879a 146 break;
RLRiedinger 6:b57b71c0879a 147
RLRiedinger 6:b57b71c0879a 148 case 2:
RLRiedinger 6:b57b71c0879a 149 lcr_tmp |= LCR_BITS2;
RLRiedinger 6:b57b71c0879a 150 break;
RLRiedinger 6:b57b71c0879a 151
RLRiedinger 6:b57b71c0879a 152 default:
RLRiedinger 6:b57b71c0879a 153 lcr_tmp |= LCR_BITS1;
RLRiedinger 6:b57b71c0879a 154 break;
RLRiedinger 6:b57b71c0879a 155
RLRiedinger 6:b57b71c0879a 156 }
RLRiedinger 6:b57b71c0879a 157
RLRiedinger 6:b57b71c0879a 158 _config.dataformat = lcr_tmp; // Save dataformat
RLRiedinger 6:b57b71c0879a 159
RLRiedinger 6:b57b71c0879a 160 this->writeRegister(LCR, lcr_tmp); // Set LCR register, activate regular RBR, THR and IER registers
wim 0:d64854a60f95 161
wim 0:d64854a60f95 162 };
RLRiedinger 6:b57b71c0879a 163
RLRiedinger 6:b57b71c0879a 164 /*
RLRiedinger 6:b57b71c0879a 165 * Generate a break condition on the serial line
RLRiedinger 6:b57b71c0879a 166 * @param none
RLRiedinger 6:b57b71c0879a 167 * @return none
RLRiedinger 6:b57b71c0879a 168 */
RLRiedinger 6:b57b71c0879a 169
wim 1:0440152c5387 170 void SC16IS750::send_break() {
RLRiedinger 6:b57b71c0879a 171
RLRiedinger 6:b57b71c0879a 172 // Wait for 1.5 frames before clearing the break condition
RLRiedinger 6:b57b71c0879a 173 // This will have different effects on our platforms, but should
RLRiedinger 6:b57b71c0879a 174 // ensure that we keep the break active for at least one frame.
RLRiedinger 6:b57b71c0879a 175 // We consider a full frame (1 start bit + 8 data bits bits +
RLRiedinger 6:b57b71c0879a 176 // 1 parity bit + 2 stop bits = 12 bits) for computation.
RLRiedinger 6:b57b71c0879a 177 // One bit time (in us) = 1000000/_baud
RLRiedinger 6:b57b71c0879a 178 // Twelve bits: 12000000 / baud delay
RLRiedinger 6:b57b71c0879a 179 // 1.5 frames: 18000000 / baud delay
wim 1:0440152c5387 180
RLRiedinger 6:b57b71c0879a 181 set_break(true);
RLRiedinger 6:b57b71c0879a 182 wait_us(18000000 / _config.baudrate);
RLRiedinger 6:b57b71c0879a 183 set_break(false);
RLRiedinger 6:b57b71c0879a 184
RLRiedinger 6:b57b71c0879a 185 }
RLRiedinger 6:b57b71c0879a 186
RLRiedinger 6:b57b71c0879a 187 /*
RLRiedinger 6:b57b71c0879a 188 * Set a break condition on the serial line
RLRiedinger 6:b57b71c0879a 189 * @param enable break condition
RLRiedinger 6:b57b71c0879a 190 * @return none
RLRiedinger 6:b57b71c0879a 191 */
RLRiedinger 6:b57b71c0879a 192
wim 1:0440152c5387 193 void SC16IS750::set_break(bool enable) {
wim 0:d64854a60f95 194
wim 1:0440152c5387 195 if (enable) {
RLRiedinger 6:b57b71c0879a 196
RLRiedinger 6:b57b71c0879a 197 _config.dataformat |= LCR_BRK_ENA; // Save dataformat
RLRiedinger 6:b57b71c0879a 198
RLRiedinger 6:b57b71c0879a 199 } else {
RLRiedinger 6:b57b71c0879a 200
RLRiedinger 6:b57b71c0879a 201 _config.dataformat &= ~LCR_BRK_ENA; // Save dataformat
RLRiedinger 6:b57b71c0879a 202
wim 1:0440152c5387 203 }
wim 1:0440152c5387 204
wim 1:0440152c5387 205 this->writeRegister(LCR, _config.dataformat); // Set LCR register
RLRiedinger 6:b57b71c0879a 206
wim 1:0440152c5387 207 }
RLRiedinger 6:b57b71c0879a 208
RLRiedinger 6:b57b71c0879a 209 /*
RLRiedinger 6:b57b71c0879a 210 * Set the flow control type on the serial port
RLRiedinger 6:b57b71c0879a 211 * Added for compatibility with Serial Class.
RLRiedinger 6:b57b71c0879a 212 * SC16IS750 supports only Flow, Pins can not be selected.
RLRiedinger 6:b57b71c0879a 213 * This method sets hardware flow control levels. SC16IS750 supports XON/XOFF, but this is not implemented.
RLRiedinger 6:b57b71c0879a 214 *
RLRiedinger 6:b57b71c0879a 215 * @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
RLRiedinger 6:b57b71c0879a 216 * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
RLRiedinger 6:b57b71c0879a 217 * @param flow2 the second flow control pin (CTS for RTSCTS)
RLRiedinger 6:b57b71c0879a 218 * @return none
RLRiedinger 6:b57b71c0879a 219 */
wim 1:0440152c5387 220
RLRiedinger 6:b57b71c0879a 221 void SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) {
RLRiedinger 6:b57b71c0879a 222
RLRiedinger 6:b57b71c0879a 223 char lcr_tmp;
RLRiedinger 6:b57b71c0879a 224 char efr_tmp = 0x00;
RLRiedinger 6:b57b71c0879a 225
RLRiedinger 6:b57b71c0879a 226 // We need to enable flow control to prevent overflow of buffers and
RLRiedinger 6:b57b71c0879a 227 // lose data when used with fast devices like the WiFly.
RLRiedinger 6:b57b71c0879a 228
RLRiedinger 6:b57b71c0879a 229 switch (type) {
RLRiedinger 6:b57b71c0879a 230
RLRiedinger 6:b57b71c0879a 231 case Disabled:
RLRiedinger 6:b57b71c0879a 232 break;
RLRiedinger 6:b57b71c0879a 233
RLRiedinger 6:b57b71c0879a 234 case RTS:
RLRiedinger 6:b57b71c0879a 235 efr_tmp = EFR_ENABLE_RTS;
RLRiedinger 6:b57b71c0879a 236 break;
RLRiedinger 6:b57b71c0879a 237
RLRiedinger 6:b57b71c0879a 238 case CTS:
RLRiedinger 6:b57b71c0879a 239 efr_tmp = EFR_ENABLE_CTS;
RLRiedinger 6:b57b71c0879a 240 break;
RLRiedinger 6:b57b71c0879a 241
RLRiedinger 6:b57b71c0879a 242 case RTSCTS:
RLRiedinger 6:b57b71c0879a 243 efr_tmp = EFR_ENABLE_RTS | EFR_ENABLE_CTS;
RLRiedinger 6:b57b71c0879a 244 break;
RLRiedinger 6:b57b71c0879a 245
RLRiedinger 6:b57b71c0879a 246 default:
RLRiedinger 6:b57b71c0879a 247 break;
RLRiedinger 6:b57b71c0879a 248
RLRiedinger 6:b57b71c0879a 249 }
RLRiedinger 6:b57b71c0879a 250
RLRiedinger 6:b57b71c0879a 251 //Save flowcontrol mode and enable enhanced functions
RLRiedinger 6:b57b71c0879a 252
RLRiedinger 6:b57b71c0879a 253 _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS;
RLRiedinger 6:b57b71c0879a 254
RLRiedinger 6:b57b71c0879a 255 lcr_tmp = this->readRegister(LCR); // save LRC register
RLRiedinger 6:b57b71c0879a 256 this->writeRegister(LCR, LCR_ENABLE_ENHANCED_FUNCTIONS); // write magic number 0xBF to enable access to EFR register
RLRiedinger 6:b57b71c0879a 257 this->writeRegister(EFR, _config.flowctrl); // set flow and enable enhanced functions
RLRiedinger 6:b57b71c0879a 258 this->writeRegister(LCR, lcr_tmp); // restore LCR register
wim 2:76cb93b511f2 259
RLRiedinger 6:b57b71c0879a 260 }
RLRiedinger 6:b57b71c0879a 261
RLRiedinger 6:b57b71c0879a 262 /*
RLRiedinger 6:b57b71c0879a 263 * Set the RX FIFO flow control levels
RLRiedinger 6:b57b71c0879a 264 * This method sets hardware flow control levels. SC16IS750 supports XON/XOFF, but this is not implemented.
RLRiedinger 6:b57b71c0879a 265 * Should be called BEFORE Auto RTS is enabled.
RLRiedinger 6:b57b71c0879a 266 *
RLRiedinger 6:b57b71c0879a 267 * @param resume trigger level to resume transmission (0..15, meaning 0-60 with a granularity of 4)
RLRiedinger 6:b57b71c0879a 268 * @param halt trigger level to resume transmission (0..15, meaning 0-60 with granularity of 4)
RLRiedinger 6:b57b71c0879a 269 * @return none
RLRiedinger 6:b57b71c0879a 270 */
RLRiedinger 6:b57b71c0879a 271
wim 2:76cb93b511f2 272 void SC16IS750::set_flow_triggers(int resume, int halt) {
RLRiedinger 6:b57b71c0879a 273
RLRiedinger 6:b57b71c0879a 274 // sanity checks
RLRiedinger 6:b57b71c0879a 275
RLRiedinger 6:b57b71c0879a 276 halt = halt & 0x0F;
RLRiedinger 6:b57b71c0879a 277 resume = resume & 0x0F;
RLRiedinger 6:b57b71c0879a 278
RLRiedinger 6:b57b71c0879a 279 if (halt <= resume) {
RLRiedinger 6:b57b71c0879a 280
RLRiedinger 6:b57b71c0879a 281 halt = TCR_HALT_DEFAULT;
RLRiedinger 6:b57b71c0879a 282 resume = TCR_RESUME_DEFAULT;
RLRiedinger 6:b57b71c0879a 283
RLRiedinger 6:b57b71c0879a 284 }
RLRiedinger 6:b57b71c0879a 285
RLRiedinger 6:b57b71c0879a 286 // Note: TCR accessible only when EFR[4] = 1 and MCR[2] = 1
RLRiedinger 6:b57b71c0879a 287
RLRiedinger 6:b57b71c0879a 288 this->writeRegister(TCR, (resume << 4) | halt); // set TCR register
RLRiedinger 6:b57b71c0879a 289
wim 2:76cb93b511f2 290 }
RLRiedinger 6:b57b71c0879a 291
RLRiedinger 6:b57b71c0879a 292 /*
RLRiedinger 6:b57b71c0879a 293 * Set the Modem Control register
RLRiedinger 6:b57b71c0879a 294 * This method sets prescaler, enables TCR and TLR
RLRiedinger 6:b57b71c0879a 295 *
RLRiedinger 6:b57b71c0879a 296 * @param none
RLRiedinger 6:b57b71c0879a 297 * @return none
RLRiedinger 6:b57b71c0879a 298 */
wim 2:76cb93b511f2 299
wim 2:76cb93b511f2 300 void SC16IS750::set_modem_control() {
RLRiedinger 6:b57b71c0879a 301
RLRiedinger 6:b57b71c0879a 302 // Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set
RLRiedinger 6:b57b71c0879a 303
RLRiedinger 6:b57b71c0879a 304 if (SC16IS750_PRESCALER == SC16IS750_PRESCALER_1) { // Default prescaler after reset
RLRiedinger 6:b57b71c0879a 305
RLRiedinger 6:b57b71c0879a 306 this->writeRegister(MCR, MCR_PRESCALE_1 | MCR_ENABLE_TCR_TLR);
RLRiedinger 6:b57b71c0879a 307
RLRiedinger 6:b57b71c0879a 308 } else {
RLRiedinger 6:b57b71c0879a 309
RLRiedinger 6:b57b71c0879a 310 this->writeRegister(MCR, MCR_PRESCALE_4 | MCR_ENABLE_TCR_TLR);
RLRiedinger 6:b57b71c0879a 311
RLRiedinger 6:b57b71c0879a 312 }
wim 2:76cb93b511f2 313
wim 2:76cb93b511f2 314 }
RLRiedinger 6:b57b71c0879a 315
RLRiedinger 6:b57b71c0879a 316 /** Initialize internal registers
wim 1:0440152c5387 317 * Should be in protection section. Public for testing purposes
wim 1:0440152c5387 318 * If initialisation fails this method does not return.
wim 1:0440152c5387 319 * @param none
wim 1:0440152c5387 320 * @return none
wim 1:0440152c5387 321 */
wim 4:12446ee9f9c8 322
RLRiedinger 6:b57b71c0879a 323 void SC16IS750::_init() {
RLRiedinger 6:b57b71c0879a 324
RLRiedinger 6:b57b71c0879a 325 // Initialize SC16IS750
RLRiedinger 6:b57b71c0879a 326
RLRiedinger 6:b57b71c0879a 327 // Hardware reset, assuming there is a HW Reset pin this->hwReset();
RLRiedinger 6:b57b71c0879a 328
RLRiedinger 6:b57b71c0879a 329 // Software reset, assuming there is no access to the HW Reset pin
RLRiedinger 6:b57b71c0879a 330
RLRiedinger 6:b57b71c0879a 331 swReset();
RLRiedinger 6:b57b71c0879a 332
RLRiedinger 6:b57b71c0879a 333 // Set default baudrate (depends on prescaler) and save in _config DLL / DLH
RLRiedinger 6:b57b71c0879a 334
RLRiedinger 6:b57b71c0879a 335 baud();
RLRiedinger 6:b57b71c0879a 336
RLRiedinger 6:b57b71c0879a 337 // Set default dataformat and save in _config LCR
RLRiedinger 6:b57b71c0879a 338
RLRiedinger 6:b57b71c0879a 339 format();
RLRiedinger 6:b57b71c0879a 340
RLRiedinger 6:b57b71c0879a 341 // Set dataflow mode and Enables enhanced functions. Save in _config EFR
RLRiedinger 6:b57b71c0879a 342
RLRiedinger 6:b57b71c0879a 343 set_flow_control();
RLRiedinger 6:b57b71c0879a 344
RLRiedinger 6:b57b71c0879a 345 // FIFO control, sets TX and RX IRQ trigger levels and enables FIFO and save in _config
RLRiedinger 6:b57b71c0879a 346 // Note FCR[5:4] only accessible when EFR[4] is set (enhanced functions enable) FCR, TLR
RLRiedinger 6:b57b71c0879a 347
RLRiedinger 6:b57b71c0879a 348 set_fifo_control();
RLRiedinger 6:b57b71c0879a 349
RLRiedinger 6:b57b71c0879a 350 flush();
RLRiedinger 6:b57b71c0879a 351
RLRiedinger 6:b57b71c0879a 352 // Modem control, sets prescaler, enable TCR and TLR
RLRiedinger 6:b57b71c0879a 353 // Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set (enhanced functions enable)
RLRiedinger 6:b57b71c0879a 354
RLRiedinger 6:b57b71c0879a 355 set_modem_control();
RLRiedinger 6:b57b71c0879a 356
RLRiedinger 6:b57b71c0879a 357 // Set RTS trigger levels
RLRiedinger 6:b57b71c0879a 358 // Note TCR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set
RLRiedinger 6:b57b71c0879a 359
RLRiedinger 6:b57b71c0879a 360 set_flow_triggers();
RLRiedinger 6:b57b71c0879a 361
RLRiedinger 6:b57b71c0879a 362 // Set default break condition and save in _config LCR
RLRiedinger 6:b57b71c0879a 363
RLRiedinger 6:b57b71c0879a 364 // set_break();
RLRiedinger 6:b57b71c0879a 365
RLRiedinger 6:b57b71c0879a 366 // The UART bridge should now be successfully initialized.
RLRiedinger 6:b57b71c0879a 367
RLRiedinger 6:b57b71c0879a 368 // Test if UART bridge is present and initialized
RLRiedinger 6:b57b71c0879a 369
RLRiedinger 6:b57b71c0879a 370 if (!connected()) {
RLRiedinger 6:b57b71c0879a 371
RLRiedinger 6:b57b71c0879a 372 #if (0)
RLRiedinger 6:b57b71c0879a 373
RLRiedinger 6:b57b71c0879a 374 // Lock up if we fail to initialize UART bridge.
RLRiedinger 6:b57b71c0879a 375
RLRiedinger 6:b57b71c0879a 376 while(1){};
RLRiedinger 6:b57b71c0879a 377
RLRiedinger 6:b57b71c0879a 378 #else
RLRiedinger 6:b57b71c0879a 379
RLRiedinger 6:b57b71c0879a 380 // printf("Failed to initialize UART bridge\r\n");
RLRiedinger 6:b57b71c0879a 381
RLRiedinger 6:b57b71c0879a 382 #endif
RLRiedinger 6:b57b71c0879a 383
RLRiedinger 6:b57b71c0879a 384 } else {
RLRiedinger 6:b57b71c0879a 385
RLRiedinger 6:b57b71c0879a 386 // printf("Initialized UART bridge!\r\n");
RLRiedinger 6:b57b71c0879a 387
RLRiedinger 6:b57b71c0879a 388 }
RLRiedinger 6:b57b71c0879a 389
RLRiedinger 6:b57b71c0879a 390 }
RLRiedinger 6:b57b71c0879a 391
RLRiedinger 6:b57b71c0879a 392 /*
RLRiedinger 6:b57b71c0879a 393 * FIFO control, sets TX and RX IRQ trigger levels and enables FIFO and save in _config
RLRiedinger 6:b57b71c0879a 394 * Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable)
RLRiedinger 6:b57b71c0879a 395 * Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set
RLRiedinger 6:b57b71c0879a 396 * @param none
RLRiedinger 6:b57b71c0879a 397 * @return none
RLRiedinger 6:b57b71c0879a 398 */
RLRiedinger 6:b57b71c0879a 399
RLRiedinger 6:b57b71c0879a 400 void SC16IS750::set_fifo_control() {
RLRiedinger 6:b57b71c0879a 401
RLRiedinger 6:b57b71c0879a 402 // Set default fifoformat FCR
RLRiedinger 6:b57b71c0879a 403
RLRiedinger 6:b57b71c0879a 404 _config.fifoenable = true;
RLRiedinger 6:b57b71c0879a 405
RLRiedinger 6:b57b71c0879a 406 // Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable)
RLRiedinger 6:b57b71c0879a 407 // _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_56;
RLRiedinger 6:b57b71c0879a 408
RLRiedinger 6:b57b71c0879a 409 _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_8; // Default
RLRiedinger 6:b57b71c0879a 410
RLRiedinger 6:b57b71c0879a 411 if (_config.fifoenable) {
RLRiedinger 6:b57b71c0879a 412
RLRiedinger 6:b57b71c0879a 413 // Enable FIFO mode and set FIFO control values
RLRiedinger 6:b57b71c0879a 414
RLRiedinger 6:b57b71c0879a 415 this->writeRegister(FCR, _config.fifoformat | FCR_ENABLE_FIFO);
RLRiedinger 6:b57b71c0879a 416
RLRiedinger 6:b57b71c0879a 417 } else {
RLRiedinger 6:b57b71c0879a 418
RLRiedinger 6:b57b71c0879a 419 // Disable FIFO mode and set FIFO control values
RLRiedinger 6:b57b71c0879a 420
RLRiedinger 6:b57b71c0879a 421 this->writeRegister(FCR, _config.fifoformat);
RLRiedinger 6:b57b71c0879a 422
RLRiedinger 6:b57b71c0879a 423 }
RLRiedinger 6:b57b71c0879a 424
RLRiedinger 6:b57b71c0879a 425 // Set Trigger level register TLR for RX and TX interrupt generation
RLRiedinger 6:b57b71c0879a 426 // Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set
RLRiedinger 6:b57b71c0879a 427 // TRL Trigger levels for RX and TX are 0..15, meaning 0-60 with a granularity of 4 chars
RLRiedinger 6:b57b71c0879a 428 // When TLR for RX or TX are 'Zero' the corresponding values in FCR are used. The FCR settings
RLRiedinger 6:b57b71c0879a 429 // have less resolution (only 4 levels) so TLR is considered an enhanced function.
RLRiedinger 6:b57b71c0879a 430
RLRiedinger 6:b57b71c0879a 431 this->writeRegister(TLR, 0x00); // Use FCR Levels
RLRiedinger 6:b57b71c0879a 432
RLRiedinger 6:b57b71c0879a 433 // this->writeRegister(TLR, (TLR_RX_DEFAULT << 4) | TLR_TX_DEFAULT); // Use Default enhanced levels
RLRiedinger 6:b57b71c0879a 434
RLRiedinger 6:b57b71c0879a 435 }
RLRiedinger 6:b57b71c0879a 436
RLRiedinger 6:b57b71c0879a 437 /*
RLRiedinger 6:b57b71c0879a 438 * Flush the UART FIFOs while maintaining current FIFO mode.
RLRiedinger 6:b57b71c0879a 439 * @param none
RLRiedinger 6:b57b71c0879a 440 * @return none
RLRiedinger 6:b57b71c0879a 441 */
wim 0:d64854a60f95 442
RLRiedinger 6:b57b71c0879a 443 void SC16IS750::flush() {
RLRiedinger 6:b57b71c0879a 444
RLRiedinger 6:b57b71c0879a 445 // FCR is Write Only, use saved _config
RLRiedinger 6:b57b71c0879a 446
RLRiedinger 6:b57b71c0879a 447 // Reset TXFIFO, reset RXFIFO, non FIFO mode
RLRiedinger 6:b57b71c0879a 448
RLRiedinger 6:b57b71c0879a 449 this->writeRegister(FCR, FCR_TX_FIFO_RST | FCR_RX_FIFO_RST);
RLRiedinger 6:b57b71c0879a 450
RLRiedinger 6:b57b71c0879a 451 if (_config.fifoenable) {
RLRiedinger 6:b57b71c0879a 452
RLRiedinger 6:b57b71c0879a 453 // Enable FIFO mode and set FIFO control values
RLRiedinger 6:b57b71c0879a 454
RLRiedinger 6:b57b71c0879a 455 this->writeRegister(FCR, _config.fifoformat | FCR_ENABLE_FIFO);
RLRiedinger 6:b57b71c0879a 456
RLRiedinger 6:b57b71c0879a 457 } else {
RLRiedinger 6:b57b71c0879a 458
RLRiedinger 6:b57b71c0879a 459 // Disable FIFO mode and set FIFO control values
RLRiedinger 6:b57b71c0879a 460
RLRiedinger 6:b57b71c0879a 461 this->writeRegister(FCR, _config.fifoformat);
RLRiedinger 6:b57b71c0879a 462
RLRiedinger 6:b57b71c0879a 463 }
RLRiedinger 6:b57b71c0879a 464
RLRiedinger 6:b57b71c0879a 465 #if (0)
RLRiedinger 6:b57b71c0879a 466
RLRiedinger 6:b57b71c0879a 467 // original
RLRiedinger 6:b57b71c0879a 468
RLRiedinger 6:b57b71c0879a 469 /*
RLRiedinger 6:b57b71c0879a 470 * Flush characters from SC16IS750 receive buffer.
RLRiedinger 6:b57b71c0879a 471 */
RLRiedinger 6:b57b71c0879a 472
RLRiedinger 6:b57b71c0879a 473 // Note: This may not be the most appropriate flush approach.
RLRiedinger 6:b57b71c0879a 474 // It might be better to just flush the UART's buffer
RLRiedinger 6:b57b71c0879a 475 // rather than the buffer of the connected device
RLRiedinger 6:b57b71c0879a 476 // which is essentially what this does.
RLRiedinger 6:b57b71c0879a 477
RLRiedinger 6:b57b71c0879a 478 while(readable() > 0) {
RLRiedinger 6:b57b71c0879a 479
RLRiedinger 6:b57b71c0879a 480 getc();
RLRiedinger 6:b57b71c0879a 481
RLRiedinger 6:b57b71c0879a 482 }
RLRiedinger 6:b57b71c0879a 483
RLRiedinger 6:b57b71c0879a 484 #endif
RLRiedinger 6:b57b71c0879a 485
RLRiedinger 6:b57b71c0879a 486 }
RLRiedinger 6:b57b71c0879a 487
RLRiedinger 6:b57b71c0879a 488 /*
RLRiedinger 6:b57b71c0879a 489 *
RLRiedinger 6:b57b71c0879a 490 * Check that UART is connected and operational.
RLRiedinger 6:b57b71c0879a 491 * @param none
RLRiedinger 6:b57b71c0879a 492 * @return bool true when connected, false otherwise
RLRiedinger 6:b57b71c0879a 493 */
RLRiedinger 6:b57b71c0879a 494
RLRiedinger 6:b57b71c0879a 495 bool SC16IS750::connected() {
RLRiedinger 6:b57b71c0879a 496
RLRiedinger 6:b57b71c0879a 497 // Perform read/write test to check if UART is working
RLRiedinger 6:b57b71c0879a 498
RLRiedinger 6:b57b71c0879a 499 const char TEST_CHARACTER = 'H';
RLRiedinger 6:b57b71c0879a 500
RLRiedinger 6:b57b71c0879a 501 this->writeRegister(SPR, TEST_CHARACTER);
RLRiedinger 6:b57b71c0879a 502
RLRiedinger 6:b57b71c0879a 503 return (this->readRegister(SPR) == TEST_CHARACTER);
wim 0:d64854a60f95 504
RLRiedinger 6:b57b71c0879a 505 }
RLRiedinger 6:b57b71c0879a 506
RLRiedinger 6:b57b71c0879a 507 /*
RLRiedinger 6:b57b71c0879a 508 * Determine if there is a character available to read.
RLRiedinger 6:b57b71c0879a 509 * This is data that's already arrived and stored in the receive
RLRiedinger 6:b57b71c0879a 510 * buffer (which holds 64 chars).
RLRiedinger 6:b57b71c0879a 511 *
RLRiedinger 6:b57b71c0879a 512 * @return 1 if there is a character available to read, 0 otherwise
RLRiedinger 6:b57b71c0879a 513 */
RLRiedinger 6:b57b71c0879a 514
RLRiedinger 6:b57b71c0879a 515 int SC16IS750::readable() {
wim 2:76cb93b511f2 516
RLRiedinger 6:b57b71c0879a 517 // if (this->readableCount() > 0) { // Check count
RLRiedinger 6:b57b71c0879a 518
RLRiedinger 6:b57b71c0879a 519 if (this->readRegister(LSR) & LSR_DR) { // Data in Receiver Bit, at least one character waiting
RLRiedinger 6:b57b71c0879a 520
RLRiedinger 6:b57b71c0879a 521 return 1;
RLRiedinger 6:b57b71c0879a 522
RLRiedinger 6:b57b71c0879a 523 } else {
RLRiedinger 6:b57b71c0879a 524
RLRiedinger 6:b57b71c0879a 525 return 0;
RLRiedinger 6:b57b71c0879a 526
RLRiedinger 6:b57b71c0879a 527 }
RLRiedinger 6:b57b71c0879a 528
RLRiedinger 6:b57b71c0879a 529 }
RLRiedinger 6:b57b71c0879a 530
RLRiedinger 6:b57b71c0879a 531 /*
RLRiedinger 6:b57b71c0879a 532 * Determine how many characters are available to read.
RLRiedinger 6:b57b71c0879a 533 * This is data that's already arrived and stored in the receive
RLRiedinger 6:b57b71c0879a 534 * buffer (which holds 64 chars).
RLRiedinger 6:b57b71c0879a 535 *
RLRiedinger 6:b57b71c0879a 536 * @return int Characters available to read
RLRiedinger 6:b57b71c0879a 537 */
RLRiedinger 6:b57b71c0879a 538
RLRiedinger 6:b57b71c0879a 539 int SC16IS750::readableCount() {
RLRiedinger 6:b57b71c0879a 540
RLRiedinger 6:b57b71c0879a 541 return (this->readRegister(RXLVL));
RLRiedinger 6:b57b71c0879a 542
RLRiedinger 6:b57b71c0879a 543 }
RLRiedinger 6:b57b71c0879a 544
RLRiedinger 6:b57b71c0879a 545 /*
RLRiedinger 6:b57b71c0879a 546 * Determine if there is space available to write a character.
RLRiedinger 6:b57b71c0879a 547 * @return 1 if there is a space for a character to write, 0 otherwise
RLRiedinger 6:b57b71c0879a 548 */
RLRiedinger 6:b57b71c0879a 549
RLRiedinger 6:b57b71c0879a 550 int SC16IS750::writable() {
RLRiedinger 6:b57b71c0879a 551
RLRiedinger 6:b57b71c0879a 552 // if ((this->writableCount() > 0) { // Check count
RLRiedinger 6:b57b71c0879a 553
RLRiedinger 6:b57b71c0879a 554 if (this->readRegister(LSR) & LSR_THRE) { // THR Empty, space for at least one character
RLRiedinger 6:b57b71c0879a 555
RLRiedinger 6:b57b71c0879a 556 return 1;
RLRiedinger 6:b57b71c0879a 557
RLRiedinger 6:b57b71c0879a 558 } else {
RLRiedinger 6:b57b71c0879a 559
RLRiedinger 6:b57b71c0879a 560 return 0;
RLRiedinger 6:b57b71c0879a 561
RLRiedinger 6:b57b71c0879a 562 }
RLRiedinger 6:b57b71c0879a 563
RLRiedinger 6:b57b71c0879a 564 }
RLRiedinger 6:b57b71c0879a 565
RLRiedinger 6:b57b71c0879a 566 /*
RLRiedinger 6:b57b71c0879a 567 * Determine how much space available for writing characters.
RLRiedinger 6:b57b71c0879a 568 * This considers data that's already stored in the transmit
RLRiedinger 6:b57b71c0879a 569 * buffer (which holds 64 chars).
RLRiedinger 6:b57b71c0879a 570 *
RLRiedinger 6:b57b71c0879a 571 * @return int character space available to write
RLRiedinger 6:b57b71c0879a 572 */
RLRiedinger 6:b57b71c0879a 573
RLRiedinger 6:b57b71c0879a 574 int SC16IS750::writableCount() {
RLRiedinger 6:b57b71c0879a 575
RLRiedinger 6:b57b71c0879a 576 return (this->readRegister(TXLVL)); // TX Level
RLRiedinger 6:b57b71c0879a 577
RLRiedinger 6:b57b71c0879a 578 }
RLRiedinger 6:b57b71c0879a 579
RLRiedinger 6:b57b71c0879a 580 /*
RLRiedinger 6:b57b71c0879a 581 * Read char from UART Bridge.
RLRiedinger 6:b57b71c0879a 582 * Acts in the same manner as 'Serial.read()'.
RLRiedinger 6:b57b71c0879a 583 * @param none
RLRiedinger 6:b57b71c0879a 584 * @return char read or -1 if no data available.
RLRiedinger 6:b57b71c0879a 585 */
RLRiedinger 6:b57b71c0879a 586
RLRiedinger 6:b57b71c0879a 587 int SC16IS750::getc() {
wim 2:76cb93b511f2 588
RLRiedinger 6:b57b71c0879a 589 if (!readable()) {
RLRiedinger 6:b57b71c0879a 590
RLRiedinger 6:b57b71c0879a 591 return -1;
RLRiedinger 6:b57b71c0879a 592
RLRiedinger 6:b57b71c0879a 593 } else {
RLRiedinger 6:b57b71c0879a 594
RLRiedinger 6:b57b71c0879a 595 return this->readRegister(RHR);
RLRiedinger 6:b57b71c0879a 596
RLRiedinger 6:b57b71c0879a 597 }
RLRiedinger 6:b57b71c0879a 598
RLRiedinger 6:b57b71c0879a 599 }
RLRiedinger 6:b57b71c0879a 600
RLRiedinger 6:b57b71c0879a 601 /*
RLRiedinger 6:b57b71c0879a 602 *
RLRiedinger 6:b57b71c0879a 603 * Write char to UART Bridge. Blocking when no free space in FIFO
RLRiedinger 6:b57b71c0879a 604 * @param value char to be written
RLRiedinger 6:b57b71c0879a 605 * @return value written
RLRiedinger 6:b57b71c0879a 606 */
RLRiedinger 6:b57b71c0879a 607
RLRiedinger 6:b57b71c0879a 608 int SC16IS750::putc(int value) {
RLRiedinger 6:b57b71c0879a 609
RLRiedinger 6:b57b71c0879a 610 while (this->readRegister(TXLVL) == 0) {
RLRiedinger 6:b57b71c0879a 611
RLRiedinger 6:b57b71c0879a 612 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 613
RLRiedinger 6:b57b71c0879a 614 wait_us(10);
RLRiedinger 6:b57b71c0879a 615
RLRiedinger 6:b57b71c0879a 616 }
RLRiedinger 6:b57b71c0879a 617
RLRiedinger 6:b57b71c0879a 618 this->writeRegister(THR, value);
RLRiedinger 6:b57b71c0879a 619
RLRiedinger 6:b57b71c0879a 620 return value;
wim 2:76cb93b511f2 621
RLRiedinger 6:b57b71c0879a 622 }
RLRiedinger 6:b57b71c0879a 623
RLRiedinger 6:b57b71c0879a 624 /*
RLRiedinger 6:b57b71c0879a 625 *
RLRiedinger 6:b57b71c0879a 626 * Write char string to UART Bridge. Blocking when no free space in FIFO
RLRiedinger 6:b57b71c0879a 627 * @param *str char string to be written
RLRiedinger 6:b57b71c0879a 628 * @return none
RLRiedinger 6:b57b71c0879a 629 */
RLRiedinger 6:b57b71c0879a 630
RLRiedinger 6:b57b71c0879a 631 void SC16IS750::writeString(const char *str) {
RLRiedinger 6:b57b71c0879a 632
RLRiedinger 6:b57b71c0879a 633 #if ENABLE_BULK_TRANSFERS
RLRiedinger 6:b57b71c0879a 634
RLRiedinger 6:b57b71c0879a 635 int len, idx;
RLRiedinger 6:b57b71c0879a 636
RLRiedinger 6:b57b71c0879a 637 len = strlen(str);
RLRiedinger 6:b57b71c0879a 638
RLRiedinger 6:b57b71c0879a 639 // Write blocks of BULK_BLOCK_LEN
RLRiedinger 6:b57b71c0879a 640
RLRiedinger 6:b57b71c0879a 641 while (len > BULK_BLOCK_LEN) {
RLRiedinger 6:b57b71c0879a 642
RLRiedinger 6:b57b71c0879a 643 while(this->readRegister(TXLVL) < BULK_BLOCK_LEN) {
RLRiedinger 6:b57b71c0879a 644
RLRiedinger 6:b57b71c0879a 645 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 646
RLRiedinger 6:b57b71c0879a 647 wait_us(10);
RLRiedinger 6:b57b71c0879a 648
RLRiedinger 6:b57b71c0879a 649 }
RLRiedinger 6:b57b71c0879a 650
RLRiedinger 6:b57b71c0879a 651 // Write a block of BULK_BLOCK_LEN bytes
RLRiedinger 6:b57b71c0879a 652
RLRiedinger 6:b57b71c0879a 653 #if (0)
RLRiedinger 6:b57b71c0879a 654
RLRiedinger 6:b57b71c0879a 655 // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
RLRiedinger 6:b57b71c0879a 656
RLRiedinger 6:b57b71c0879a 657 for (idx = 0; idx < BULK_BLOCK_LEN; idx++) {
RLRiedinger 6:b57b71c0879a 658
RLRiedinger 6:b57b71c0879a 659 this->writeRegister(THR, str[idx]);
RLRiedinger 6:b57b71c0879a 660
RLRiedinger 6:b57b71c0879a 661 }
RLRiedinger 6:b57b71c0879a 662
RLRiedinger 6:b57b71c0879a 663 #else
RLRiedinger 6:b57b71c0879a 664
RLRiedinger 6:b57b71c0879a 665 // Optimized
RLRiedinger 6:b57b71c0879a 666
RLRiedinger 6:b57b71c0879a 667 this->writeDataBlock(str, BULK_BLOCK_LEN);
RLRiedinger 6:b57b71c0879a 668
RLRiedinger 6:b57b71c0879a 669 #endif
RLRiedinger 6:b57b71c0879a 670
RLRiedinger 6:b57b71c0879a 671 len -= BULK_BLOCK_LEN;
RLRiedinger 6:b57b71c0879a 672 str += BULK_BLOCK_LEN;
RLRiedinger 6:b57b71c0879a 673
RLRiedinger 6:b57b71c0879a 674 }
RLRiedinger 6:b57b71c0879a 675
RLRiedinger 6:b57b71c0879a 676 // Write remaining bytes
RLRiedinger 6:b57b71c0879a 677 // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
RLRiedinger 6:b57b71c0879a 678
RLRiedinger 6:b57b71c0879a 679 for (idx = 0; idx < len; idx++) {
RLRiedinger 6:b57b71c0879a 680
RLRiedinger 6:b57b71c0879a 681 while (this->readRegister(TXLVL) == 0) {
RLRiedinger 6:b57b71c0879a 682
RLRiedinger 6:b57b71c0879a 683 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 684
RLRiedinger 6:b57b71c0879a 685 wait_us(10);
RLRiedinger 6:b57b71c0879a 686
RLRiedinger 6:b57b71c0879a 687 }
RLRiedinger 6:b57b71c0879a 688
RLRiedinger 6:b57b71c0879a 689 this->writeRegister(THR, str[idx]);
RLRiedinger 6:b57b71c0879a 690
RLRiedinger 6:b57b71c0879a 691 }
RLRiedinger 6:b57b71c0879a 692
RLRiedinger 6:b57b71c0879a 693 #else
RLRiedinger 6:b57b71c0879a 694
RLRiedinger 6:b57b71c0879a 695 // Single writes instead of bulktransfer
RLRiedinger 6:b57b71c0879a 696
RLRiedinger 6:b57b71c0879a 697 int len, idx;
RLRiedinger 6:b57b71c0879a 698
RLRiedinger 6:b57b71c0879a 699 len = strlen(str);
RLRiedinger 6:b57b71c0879a 700
RLRiedinger 6:b57b71c0879a 701 for (idx = 0; idx < len; idx++) {
RLRiedinger 6:b57b71c0879a 702
RLRiedinger 6:b57b71c0879a 703 while (this->readRegister(TXLVL) == 0) {
RLRiedinger 6:b57b71c0879a 704
RLRiedinger 6:b57b71c0879a 705 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 706
RLRiedinger 6:b57b71c0879a 707 wait_us(10);
RLRiedinger 6:b57b71c0879a 708
RLRiedinger 6:b57b71c0879a 709 }
RLRiedinger 6:b57b71c0879a 710
RLRiedinger 6:b57b71c0879a 711 this->writeRegister(THR, str[idx]);
RLRiedinger 6:b57b71c0879a 712
RLRiedinger 6:b57b71c0879a 713 }
RLRiedinger 6:b57b71c0879a 714
RLRiedinger 6:b57b71c0879a 715 #endif
wim 2:76cb93b511f2 716
RLRiedinger 6:b57b71c0879a 717 }
RLRiedinger 6:b57b71c0879a 718
RLRiedinger 6:b57b71c0879a 719 /*
RLRiedinger 6:b57b71c0879a 720 *
RLRiedinger 6:b57b71c0879a 721 * Write byte array to UART Bridge. Blocking when no free space in FIFO
RLRiedinger 6:b57b71c0879a 722 * @param *data byte array to be written
RLRiedinger 6:b57b71c0879a 723 * @param len number of bytes to write
RLRiedinger 6:b57b71c0879a 724 * @return none
RLRiedinger 6:b57b71c0879a 725 */
RLRiedinger 6:b57b71c0879a 726
RLRiedinger 6:b57b71c0879a 727 void SC16IS750::writeBytes(const char *data, int len) {
RLRiedinger 6:b57b71c0879a 728
RLRiedinger 6:b57b71c0879a 729 #if ENABLE_BULK_TRANSFERS
RLRiedinger 6:b57b71c0879a 730
RLRiedinger 6:b57b71c0879a 731 int idx;
RLRiedinger 6:b57b71c0879a 732
RLRiedinger 6:b57b71c0879a 733 // Write blocks of BULK_BLOCK_LEN
RLRiedinger 6:b57b71c0879a 734
RLRiedinger 6:b57b71c0879a 735 while (len > BULK_BLOCK_LEN) {
RLRiedinger 6:b57b71c0879a 736
RLRiedinger 6:b57b71c0879a 737 while(this->readRegister(TXLVL) < BULK_BLOCK_LEN) {
RLRiedinger 6:b57b71c0879a 738
RLRiedinger 6:b57b71c0879a 739 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 740
RLRiedinger 6:b57b71c0879a 741 wait_us(10);
RLRiedinger 6:b57b71c0879a 742
RLRiedinger 6:b57b71c0879a 743 }
RLRiedinger 6:b57b71c0879a 744
RLRiedinger 6:b57b71c0879a 745 // Write a block of BULK_BLOCK_LEN bytes
RLRiedinger 6:b57b71c0879a 746
RLRiedinger 6:b57b71c0879a 747 #if (0)
RLRiedinger 6:b57b71c0879a 748
RLRiedinger 6:b57b71c0879a 749 // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
RLRiedinger 6:b57b71c0879a 750
RLRiedinger 6:b57b71c0879a 751 for (idx = 0; idx < BULK_BLOCK_LEN; idx++) {
RLRiedinger 6:b57b71c0879a 752
RLRiedinger 6:b57b71c0879a 753 this->writeRegister(THR, data[idx]);
RLRiedinger 6:b57b71c0879a 754
RLRiedinger 6:b57b71c0879a 755 }
RLRiedinger 6:b57b71c0879a 756
RLRiedinger 6:b57b71c0879a 757 #else
RLRiedinger 6:b57b71c0879a 758
RLRiedinger 6:b57b71c0879a 759 // Optimized
RLRiedinger 6:b57b71c0879a 760
RLRiedinger 6:b57b71c0879a 761 this->writeDataBlock(data, BULK_BLOCK_LEN);
RLRiedinger 6:b57b71c0879a 762
RLRiedinger 6:b57b71c0879a 763 #endif
RLRiedinger 6:b57b71c0879a 764
RLRiedinger 6:b57b71c0879a 765 len -= BULK_BLOCK_LEN;
RLRiedinger 6:b57b71c0879a 766 data += BULK_BLOCK_LEN;
RLRiedinger 6:b57b71c0879a 767
RLRiedinger 6:b57b71c0879a 768 }
RLRiedinger 6:b57b71c0879a 769
RLRiedinger 6:b57b71c0879a 770 // Write remaining bytes
RLRiedinger 6:b57b71c0879a 771 // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
RLRiedinger 6:b57b71c0879a 772
RLRiedinger 6:b57b71c0879a 773 for (idx = 0; idx < len; idx++) {
RLRiedinger 6:b57b71c0879a 774
RLRiedinger 6:b57b71c0879a 775 while (this->readRegister(TXLVL) == 0) {
RLRiedinger 6:b57b71c0879a 776
RLRiedinger 6:b57b71c0879a 777 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 778
RLRiedinger 6:b57b71c0879a 779 wait_us(10);
RLRiedinger 6:b57b71c0879a 780
RLRiedinger 6:b57b71c0879a 781 }
RLRiedinger 6:b57b71c0879a 782
RLRiedinger 6:b57b71c0879a 783 this->writeRegister(THR, data[idx]);
RLRiedinger 6:b57b71c0879a 784
RLRiedinger 6:b57b71c0879a 785 }
RLRiedinger 6:b57b71c0879a 786
RLRiedinger 6:b57b71c0879a 787 #else
RLRiedinger 6:b57b71c0879a 788
RLRiedinger 6:b57b71c0879a 789 // Single writes instead of bulktransfer
RLRiedinger 6:b57b71c0879a 790
RLRiedinger 6:b57b71c0879a 791 int idx;
RLRiedinger 6:b57b71c0879a 792
RLRiedinger 6:b57b71c0879a 793 for (idx = 0; idx < len; idx++) {
RLRiedinger 6:b57b71c0879a 794
RLRiedinger 6:b57b71c0879a 795 while (this->readRegister(TXLVL) == 0) {
RLRiedinger 6:b57b71c0879a 796
RLRiedinger 6:b57b71c0879a 797 // Wait for space in TX buffer
RLRiedinger 6:b57b71c0879a 798
RLRiedinger 6:b57b71c0879a 799 wait_us(10);
RLRiedinger 6:b57b71c0879a 800
RLRiedinger 6:b57b71c0879a 801 }
RLRiedinger 6:b57b71c0879a 802
RLRiedinger 6:b57b71c0879a 803 this->writeRegister(THR, str[idx]);
RLRiedinger 6:b57b71c0879a 804
RLRiedinger 6:b57b71c0879a 805 }
RLRiedinger 6:b57b71c0879a 806
RLRiedinger 6:b57b71c0879a 807 #endif
wim 0:d64854a60f95 808
RLRiedinger 6:b57b71c0879a 809 }
RLRiedinger 6:b57b71c0879a 810
RLRiedinger 6:b57b71c0879a 811 /*
RLRiedinger 6:b57b71c0879a 812 * Set direction of I/O port pins.
RLRiedinger 6:b57b71c0879a 813 * This method is specific to the SPI-I2C UART and not found on the 16750
RLRiedinger 6:b57b71c0879a 814 * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 815 * @param bits Bitpattern for I/O (1=output, 0=input)
RLRiedinger 6:b57b71c0879a 816 * @return none
RLRiedinger 6:b57b71c0879a 817 */
RLRiedinger 6:b57b71c0879a 818
RLRiedinger 6:b57b71c0879a 819 void SC16IS750::ioSetDirection(unsigned char bits) {
RLRiedinger 6:b57b71c0879a 820
RLRiedinger 6:b57b71c0879a 821 this->writeRegister(IODIR, bits);
RLRiedinger 6:b57b71c0879a 822
RLRiedinger 6:b57b71c0879a 823 }
RLRiedinger 6:b57b71c0879a 824
RLRiedinger 6:b57b71c0879a 825 /*
RLRiedinger 6:b57b71c0879a 826 * Set bits of I/O port pins.
RLRiedinger 6:b57b71c0879a 827 * This method is specific to the SPI-I2C UART and not found on the 16750
RLRiedinger 6:b57b71c0879a 828 * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 829 * @param bits Bitpattern for I/O (1= set output bit, 0 = clear output bit)
RLRiedinger 6:b57b71c0879a 830 * @return none
RLRiedinger 6:b57b71c0879a 831 */
RLRiedinger 6:b57b71c0879a 832
RLRiedinger 6:b57b71c0879a 833 void SC16IS750::ioSetState(unsigned char bits) {
RLRiedinger 6:b57b71c0879a 834
RLRiedinger 6:b57b71c0879a 835 this->writeRegister(IOSTATE, bits);
RLRiedinger 6:b57b71c0879a 836
RLRiedinger 6:b57b71c0879a 837 }
RLRiedinger 6:b57b71c0879a 838
RLRiedinger 6:b57b71c0879a 839 /*
RLRiedinger 6:b57b71c0879a 840 * Get bits of I/O port pins.
RLRiedinger 6:b57b71c0879a 841 * This method is specific to the SPI-I2C UART and not found on the 16750
RLRiedinger 6:b57b71c0879a 842 * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 843 * @param none
RLRiedinger 6:b57b71c0879a 844 * @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
RLRiedinger 6:b57b71c0879a 845 */
wim 1:0440152c5387 846
RLRiedinger 6:b57b71c0879a 847 unsigned char SC16IS750::ioGetState() {
RLRiedinger 6:b57b71c0879a 848
RLRiedinger 6:b57b71c0879a 849 return this->readRegister(IOSTATE) ;
RLRiedinger 6:b57b71c0879a 850
RLRiedinger 6:b57b71c0879a 851 }
RLRiedinger 6:b57b71c0879a 852
RLRiedinger 6:b57b71c0879a 853 /*
RLRiedinger 6:b57b71c0879a 854 * Software Reset SC16IS750 device.
RLRiedinger 6:b57b71c0879a 855 * This method is specific to the SPI-I2C UART and not found on the 16750
RLRiedinger 6:b57b71c0879a 856 * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 857 * @param none
RLRiedinger 6:b57b71c0879a 858 * @return none
RLRiedinger 6:b57b71c0879a 859 */
RLRiedinger 6:b57b71c0879a 860
RLRiedinger 6:b57b71c0879a 861 void SC16IS750::swReset() {
RLRiedinger 6:b57b71c0879a 862
RLRiedinger 6:b57b71c0879a 863 this->writeRegister(IOCTRL, IOC_SW_RST);
RLRiedinger 6:b57b71c0879a 864
wim 1:0440152c5387 865 }
wim 1:0440152c5387 866
RLRiedinger 6:b57b71c0879a 867 //
RLRiedinger 6:b57b71c0879a 868 // End Abstract Class Implementation
RLRiedinger 6:b57b71c0879a 869 //
RLRiedinger 6:b57b71c0879a 870
RLRiedinger 6:b57b71c0879a 871 //
RLRiedinger 6:b57b71c0879a 872 // Begin SPI Class Implementation
RLRiedinger 6:b57b71c0879a 873 //
wim 2:76cb93b511f2 874
RLRiedinger 6:b57b71c0879a 875 /*
RLRiedinger 6:b57b71c0879a 876 * Create an SC16IS750_SPI object using a specified SPI bus and CS
RLRiedinger 6:b57b71c0879a 877 *
RLRiedinger 6:b57b71c0879a 878 * @param SPI &spi the SPI port to connect to
RLRiedinger 6:b57b71c0879a 879 * @param cs Pinname of the CS pin (active low)
RLRiedinger 6:b57b71c0879a 880 * @param rst Pinname for Reset pin (active low) Optional, Default = NC
RLRiedinger 6:b57b71c0879a 881 */
wim 1:0440152c5387 882
RLRiedinger 6:b57b71c0879a 883 SC16IS750_SPI::SC16IS750_SPI(SPI *spi, PinName cs, PinName rst) : _spi(spi), _cs(cs) {
RLRiedinger 6:b57b71c0879a 884
RLRiedinger 6:b57b71c0879a 885 _cs = 1; // Deselect
RLRiedinger 6:b57b71c0879a 886
RLRiedinger 6:b57b71c0879a 887 _spi->format(8, 0);
RLRiedinger 6:b57b71c0879a 888
RLRiedinger 6:b57b71c0879a 889 _spi->frequency(1000000);
RLRiedinger 6:b57b71c0879a 890
RLRiedinger 6:b57b71c0879a 891 //_spi->frequency(100000);
RLRiedinger 6:b57b71c0879a 892
RLRiedinger 6:b57b71c0879a 893 // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
RLRiedinger 6:b57b71c0879a 894
RLRiedinger 6:b57b71c0879a 895 if (rst != NC) {
RLRiedinger 6:b57b71c0879a 896
RLRiedinger 6:b57b71c0879a 897 _reset = new DigitalOut(rst); // Construct new pin
RLRiedinger 6:b57b71c0879a 898 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 899
RLRiedinger 6:b57b71c0879a 900 } else {
RLRiedinger 6:b57b71c0879a 901
RLRiedinger 6:b57b71c0879a 902 // No Hardware Reset pin
RLRiedinger 6:b57b71c0879a 903
RLRiedinger 6:b57b71c0879a 904 _reset = NULL; // Construct dummy pin
RLRiedinger 6:b57b71c0879a 905
RLRiedinger 6:b57b71c0879a 906 }
RLRiedinger 6:b57b71c0879a 907
RLRiedinger 6:b57b71c0879a 908
RLRiedinger 6:b57b71c0879a 909 // Dont call _init() until SPI port has been configured.
RLRiedinger 6:b57b71c0879a 910 // That is why _init() is not called in parent Constructor
RLRiedinger 6:b57b71c0879a 911
RLRiedinger 6:b57b71c0879a 912 _init();
RLRiedinger 6:b57b71c0879a 913
RLRiedinger 6:b57b71c0879a 914 }
RLRiedinger 6:b57b71c0879a 915
RLRiedinger 6:b57b71c0879a 916 /*
RLRiedinger 6:b57b71c0879a 917 * Destruct SC16IS750_SPI bridge object
RLRiedinger 6:b57b71c0879a 918 *
RLRiedinger 6:b57b71c0879a 919 * @param none
RLRiedinger 6:b57b71c0879a 920 * @return none
RLRiedinger 6:b57b71c0879a 921 */
wim 1:0440152c5387 922
RLRiedinger 6:b57b71c0879a 923 SC16IS750_SPI::~SC16IS750_SPI() {
RLRiedinger 6:b57b71c0879a 924
RLRiedinger 6:b57b71c0879a 925 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 926
RLRiedinger 6:b57b71c0879a 927 delete _reset;
RLRiedinger 6:b57b71c0879a 928
RLRiedinger 6:b57b71c0879a 929 } // Reset pin
wim 0:d64854a60f95 930
wim 0:d64854a60f95 931 }
wim 0:d64854a60f95 932
wim 0:d64854a60f95 933
RLRiedinger 6:b57b71c0879a 934 /*
RLRiedinger 6:b57b71c0879a 935 * Write value to internal register.
RLRiedinger 6:b57b71c0879a 936 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 937 * @param data The 8bit value to write
RLRiedinger 6:b57b71c0879a 938 * @return none
RLRiedinger 6:b57b71c0879a 939 */
wim 2:76cb93b511f2 940
RLRiedinger 6:b57b71c0879a 941 void SC16IS750_SPI::writeRegister(RegisterName registerAddress, char data) {
RLRiedinger 6:b57b71c0879a 942
RLRiedinger 6:b57b71c0879a 943 _cs = 0; // Select;
RLRiedinger 6:b57b71c0879a 944 _spi->write(registerAddress);
RLRiedinger 6:b57b71c0879a 945 _spi->write(data);
RLRiedinger 6:b57b71c0879a 946 _cs = 1; // Deselect;
wim 2:76cb93b511f2 947
RLRiedinger 6:b57b71c0879a 948 }
RLRiedinger 6:b57b71c0879a 949
RLRiedinger 6:b57b71c0879a 950 /*
RLRiedinger 6:b57b71c0879a 951 * Read value from internal register.
RLRiedinger 6:b57b71c0879a 952 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 953 * @return char The 8bit value read from the register
RLRiedinger 6:b57b71c0879a 954 */
wim 3:9783b6bde958 955
RLRiedinger 6:b57b71c0879a 956 char SC16IS750_SPI::readRegister(RegisterName registerAddress) {
RLRiedinger 6:b57b71c0879a 957
RLRiedinger 6:b57b71c0879a 958 // Used in SPI read operations to flush slave's shift register
RLRiedinger 6:b57b71c0879a 959
RLRiedinger 6:b57b71c0879a 960 const char SPI_DUMMY_CHAR = 0xFF;
RLRiedinger 6:b57b71c0879a 961
RLRiedinger 6:b57b71c0879a 962 char result;
RLRiedinger 6:b57b71c0879a 963
RLRiedinger 6:b57b71c0879a 964 _cs = 0; // Select;
RLRiedinger 6:b57b71c0879a 965 _spi->write(SPI_READ_MODE_FLAG | registerAddress);
RLRiedinger 6:b57b71c0879a 966 result = _spi->write(SPI_DUMMY_CHAR);
RLRiedinger 6:b57b71c0879a 967 _cs = 1; // Deselect;
RLRiedinger 6:b57b71c0879a 968
RLRiedinger 6:b57b71c0879a 969 return result;
wim 1:0440152c5387 970
wim 0:d64854a60f95 971 }
RLRiedinger 6:b57b71c0879a 972
RLRiedinger 6:b57b71c0879a 973 /*
RLRiedinger 6:b57b71c0879a 974 * Write multiple datavalues to Transmitregister.
RLRiedinger 6:b57b71c0879a 975 * More Efficient implementation than writing individual bytes
RLRiedinger 6:b57b71c0879a 976 * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 977 *
RLRiedinger 6:b57b71c0879a 978 * @param char* databytes The pointer to the block of data
RLRiedinger 6:b57b71c0879a 979 * @param len The number of bytes to write
RLRiedinger 6:b57b71c0879a 980 * @return none
RLRiedinger 6:b57b71c0879a 981 */
RLRiedinger 6:b57b71c0879a 982
wim 3:9783b6bde958 983 void SC16IS750_SPI::writeDataBlock (const char *data, int len) {
RLRiedinger 6:b57b71c0879a 984
RLRiedinger 6:b57b71c0879a 985 int i;
RLRiedinger 6:b57b71c0879a 986
RLRiedinger 6:b57b71c0879a 987 _cs = 0; // select;
RLRiedinger 6:b57b71c0879a 988
RLRiedinger 6:b57b71c0879a 989 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 990 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
wim 3:9783b6bde958 991
RLRiedinger 6:b57b71c0879a 992 _spi->write(THR);
RLRiedinger 6:b57b71c0879a 993
RLRiedinger 6:b57b71c0879a 994 for (i = 0; i < len; i++, data++) {
RLRiedinger 6:b57b71c0879a 995
RLRiedinger 6:b57b71c0879a 996 _spi->write(*data);
RLRiedinger 6:b57b71c0879a 997
RLRiedinger 6:b57b71c0879a 998 }
RLRiedinger 6:b57b71c0879a 999
RLRiedinger 6:b57b71c0879a 1000 _cs = 1; // deselect;
wim 4:12446ee9f9c8 1001
RLRiedinger 6:b57b71c0879a 1002 }
RLRiedinger 6:b57b71c0879a 1003
RLRiedinger 6:b57b71c0879a 1004 /*
RLRiedinger 6:b57b71c0879a 1005 * Hardware Reset SC16IS750 device.
RLRiedinger 6:b57b71c0879a 1006 * This method is only functional when the Reset pin has been declared and is also connected
RLRiedinger 6:b57b71c0879a 1007 * @param none
RLRiedinger 6:b57b71c0879a 1008 * @return none
RLRiedinger 6:b57b71c0879a 1009 */
wim 4:12446ee9f9c8 1010
RLRiedinger 6:b57b71c0879a 1011 void SC16IS750_SPI::hwReset() {
RLRiedinger 6:b57b71c0879a 1012
RLRiedinger 6:b57b71c0879a 1013 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 1014
RLRiedinger 6:b57b71c0879a 1015 _reset->write(0); // Activate
RLRiedinger 6:b57b71c0879a 1016
RLRiedinger 6:b57b71c0879a 1017 // wait_ms(100);
RLRiedinger 6:b57b71c0879a 1018
RLRiedinger 6:b57b71c0879a 1019 wait_ms(1000); //Test only
RLRiedinger 6:b57b71c0879a 1020
RLRiedinger 6:b57b71c0879a 1021 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1022
RLRiedinger 6:b57b71c0879a 1023 } else {
RLRiedinger 6:b57b71c0879a 1024
RLRiedinger 6:b57b71c0879a 1025 printf("Hardware Reset pin is not available...\n\r");
RLRiedinger 6:b57b71c0879a 1026
RLRiedinger 6:b57b71c0879a 1027 }
wim 4:12446ee9f9c8 1028
wim 4:12446ee9f9c8 1029 }
wim 4:12446ee9f9c8 1030
wim 0:d64854a60f95 1031 //
wim 0:d64854a60f95 1032 // End SPI Implementation
wim 1:0440152c5387 1033 //
RLRiedinger 6:b57b71c0879a 1034
wim 4:12446ee9f9c8 1035 //
wim 4:12446ee9f9c8 1036 // Begin I2C Implementation
wim 4:12446ee9f9c8 1037 //
wim 4:12446ee9f9c8 1038
RLRiedinger 6:b57b71c0879a 1039 /*
RLRiedinger 6:b57b71c0879a 1040 * Create a SC16IS750_I2C object for a bridge between I2C and a Serial port
RLRiedinger 6:b57b71c0879a 1041 *
RLRiedinger 6:b57b71c0879a 1042 * @param I2C &i2c the I2C port to connect to
RLRiedinger 6:b57b71c0879a 1043 * @param char deviceAddress the I2C slave address of the SC16IS750
RLRiedinger 6:b57b71c0879a 1044 * @param rst Pinname for Reset pin (active low) Optional, Default = NC
RLRiedinger 6:b57b71c0879a 1045 *
RLRiedinger 6:b57b71c0879a 1046 */
RLRiedinger 6:b57b71c0879a 1047
wim 4:12446ee9f9c8 1048 SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE) {
RLRiedinger 6:b57b71c0879a 1049
RLRiedinger 6:b57b71c0879a 1050 //_i2c->frequency(400000);
RLRiedinger 6:b57b71c0879a 1051
RLRiedinger 6:b57b71c0879a 1052 _i2c->frequency(400000);
RLRiedinger 6:b57b71c0879a 1053
RLRiedinger 6:b57b71c0879a 1054 // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
RLRiedinger 6:b57b71c0879a 1055
RLRiedinger 6:b57b71c0879a 1056 if (rst != NC) {
RLRiedinger 6:b57b71c0879a 1057
RLRiedinger 6:b57b71c0879a 1058 _reset = new DigitalOut(rst); // Construct new pin
RLRiedinger 6:b57b71c0879a 1059 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1060
RLRiedinger 6:b57b71c0879a 1061 } else {
RLRiedinger 6:b57b71c0879a 1062
RLRiedinger 6:b57b71c0879a 1063 // No Hardware Reset pin
RLRiedinger 6:b57b71c0879a 1064
RLRiedinger 6:b57b71c0879a 1065 _reset = NULL; // Construct dummy pin
RLRiedinger 6:b57b71c0879a 1066
RLRiedinger 6:b57b71c0879a 1067 }
RLRiedinger 6:b57b71c0879a 1068
RLRiedinger 6:b57b71c0879a 1069 // Dont call _init() until I2C port has been configured.
RLRiedinger 6:b57b71c0879a 1070 // That is why _init() is not called in parent Constructor
RLRiedinger 6:b57b71c0879a 1071
RLRiedinger 6:b57b71c0879a 1072 _init();
wim 0:d64854a60f95 1073
wim 0:d64854a60f95 1074 }
RLRiedinger 6:b57b71c0879a 1075
RLRiedinger 6:b57b71c0879a 1076 /*
RLRiedinger 6:b57b71c0879a 1077 * Destruct SC16IS750_I2C bridge object
RLRiedinger 6:b57b71c0879a 1078 *
RLRiedinger 6:b57b71c0879a 1079 * @param none
RLRiedinger 6:b57b71c0879a 1080 * @return none
RLRiedinger 6:b57b71c0879a 1081 */
wim 0:d64854a60f95 1082
wim 4:12446ee9f9c8 1083 SC16IS750_I2C::~SC16IS750_I2C() {
RLRiedinger 6:b57b71c0879a 1084
RLRiedinger 6:b57b71c0879a 1085 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 1086
RLRiedinger 6:b57b71c0879a 1087 delete _reset; // Reset pin
RLRiedinger 6:b57b71c0879a 1088
RLRiedinger 6:b57b71c0879a 1089 }
RLRiedinger 6:b57b71c0879a 1090
wim 4:12446ee9f9c8 1091 }
RLRiedinger 6:b57b71c0879a 1092
RLRiedinger 6:b57b71c0879a 1093 /*
RLRiedinger 6:b57b71c0879a 1094 * Write value to internal register.
RLRiedinger 6:b57b71c0879a 1095 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1096 * @param data The 8bit value to write
RLRiedinger 6:b57b71c0879a 1097 * @return none
RLRiedinger 6:b57b71c0879a 1098 */
RLRiedinger 6:b57b71c0879a 1099
wim 0:d64854a60f95 1100 void SC16IS750_I2C::writeRegister(RegisterName registerAddress, char data) {
RLRiedinger 6:b57b71c0879a 1101
RLRiedinger 6:b57b71c0879a 1102 char w[2];
RLRiedinger 6:b57b71c0879a 1103
RLRiedinger 6:b57b71c0879a 1104 w[0] = registerAddress;
RLRiedinger 6:b57b71c0879a 1105 w[1] = data;
RLRiedinger 6:b57b71c0879a 1106
RLRiedinger 6:b57b71c0879a 1107 _i2c->write(_slaveAddress, w, 2);
wim 0:d64854a60f95 1108
wim 0:d64854a60f95 1109 }
RLRiedinger 6:b57b71c0879a 1110
RLRiedinger 6:b57b71c0879a 1111 /*
RLRiedinger 6:b57b71c0879a 1112 * Read value from internal register.
RLRiedinger 6:b57b71c0879a 1113 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1114 * @return char The 8bit value read from the register
RLRiedinger 6:b57b71c0879a 1115 */
RLRiedinger 6:b57b71c0879a 1116
wim 0:d64854a60f95 1117 char SC16IS750_I2C::readRegister(RegisterName registerAddress) {
RLRiedinger 6:b57b71c0879a 1118
RLRiedinger 6:b57b71c0879a 1119 /*
RLRiedinger 6:b57b71c0879a 1120 * Read char from SC16IS750 register at <registerAddress>.
RLRiedinger 6:b57b71c0879a 1121 */
wim 0:d64854a60f95 1122
RLRiedinger 6:b57b71c0879a 1123 char w[1];
RLRiedinger 6:b57b71c0879a 1124 char r[1];
RLRiedinger 6:b57b71c0879a 1125
RLRiedinger 6:b57b71c0879a 1126 w[0] = registerAddress;
wim 0:d64854a60f95 1127
RLRiedinger 6:b57b71c0879a 1128 // _i2c->write(_slaveAddress, w, 1 );
RLRiedinger 6:b57b71c0879a 1129
RLRiedinger 6:b57b71c0879a 1130 _i2c->write(_slaveAddress, w, 1, true); // Repeated Start
RLRiedinger 6:b57b71c0879a 1131 _i2c->read(_slaveAddress, r, 1);
RLRiedinger 6:b57b71c0879a 1132
RLRiedinger 6:b57b71c0879a 1133 return (r[0]);
wim 0:d64854a60f95 1134
RLRiedinger 6:b57b71c0879a 1135 }
RLRiedinger 6:b57b71c0879a 1136
RLRiedinger 6:b57b71c0879a 1137 /*
RLRiedinger 6:b57b71c0879a 1138 * Write multiple datavalues to Transmitregister.
RLRiedinger 6:b57b71c0879a 1139 * More Efficient implementation than writing individual bytes
RLRiedinger 6:b57b71c0879a 1140 * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1141 * Pure virtual, must be declared in derived class.
RLRiedinger 6:b57b71c0879a 1142 * @param char* databytes The pointer to the block of data
RLRiedinger 6:b57b71c0879a 1143 * @param len The number of bytes to write
RLRiedinger 6:b57b71c0879a 1144 * @return none
RLRiedinger 6:b57b71c0879a 1145 */
wim 3:9783b6bde958 1146
RLRiedinger 6:b57b71c0879a 1147 void SC16IS750_I2C::writeDataBlock (const char *data, int len) {
wim 3:9783b6bde958 1148
RLRiedinger 6:b57b71c0879a 1149 #if (0)
RLRiedinger 6:b57b71c0879a 1150
RLRiedinger 6:b57b71c0879a 1151 int i;
RLRiedinger 6:b57b71c0879a 1152 char w[BULK_BLOCK_LEN];
RLRiedinger 6:b57b71c0879a 1153
RLRiedinger 6:b57b71c0879a 1154 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 1155 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1156
RLRiedinger 6:b57b71c0879a 1157 w[0] = THR;
RLRiedinger 6:b57b71c0879a 1158
RLRiedinger 6:b57b71c0879a 1159 // Copy the data ...
RLRiedinger 6:b57b71c0879a 1160
RLRiedinger 6:b57b71c0879a 1161 for (i=0; i<len; i++)
RLRiedinger 6:b57b71c0879a 1162 w[i+1] = data[i];
RLRiedinger 6:b57b71c0879a 1163
RLRiedinger 6:b57b71c0879a 1164 _i2c->write(_slaveAddress, w, len + 1);
RLRiedinger 6:b57b71c0879a 1165
RLRiedinger 6:b57b71c0879a 1166 #else
RLRiedinger 6:b57b71c0879a 1167
RLRiedinger 6:b57b71c0879a 1168 int i;
RLRiedinger 6:b57b71c0879a 1169
RLRiedinger 6:b57b71c0879a 1170 _i2c->start();
RLRiedinger 6:b57b71c0879a 1171 _i2c->write(_slaveAddress);
RLRiedinger 6:b57b71c0879a 1172
RLRiedinger 6:b57b71c0879a 1173 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 1174 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1175
RLRiedinger 6:b57b71c0879a 1176 _i2c->write(THR);
RLRiedinger 6:b57b71c0879a 1177
RLRiedinger 6:b57b71c0879a 1178 // Send the data ..
RLRiedinger 6:b57b71c0879a 1179
RLRiedinger 6:b57b71c0879a 1180 for (i = 0; i < len; i++) {
RLRiedinger 6:b57b71c0879a 1181
RLRiedinger 6:b57b71c0879a 1182 _i2c->write(data[i]);
RLRiedinger 6:b57b71c0879a 1183
RLRiedinger 6:b57b71c0879a 1184 }
RLRiedinger 6:b57b71c0879a 1185
RLRiedinger 6:b57b71c0879a 1186 _i2c->stop();
RLRiedinger 6:b57b71c0879a 1187
RLRiedinger 6:b57b71c0879a 1188 #endif
wim 3:9783b6bde958 1189
RLRiedinger 6:b57b71c0879a 1190 }
RLRiedinger 6:b57b71c0879a 1191
RLRiedinger 6:b57b71c0879a 1192 /*
RLRiedinger 6:b57b71c0879a 1193 * Hardware Reset SC16IS750 device.
RLRiedinger 6:b57b71c0879a 1194 * This method is only available when the Reset pin has been declared and is also connected
RLRiedinger 6:b57b71c0879a 1195 * @param none
RLRiedinger 6:b57b71c0879a 1196 * @return none
RLRiedinger 6:b57b71c0879a 1197 */
wim 4:12446ee9f9c8 1198
RLRiedinger 6:b57b71c0879a 1199 void SC16IS750_I2C::hwReset() {
RLRiedinger 6:b57b71c0879a 1200
RLRiedinger 6:b57b71c0879a 1201 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 1202
RLRiedinger 6:b57b71c0879a 1203 _reset->write(0); // Activate
RLRiedinger 6:b57b71c0879a 1204
RLRiedinger 6:b57b71c0879a 1205 // wait_ms(100);
RLRiedinger 6:b57b71c0879a 1206
RLRiedinger 6:b57b71c0879a 1207 wait_ms(1000); // Test only
RLRiedinger 6:b57b71c0879a 1208
RLRiedinger 6:b57b71c0879a 1209 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1210
RLRiedinger 6:b57b71c0879a 1211
RLRiedinger 6:b57b71c0879a 1212 } else {
RLRiedinger 6:b57b71c0879a 1213
RLRiedinger 6:b57b71c0879a 1214 printf("Hardware Reset pin is not available ...\n\r");
RLRiedinger 6:b57b71c0879a 1215
RLRiedinger 6:b57b71c0879a 1216 }
RLRiedinger 6:b57b71c0879a 1217
wim 4:12446ee9f9c8 1218 }
wim 4:12446ee9f9c8 1219
wim 0:d64854a60f95 1220 //
wim 1:0440152c5387 1221 // End I2C Implementation
wim 4:12446ee9f9c8 1222 //
RLRiedinger 6:b57b71c0879a 1223
wim 4:12446ee9f9c8 1224 //
wim 4:12446ee9f9c8 1225 // Begin SPI Class Implementation for 16SCIS752 dual UART
wim 4:12446ee9f9c8 1226 //
wim 4:12446ee9f9c8 1227
RLRiedinger 6:b57b71c0879a 1228 /*
RLRiedinger 6:b57b71c0879a 1229 * Create an SC16IS752_SPI object using a specified SPI bus and CS
RLRiedinger 6:b57b71c0879a 1230 * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 1231 * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 1232 *
RLRiedinger 6:b57b71c0879a 1233 * @param SPI &spi the SPI port to connect to
RLRiedinger 6:b57b71c0879a 1234 * @param cs Pinname of the CS pin (active low)
RLRiedinger 6:b57b71c0879a 1235 * @param rst Pinname for Reset pin (active low) Optional, Default = NC
RLRiedinger 6:b57b71c0879a 1236 * @param channel UART ChannelName, Default = Channel_A
RLRiedinger 6:b57b71c0879a 1237 */
wim 4:12446ee9f9c8 1238
RLRiedinger 6:b57b71c0879a 1239 SC16IS752_SPI::SC16IS752_SPI (SPI *spi, PinName cs, PinName rst, ChannelName channel) : _spi(spi), _cs(cs), _channel(channel) {
RLRiedinger 6:b57b71c0879a 1240
RLRiedinger 6:b57b71c0879a 1241 _cs = 1; // Deselect
RLRiedinger 6:b57b71c0879a 1242
RLRiedinger 6:b57b71c0879a 1243 _spi->format(8, 0);
RLRiedinger 6:b57b71c0879a 1244 _spi->frequency(1000000);
RLRiedinger 6:b57b71c0879a 1245
RLRiedinger 6:b57b71c0879a 1246 // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
RLRiedinger 6:b57b71c0879a 1247
RLRiedinger 6:b57b71c0879a 1248 if (rst != NC) {
RLRiedinger 6:b57b71c0879a 1249
RLRiedinger 6:b57b71c0879a 1250 _reset = new DigitalOut(rst); // Construct new pin
RLRiedinger 6:b57b71c0879a 1251 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1252
RLRiedinger 6:b57b71c0879a 1253 }
RLRiedinger 6:b57b71c0879a 1254 else {
RLRiedinger 6:b57b71c0879a 1255
RLRiedinger 6:b57b71c0879a 1256 // No Hardware Reset pin
RLRiedinger 6:b57b71c0879a 1257 _reset = NULL; // Construct dummy pin
RLRiedinger 6:b57b71c0879a 1258
RLRiedinger 6:b57b71c0879a 1259 }
RLRiedinger 6:b57b71c0879a 1260
RLRiedinger 6:b57b71c0879a 1261 // Dont call _init() until SPI port has been configured.
RLRiedinger 6:b57b71c0879a 1262 // That is why _init() is not called in parent Constructor
RLRiedinger 6:b57b71c0879a 1263
RLRiedinger 6:b57b71c0879a 1264 _init();
wim 4:12446ee9f9c8 1265
wim 4:12446ee9f9c8 1266 }
RLRiedinger 6:b57b71c0879a 1267
RLRiedinger 6:b57b71c0879a 1268 /*
RLRiedinger 6:b57b71c0879a 1269 * Destruct SC16IS750_SPI bridge object
RLRiedinger 6:b57b71c0879a 1270 *
RLRiedinger 6:b57b71c0879a 1271 * @param none
RLRiedinger 6:b57b71c0879a 1272 * @return none
RLRiedinger 6:b57b71c0879a 1273 */
wim 4:12446ee9f9c8 1274
RLRiedinger 6:b57b71c0879a 1275 SC16IS752_SPI::~SC16IS752_SPI() {
RLRiedinger 6:b57b71c0879a 1276
RLRiedinger 6:b57b71c0879a 1277 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 1278
RLRiedinger 6:b57b71c0879a 1279 delete _reset; // Reset pin
RLRiedinger 6:b57b71c0879a 1280
RLRiedinger 6:b57b71c0879a 1281 }
RLRiedinger 6:b57b71c0879a 1282
RLRiedinger 6:b57b71c0879a 1283 }
RLRiedinger 6:b57b71c0879a 1284
RLRiedinger 6:b57b71c0879a 1285 /*
RLRiedinger 6:b57b71c0879a 1286 * Write value to internal register.
RLRiedinger 6:b57b71c0879a 1287 * Pure virtual, must be declared in derived class.
RLRiedinger 6:b57b71c0879a 1288 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1289 * @param data The 8bit value to write
RLRiedinger 6:b57b71c0879a 1290 * @return none
RLRiedinger 6:b57b71c0879a 1291 */
RLRiedinger 6:b57b71c0879a 1292
wim 4:12446ee9f9c8 1293 void SC16IS752_SPI::writeRegister(RegisterName registerAddress, char data) {
RLRiedinger 6:b57b71c0879a 1294
RLRiedinger 6:b57b71c0879a 1295 _cs = 0; // Select;
RLRiedinger 6:b57b71c0879a 1296 _spi->write(registerAddress | _channel);
RLRiedinger 6:b57b71c0879a 1297 _spi->write(data);
RLRiedinger 6:b57b71c0879a 1298 _cs = 1; // Deselect;
wim 4:12446ee9f9c8 1299
wim 4:12446ee9f9c8 1300 }
RLRiedinger 6:b57b71c0879a 1301
RLRiedinger 6:b57b71c0879a 1302 /*
RLRiedinger 6:b57b71c0879a 1303 * Read value from internal register.
RLRiedinger 6:b57b71c0879a 1304 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1305 * @return char The 8bit value read from the register
RLRiedinger 6:b57b71c0879a 1306 */
RLRiedinger 6:b57b71c0879a 1307
wim 4:12446ee9f9c8 1308 char SC16IS752_SPI::readRegister(RegisterName registerAddress) {
RLRiedinger 6:b57b71c0879a 1309
RLRiedinger 6:b57b71c0879a 1310 // Used in SPI read operations to flush slave's shift register
RLRiedinger 6:b57b71c0879a 1311
RLRiedinger 6:b57b71c0879a 1312 const char SPI_DUMMY_CHAR = 0xFF;
RLRiedinger 6:b57b71c0879a 1313
RLRiedinger 6:b57b71c0879a 1314 char result;
RLRiedinger 6:b57b71c0879a 1315
RLRiedinger 6:b57b71c0879a 1316 _cs = 0; // Select;
RLRiedinger 6:b57b71c0879a 1317 _spi->write(SPI_READ_MODE_FLAG | registerAddress | _channel);
RLRiedinger 6:b57b71c0879a 1318 result = _spi->write(SPI_DUMMY_CHAR);
RLRiedinger 6:b57b71c0879a 1319 _cs = 1; // Deselect;
RLRiedinger 6:b57b71c0879a 1320
RLRiedinger 6:b57b71c0879a 1321 return result;
wim 4:12446ee9f9c8 1322
wim 4:12446ee9f9c8 1323 }
RLRiedinger 6:b57b71c0879a 1324
RLRiedinger 6:b57b71c0879a 1325 /*
RLRiedinger 6:b57b71c0879a 1326 * Write multiple datavalues to Transmitregister.
RLRiedinger 6:b57b71c0879a 1327 * More Efficient implementation than writing individual bytes
RLRiedinger 6:b57b71c0879a 1328 * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1329 * Pure virtual, must be declared in derived class.
RLRiedinger 6:b57b71c0879a 1330 * @param char* databytes The pointer to the block of data
RLRiedinger 6:b57b71c0879a 1331 * @param len The number of bytes to write
RLRiedinger 6:b57b71c0879a 1332 * @return none
RLRiedinger 6:b57b71c0879a 1333 */
RLRiedinger 6:b57b71c0879a 1334
wim 4:12446ee9f9c8 1335 void SC16IS752_SPI::writeDataBlock (const char *data, int len) {
RLRiedinger 6:b57b71c0879a 1336
RLRiedinger 6:b57b71c0879a 1337 int i;
RLRiedinger 6:b57b71c0879a 1338
RLRiedinger 6:b57b71c0879a 1339 _cs = 0; // Select;
RLRiedinger 6:b57b71c0879a 1340
RLRiedinger 6:b57b71c0879a 1341 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 1342 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
wim 4:12446ee9f9c8 1343
RLRiedinger 6:b57b71c0879a 1344 _spi->write(THR | _channel);
RLRiedinger 6:b57b71c0879a 1345
RLRiedinger 6:b57b71c0879a 1346 for (i = 0; i < len; i++, data++) {
RLRiedinger 6:b57b71c0879a 1347
RLRiedinger 6:b57b71c0879a 1348 _spi->write(*data);
RLRiedinger 6:b57b71c0879a 1349
RLRiedinger 6:b57b71c0879a 1350 }
RLRiedinger 6:b57b71c0879a 1351
RLRiedinger 6:b57b71c0879a 1352 _cs = 1; // Deselect;
wim 4:12446ee9f9c8 1353
RLRiedinger 6:b57b71c0879a 1354 }
RLRiedinger 6:b57b71c0879a 1355
RLRiedinger 6:b57b71c0879a 1356 /*
RLRiedinger 6:b57b71c0879a 1357 * Hardware Reset SC16IS752 device.
RLRiedinger 6:b57b71c0879a 1358 * This method is only available when the Reset pin has been declared and is also connected
RLRiedinger 6:b57b71c0879a 1359 * @param none
RLRiedinger 6:b57b71c0879a 1360 * @return none
RLRiedinger 6:b57b71c0879a 1361 */
wim 4:12446ee9f9c8 1362
RLRiedinger 6:b57b71c0879a 1363 void SC16IS752_SPI::hwReset() {
RLRiedinger 6:b57b71c0879a 1364
RLRiedinger 6:b57b71c0879a 1365 if (_reset != NULL) {
RLRiedinger 6:b57b71c0879a 1366
RLRiedinger 6:b57b71c0879a 1367 _reset->write(0); // Activate
RLRiedinger 6:b57b71c0879a 1368
RLRiedinger 6:b57b71c0879a 1369 // wait_ms(100);
RLRiedinger 6:b57b71c0879a 1370
RLRiedinger 6:b57b71c0879a 1371 wait_ms(1000); // Test only
RLRiedinger 6:b57b71c0879a 1372
RLRiedinger 6:b57b71c0879a 1373 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1374
RLRiedinger 6:b57b71c0879a 1375 } else {
RLRiedinger 6:b57b71c0879a 1376
RLRiedinger 6:b57b71c0879a 1377 printf("Hardware Reset pin is not available ...\n\r");
RLRiedinger 6:b57b71c0879a 1378
RLRiedinger 6:b57b71c0879a 1379 }
wim 4:12446ee9f9c8 1380
wim 4:12446ee9f9c8 1381 }
wim 4:12446ee9f9c8 1382
wim 4:12446ee9f9c8 1383 //
wim 4:12446ee9f9c8 1384 // End SPI Implementation
wim 4:12446ee9f9c8 1385 //
RLRiedinger 6:b57b71c0879a 1386
wim 4:12446ee9f9c8 1387 //
wim 4:12446ee9f9c8 1388 // Begin I2C Implementation for 16SCIS752 dual UART
wim 4:12446ee9f9c8 1389 //
wim 4:12446ee9f9c8 1390
RLRiedinger 6:b57b71c0879a 1391 /*
RLRiedinger 6:b57b71c0879a 1392 * Create a SC16IS752_I2C object for a bridge between I2C and a Serial port
RLRiedinger 6:b57b71c0879a 1393 * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 1394 * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.
RLRiedinger 6:b57b71c0879a 1395 *
RLRiedinger 6:b57b71c0879a 1396 * @param I2C &i2c the I2C port to connect to
RLRiedinger 6:b57b71c0879a 1397 * @param char deviceAddress the I2C slave address of the SC16IS750
RLRiedinger 6:b57b71c0879a 1398 * @param rst Pinname for Reset pin (active low) Optional, Default = NC
RLRiedinger 6:b57b71c0879a 1399 * @param channel UART Channel, Default = Channel_A
RLRiedinger 6:b57b71c0879a 1400 */
wim 4:12446ee9f9c8 1401
RLRiedinger 6:b57b71c0879a 1402 SC16IS752_I2C::SC16IS752_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst, ChannelName channel) :
RLRiedinger 6:b57b71c0879a 1403 _i2c(i2c), _slaveAddress(deviceAddress & 0xFE), _channel(channel) {
RLRiedinger 6:b57b71c0879a 1404
RLRiedinger 6:b57b71c0879a 1405 // _i2c->frequency(400000);
RLRiedinger 6:b57b71c0879a 1406
RLRiedinger 6:b57b71c0879a 1407 _i2c->frequency(100000);
RLRiedinger 6:b57b71c0879a 1408
RLRiedinger 6:b57b71c0879a 1409 // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
RLRiedinger 6:b57b71c0879a 1410
RLRiedinger 6:b57b71c0879a 1411 if (rst != NC) {
RLRiedinger 6:b57b71c0879a 1412
RLRiedinger 6:b57b71c0879a 1413 _reset = new DigitalOut(rst); // Construct new pin
RLRiedinger 6:b57b71c0879a 1414 _reset->write(1); // Deactivate
RLRiedinger 6:b57b71c0879a 1415
RLRiedinger 6:b57b71c0879a 1416 } else {
RLRiedinger 6:b57b71c0879a 1417
RLRiedinger 6:b57b71c0879a 1418 // No Hardware Reset pin
RLRiedinger 6:b57b71c0879a 1419
RLRiedinger 6:b57b71c0879a 1420 _reset = NULL; // Construct dummy pin
RLRiedinger 6:b57b71c0879a 1421
RLRiedinger 6:b57b71c0879a 1422 }
RLRiedinger 6:b57b71c0879a 1423
RLRiedinger 6:b57b71c0879a 1424 // Dont call _init() until I2C port has been configured.
RLRiedinger 6:b57b71c0879a 1425 // That is why _init() is not called in parent Constructor
RLRiedinger 6:b57b71c0879a 1426
RLRiedinger 6:b57b71c0879a 1427 _init();
wim 4:12446ee9f9c8 1428
wim 4:12446ee9f9c8 1429 }
wim 4:12446ee9f9c8 1430
RLRiedinger 6:b57b71c0879a 1431 /*
RLRiedinger 6:b57b71c0879a 1432 * Destruct SC16IS752_I2C bridge object
RLRiedinger 6:b57b71c0879a 1433 *
RLRiedinger 6:b57b71c0879a 1434 * @param none
RLRiedinger 6:b57b71c0879a 1435 * @return none
RLRiedinger 6:b57b71c0879a 1436 */
wim 4:12446ee9f9c8 1437
RLRiedinger 6:b57b71c0879a 1438 SC16IS752_I2C::~SC16IS752_I2C() {
wim 4:12446ee9f9c8 1439
RLRiedinger 6:b57b71c0879a 1440 if (_reset != NULL) {delete _reset;} // Reset pin
RLRiedinger 6:b57b71c0879a 1441
wim 4:12446ee9f9c8 1442 }
RLRiedinger 6:b57b71c0879a 1443
RLRiedinger 6:b57b71c0879a 1444 /*
RLRiedinger 6:b57b71c0879a 1445 * Write value to internal register.
RLRiedinger 6:b57b71c0879a 1446 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1447 * @param data The 8bit value to write
RLRiedinger 6:b57b71c0879a 1448 * @return none
RLRiedinger 6:b57b71c0879a 1449 */
wim 4:12446ee9f9c8 1450
RLRiedinger 6:b57b71c0879a 1451 void SC16IS752_I2C::writeRegister(RegisterName registerAddress, char data) {
RLRiedinger 6:b57b71c0879a 1452
RLRiedinger 6:b57b71c0879a 1453 char w[2];
RLRiedinger 6:b57b71c0879a 1454
RLRiedinger 6:b57b71c0879a 1455 w[0] = registerAddress | _channel;
RLRiedinger 6:b57b71c0879a 1456 w[1] = data;
RLRiedinger 6:b57b71c0879a 1457
RLRiedinger 6:b57b71c0879a 1458 _i2c->write( _slaveAddress, w, 2 );
RLRiedinger 6:b57b71c0879a 1459
RLRiedinger 6:b57b71c0879a 1460 }
RLRiedinger 6:b57b71c0879a 1461
RLRiedinger 6:b57b71c0879a 1462 /*
RLRiedinger 6:b57b71c0879a 1463 * Read value from internal register.
RLRiedinger 6:b57b71c0879a 1464 * @param registerAddress The address of the Register (enum RegisterName)
RLRiedinger 6:b57b71c0879a 1465 * @return char The 8bit value read from the register
RLRiedinger 6:b57b71c0879a 1466 */
wim 4:12446ee9f9c8 1467
RLRiedinger 6:b57b71c0879a 1468 char SC16IS752_I2C::readRegister(RegisterName registerAddress) {
RLRiedinger 6:b57b71c0879a 1469
RLRiedinger 6:b57b71c0879a 1470 /*
RLRiedinger 6:b57b71c0879a 1471 * Read char from SC16IS752 register at <registerAddress>.
RLRiedinger 6:b57b71c0879a 1472 */
RLRiedinger 6:b57b71c0879a 1473
RLRiedinger 6:b57b71c0879a 1474 char w[1];
RLRiedinger 6:b57b71c0879a 1475 char r[1];
RLRiedinger 6:b57b71c0879a 1476
RLRiedinger 6:b57b71c0879a 1477 w[0] = registerAddress | _channel;
RLRiedinger 6:b57b71c0879a 1478
RLRiedinger 6:b57b71c0879a 1479 // _i2c->write( _slaveAddress, w, 1);
RLRiedinger 6:b57b71c0879a 1480 _i2c->write(_slaveAddress, w, 1, true); // Repeated Start
RLRiedinger 6:b57b71c0879a 1481 _i2c->read(_slaveAddress, r, 1);
RLRiedinger 6:b57b71c0879a 1482
RLRiedinger 6:b57b71c0879a 1483 return (r[0]);
wim 4:12446ee9f9c8 1484
RLRiedinger 6:b57b71c0879a 1485 }
RLRiedinger 6:b57b71c0879a 1486
RLRiedinger 6:b57b71c0879a 1487 /*
RLRiedinger 6:b57b71c0879a 1488 * Write multiple datavalues to Transmitregister.
RLRiedinger 6:b57b71c0879a 1489 * More Efficient implementation than writing individual bytes
RLRiedinger 6:b57b71c0879a 1490 * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1491 * Pure virtual, must be declared in derived class.
RLRiedinger 6:b57b71c0879a 1492 * @param char* databytes The pointer to the block of data
RLRiedinger 6:b57b71c0879a 1493 * @param len The number of bytes to write
RLRiedinger 6:b57b71c0879a 1494 * @return none
RLRiedinger 6:b57b71c0879a 1495 */
wim 4:12446ee9f9c8 1496
RLRiedinger 6:b57b71c0879a 1497 void SC16IS752_I2C::writeDataBlock (const char *data, int len) {
wim 4:12446ee9f9c8 1498
RLRiedinger 6:b57b71c0879a 1499 #if (0)
RLRiedinger 6:b57b71c0879a 1500
RLRiedinger 6:b57b71c0879a 1501 int i;
RLRiedinger 6:b57b71c0879a 1502 char w[BULK_BLOCK_LEN];
RLRiedinger 6:b57b71c0879a 1503
RLRiedinger 6:b57b71c0879a 1504 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 1505 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1506
RLRiedinger 6:b57b71c0879a 1507 w[0] = THR | _channel;
RLRiedinger 6:b57b71c0879a 1508
RLRiedinger 6:b57b71c0879a 1509 // Copy the data ...
RLRiedinger 6:b57b71c0879a 1510
RLRiedinger 6:b57b71c0879a 1511 for (i = 0; i < len; i++) {
RLRiedinger 6:b57b71c0879a 1512
RLRiedinger 6:b57b71c0879a 1513 w[i+1] = data[i];
RLRiedinger 6:b57b71c0879a 1514
RLRiedinger 6:b57b71c0879a 1515 }
RLRiedinger 6:b57b71c0879a 1516
RLRiedinger 6:b57b71c0879a 1517 _i2c->write(_slaveAddress, w, len + 1);
RLRiedinger 6:b57b71c0879a 1518
RLRiedinger 6:b57b71c0879a 1519 #else
RLRiedinger 6:b57b71c0879a 1520
RLRiedinger 6:b57b71c0879a 1521 int i;
RLRiedinger 6:b57b71c0879a 1522
RLRiedinger 6:b57b71c0879a 1523 _i2c->start();
RLRiedinger 6:b57b71c0879a 1524 _i2c->write(_slaveAddress);
RLRiedinger 6:b57b71c0879a 1525
RLRiedinger 6:b57b71c0879a 1526 // Select the Transmit Holding Register
RLRiedinger 6:b57b71c0879a 1527 // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
RLRiedinger 6:b57b71c0879a 1528
RLRiedinger 6:b57b71c0879a 1529 _i2c->write(THR | _channel);
RLRiedinger 6:b57b71c0879a 1530
RLRiedinger 6:b57b71c0879a 1531 // Send the data ...
RLRiedinger 6:b57b71c0879a 1532
RLRiedinger 6:b57b71c0879a 1533 for (i = 0; i < len; i++) {
RLRiedinger 6:b57b71c0879a 1534
RLRiedinger 6:b57b71c0879a 1535 _i2c->write(data[i]);
RLRiedinger 6:b57b71c0879a 1536
RLRiedinger 6:b57b71c0879a 1537 }
RLRiedinger 6:b57b71c0879a 1538
RLRiedinger 6:b57b71c0879a 1539 _i2c->stop();
RLRiedinger 6:b57b71c0879a 1540
RLRiedinger 6:b57b71c0879a 1541 #endif
wim 4:12446ee9f9c8 1542
RLRiedinger 6:b57b71c0879a 1543 }
RLRiedinger 6:b57b71c0879a 1544
RLRiedinger 6:b57b71c0879a 1545 /*
RLRiedinger 6:b57b71c0879a 1546 * Hardware Reset SC16IS752 device.
RLRiedinger 6:b57b71c0879a 1547 * This method is only available when the Reset pin has been declared and is also connected
RLRiedinger 6:b57b71c0879a 1548 * @param none
RLRiedinger 6:b57b71c0879a 1549 * @return none
RLRiedinger 6:b57b71c0879a 1550 */
RLRiedinger 6:b57b71c0879a 1551
wim 4:12446ee9f9c8 1552 void SC16IS752_I2C::hwReset() {
RLRiedinger 6:b57b71c0879a 1553
RLRiedinger 6:b57b71c0879a 1554 if (_reset != NULL){
RLRiedinger 6:b57b71c0879a 1555
RLRiedinger 6:b57b71c0879a 1556 _reset->write(0); //activate
RLRiedinger 6:b57b71c0879a 1557
RLRiedinger 6:b57b71c0879a 1558 // wait_ms(100);
RLRiedinger 6:b57b71c0879a 1559
RLRiedinger 6:b57b71c0879a 1560 wait_ms(1000); //test only
RLRiedinger 6:b57b71c0879a 1561
RLRiedinger 6:b57b71c0879a 1562 _reset->write(1); //deactivate
RLRiedinger 6:b57b71c0879a 1563
RLRiedinger 6:b57b71c0879a 1564
RLRiedinger 6:b57b71c0879a 1565 } else {
RLRiedinger 6:b57b71c0879a 1566
RLRiedinger 6:b57b71c0879a 1567 printf("Hardware Reset pin is not available...\n\r");
RLRiedinger 6:b57b71c0879a 1568
RLRiedinger 6:b57b71c0879a 1569 }
RLRiedinger 6:b57b71c0879a 1570
wim 4:12446ee9f9c8 1571 }
wim 4:12446ee9f9c8 1572
wim 4:12446ee9f9c8 1573 //
wim 4:12446ee9f9c8 1574 // End I2C Implementation
wim 4:12446ee9f9c8 1575 //