MAX3100, an external serial device to add additional serial ports via SPI

Committer:
elelthvd
Date:
Tue Aug 04 06:47:16 2020 +0000
Revision:
3:6304e14baed8
Parent:
2:2a49171453d5
Comment out irqmask functions.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:055897ab699b 1 /*
AjK 0:055897ab699b 2 Copyright (c) 2011 Andy Kirkham
AjK 0:055897ab699b 3
AjK 0:055897ab699b 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 0:055897ab699b 5 of this software and associated documentation files (the "Software"), to deal
AjK 0:055897ab699b 6 in the Software without restriction, including without limitation the rights
AjK 0:055897ab699b 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 0:055897ab699b 8 copies of the Software, and to permit persons to whom the Software is
AjK 0:055897ab699b 9 furnished to do so, subject to the following conditions:
AjK 0:055897ab699b 10
AjK 0:055897ab699b 11 The above copyright notice and this permission notice shall be included in
AjK 0:055897ab699b 12 all copies or substantial portions of the Software.
AjK 0:055897ab699b 13
AjK 0:055897ab699b 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 0:055897ab699b 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 0:055897ab699b 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 0:055897ab699b 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 0:055897ab699b 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 0:055897ab699b 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 0:055897ab699b 20 THE SOFTWARE.
AjK 0:055897ab699b 21 */
AjK 0:055897ab699b 22
AjK 0:055897ab699b 23
AjK 0:055897ab699b 24 #ifndef AJK_MAX31000_H
AjK 0:055897ab699b 25 #define AJK_MAX31000_H
AjK 0:055897ab699b 26
AjK 0:055897ab699b 27 #ifndef MBED_H
AjK 0:055897ab699b 28 #include "mbed.h"
elelthvd 3:6304e14baed8 29 #include <Stream.h>
AjK 0:055897ab699b 30 #endif
AjK 0:055897ab699b 31
AjK 0:055897ab699b 32 #ifndef MAX3100_TX_BUFFER_SIZE
AjK 0:055897ab699b 33 #define MAX3100_TX_BUFFER_SIZE 32
AjK 0:055897ab699b 34 #endif
AjK 0:055897ab699b 35
AjK 0:055897ab699b 36 #ifndef MAX3100_RX_BUFFER_SIZE
AjK 0:055897ab699b 37 #define MAX3100_RX_BUFFER_SIZE 32
AjK 0:055897ab699b 38 #endif
AjK 0:055897ab699b 39
AjK 0:055897ab699b 40 #ifndef MAX3100_SPI_FREQ
AjK 0:055897ab699b 41 #define MAX3100_SPI_FREQ 5000000
AjK 0:055897ab699b 42 #endif
AjK 0:055897ab699b 43
AjK 0:055897ab699b 44 #define MAX3100_CONF_WR (3U << 14)
AjK 0:055897ab699b 45 #define MAX3100_CONF_RD (1U << 14)
AjK 0:055897ab699b 46 #define MAX3100_CONF_T (1U << 14)
AjK 0:055897ab699b 47 #define MAX3100_CONF_R (1U << 15)
AjK 0:055897ab699b 48 #define MAX3100_FEN(x) (x << 13)
AjK 0:055897ab699b 49 #define MAX3100_SHDNi(x) (x << 12)
AjK 0:055897ab699b 50 #define MAX3100_TM(x) (x << 11)
AjK 0:055897ab699b 51 #define MAX3100_RM(x) (x << 10)
AjK 0:055897ab699b 52 #define MAX3100_PM(x) (x << 9)
AjK 0:055897ab699b 53 #define MAX3100_RAM(x) (x << 8)
AjK 0:055897ab699b 54 #define MAX3100_IR(x) (x << 7)
AjK 0:055897ab699b 55 #define MAX3100_ST(x) (x << 6)
AjK 0:055897ab699b 56 #define MAX3100_PE(x) (x << 5)
AjK 0:055897ab699b 57 #define MAX3100_L(x) (x << 4)
AjK 0:055897ab699b 58 #define MAX3100_BAUD(x) (x << 0)
AjK 0:055897ab699b 59
AjK 0:055897ab699b 60 #define MAX3100_DATA_WR (2U << 14)
AjK 0:055897ab699b 61 #define MAX3100_DATA_RD (0)
AjK 0:055897ab699b 62 #define MAX3100_TE(x) (x << 10)
AjK 0:055897ab699b 63 #define MAX3100_RAFE(x) (x << 10)
AjK 0:055897ab699b 64 #define MAX3100_RTS(x) (x << 9)
AjK 0:055897ab699b 65 #define MAX3100_CTS(x) (x << 9)
AjK 0:055897ab699b 66 #define MAX3100_PT(x) (x << 8)
AjK 0:055897ab699b 67 #define MAX3100_PR(x) (x << 8)
AjK 0:055897ab699b 68
AjK 0:055897ab699b 69 namespace AjK {
AjK 0:055897ab699b 70
AjK 0:055897ab699b 71 class MAX3100Dummy;
AjK 0:055897ab699b 72
AjK 0:055897ab699b 73 /** MAX3100 An external serial IO device.
AjK 0:055897ab699b 74 *
AjK 0:055897ab699b 75 * The MAX3100 librray is designed to allow the easy attachment of additional
AjK 0:055897ab699b 76 * serial ports to the Mbed. We all know that the Mbed already has 3 potential
AjK 0:055897ab699b 77 * serial ports. But maybe you need more ports or maybe you need to use the Mbed
AjK 0:055897ab699b 78 * pins for an alternative function. The MAX3100 may well be able to help in
AjK 0:055897ab699b 79 * situations like these.
AjK 0:055897ab699b 80 *
AjK 0:055897ab699b 81 * Each MAX3100 device you create in is TX/RX buffered with 32 characters in a circular
AjK 0:055897ab699b 82 * buffer system.
AjK 0:055897ab699b 83 *
AjK 0:055897ab699b 84 * The MAX3100 uses at least one Mbed SPI port and additional DigitalOut and InterruptIn
AjK 0:055897ab699b 85 * pins to work. However, you can attach multiple MAX3100 devices to a single SPI "bus".
AjK 0:055897ab699b 86 *
AjK 0:055897ab699b 87 * For more information on attaching multiple devices see all the examples listed below.
AjK 0:055897ab699b 88 *
AjK 0:055897ab699b 89 * @see example1.h
AjK 0:055897ab699b 90 * @see example2.h
AjK 0:055897ab699b 91 * @see example3.h
AjK 0:055897ab699b 92 * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
AjK 0:055897ab699b 93 */
AjK 0:055897ab699b 94 class MAX3100 : public Stream {
AjK 0:055897ab699b 95
AjK 0:055897ab699b 96 protected:
AjK 0:055897ab699b 97
AjK 0:055897ab699b 98 SPI *_spi;
AjK 0:055897ab699b 99 DigitalOut *_cs;
AjK 0:055897ab699b 100 InterruptIn *_irq;
AjK 0:055897ab699b 101
AjK 0:055897ab699b 102 uint16_t tx_buffer[MAX3100_TX_BUFFER_SIZE];
AjK 0:055897ab699b 103 int tx_buffer_in;
AjK 0:055897ab699b 104 int tx_buffer_out;
AjK 0:055897ab699b 105 bool tx_buffer_full;
AjK 0:055897ab699b 106
AjK 0:055897ab699b 107 uint16_t rx_buffer[MAX3100_RX_BUFFER_SIZE];
AjK 0:055897ab699b 108 int rx_buffer_in;
AjK 0:055897ab699b 109 int rx_buffer_out;
AjK 0:055897ab699b 110 bool rx_buffer_full;
AjK 0:055897ab699b 111
AjK 0:055897ab699b 112 uint16_t config;
AjK 0:055897ab699b 113 int _device;
AjK 0:055897ab699b 114 int _parity;
AjK 0:055897ab699b 115
AjK 1:46c8c60e744a 116 uint32_t _irqMask0, _irqMask2;
AjK 1:46c8c60e744a 117
AjK 1:46c8c60e744a 118 void irqDisable(void);
AjK 1:46c8c60e744a 119 void irqEnable(void);
AjK 1:46c8c60e744a 120
AjK 0:055897ab699b 121 virtual int _putc(int c) { return putc(c); }
AjK 0:055897ab699b 122 virtual int _getc() { return getc(); }
AjK 0:055897ab699b 123
AjK 0:055897ab699b 124 /** init
AjK 0:055897ab699b 125 *
AjK 0:055897ab699b 126 * Initialise the device.
AjK 0:055897ab699b 127 * @param PinName SPI mosi
AjK 0:055897ab699b 128 * @param PinName SPI miso
AjK 0:055897ab699b 129 * @param PinName SPI sclk
AjK 0:055897ab699b 130 * @param PinName DigitalOut cs
AjK 0:055897ab699b 131 * @param PinName InterruptIn irq
AjK 0:055897ab699b 132 * @param SPI * A pointer to a shared SPI bus
AjK 0:055897ab699b 133 */
AjK 0:055897ab699b 134 void init(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, SPI *spi = (SPI *)NULL);
AjK 0:055897ab699b 135
AjK 0:055897ab699b 136 uint16_t spiwrite(uint16_t val);
AjK 0:055897ab699b 137 uint16_t config_write(uint16_t val);
AjK 0:055897ab699b 138 uint16_t config_read(void);
AjK 0:055897ab699b 139
AjK 0:055897ab699b 140 // C style callback function pointer for external CS control.
AjK 0:055897ab699b 141 void (*_cs_function)(int, int);
AjK 0:055897ab699b 142
AjK 0:055897ab699b 143 // C++ style callback method pointer for external CS control
AjK 0:055897ab699b 144 MAX3100Dummy *_cs_obj;
AjK 0:055897ab699b 145 void (MAX3100Dummy::*_cs_method)(int, int);
AjK 0:055897ab699b 146
AjK 2:2a49171453d5 147 // C style callback function pointer for user isr callback.
AjK 2:2a49171453d5 148 void (*_isr_user_function)(int);
AjK 2:2a49171453d5 149
AjK 2:2a49171453d5 150 // C++ style callback method pointer for external CS control
AjK 2:2a49171453d5 151 MAX3100Dummy *_isr_user_obj;
AjK 2:2a49171453d5 152 void (MAX3100Dummy::*_isr_user_method)(int);
AjK 2:2a49171453d5 153
AjK 0:055897ab699b 154 // Internal CS control.
AjK 0:055897ab699b 155 void cs_value(int);
AjK 0:055897ab699b 156
AjK 0:055897ab699b 157 // calculate byte parity.
AjK 0:055897ab699b 158 int parityCal(uint8_t c);
AjK 1:46c8c60e744a 159
elelthvd 3:6304e14baed8 160 // // http://mbed.org/forum/bugs-suggestions/topic/1498
elelthvd 3:6304e14baed8 161 // void topic_1498(PinName p);
AjK 0:055897ab699b 162
AjK 0:055897ab699b 163 public:
AjK 0:055897ab699b 164
AjK 2:2a49171453d5 165 static const int ISR = 0;
AjK 2:2a49171453d5 166
AjK 2:2a49171453d5 167 static const int ISR_RX = 1;
AjK 2:2a49171453d5 168
AjK 2:2a49171453d5 169 static const int ISR_TX = 2;
AjK 2:2a49171453d5 170
AjK 0:055897ab699b 171 /** Constructor
AjK 0:055897ab699b 172 */
AjK 0:055897ab699b 173 MAX3100() { error( "No pins supplied to constructor" ); }
AjK 0:055897ab699b 174
AjK 0:055897ab699b 175 /** Constructor
AjK 0:055897ab699b 176 */
AjK 0:055897ab699b 177 MAX3100(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, int device = 0) {
AjK 0:055897ab699b 178 _device = device;
AjK 0:055897ab699b 179 init( mosi, miso, sclk, cs, irq);
AjK 0:055897ab699b 180 }
AjK 0:055897ab699b 181
AjK 0:055897ab699b 182 /** Constructor
AjK 0:055897ab699b 183 */
AjK 0:055897ab699b 184 MAX3100(SPI *spi, PinName cs, PinName irq, int device = 0) {
AjK 0:055897ab699b 185 _device = device;
AjK 0:055897ab699b 186 init( NC, NC, NC, cs, irq, spi);
AjK 0:055897ab699b 187 }
AjK 0:055897ab699b 188
AjK 0:055897ab699b 189 /** Destructor
AjK 0:055897ab699b 190 */
AjK 0:055897ab699b 191 virtual ~MAX3100() {
AjK 0:055897ab699b 192 if ( _spi ) delete( _spi );
AjK 0:055897ab699b 193 if ( _irq ) delete( _irq );
AjK 0:055897ab699b 194 if ( _cs ) delete( _cs );
AjK 0:055897ab699b 195 }
AjK 0:055897ab699b 196
AjK 0:055897ab699b 197 enum Parity {
AjK 0:055897ab699b 198 None = 0
AjK 0:055897ab699b 199 , Odd
AjK 0:055897ab699b 200 , Even
AjK 0:055897ab699b 201 , Forced1
AjK 0:055897ab699b 202 , Forced0
AjK 0:055897ab699b 203 };
AjK 0:055897ab699b 204
AjK 0:055897ab699b 205 /** setParity
AjK 0:055897ab699b 206 *
AjK 0:055897ab699b 207 * Set the parity of the system. Default is None.
AjK 0:055897ab699b 208 *
AjK 0:055897ab699b 209 * @param Parity None, Odd, Even
AjK 0:055897ab699b 210 */
AjK 0:055897ab699b 211 void setParity(int p) { _parity = p; }
AjK 0:055897ab699b 212
AjK 0:055897ab699b 213 /** setStopBits
AjK 0:055897ab699b 214 *
AjK 0:055897ab699b 215 * Set the number of stop bits. Default is One.
AjK 0:055897ab699b 216 *
AjK 0:055897ab699b 217 * @param int 1 or 2
AjK 0:055897ab699b 218 */
AjK 0:055897ab699b 219 void setStopBits(int i);
AjK 0:055897ab699b 220
AjK 0:055897ab699b 221 /** System interrupt service routine.
AjK 0:055897ab699b 222 */
AjK 0:055897ab699b 223 void isr(void);
AjK 0:055897ab699b 224
AjK 0:055897ab699b 225 /** baud
AjK 0:055897ab699b 226 * Set the system baud. Default is "10" (9600). Note,
AjK 0:055897ab699b 227 * this is not like Mbed's Serial where you pass the
AjK 0:055897ab699b 228 * baud rate you want. The MAX3100 has 16 possible
AjK 0:055897ab699b 229 * preset prescalers you can choose from. See the datasheet
AjK 0:055897ab699b 230 * for more info.
AjK 0:055897ab699b 231 *
AjK 0:055897ab699b 232 * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
AjK 0:055897ab699b 233 * @param int A number from 0 to 15 indicating which prescaler to use.
AjK 0:055897ab699b 234 */
AjK 0:055897ab699b 235 void baud(int baudrate);
AjK 0:055897ab699b 236
AjK 0:055897ab699b 237 /** enableRxIrq
AjK 0:055897ab699b 238 */
AjK 0:055897ab699b 239 void enableRxIrq(void);
AjK 0:055897ab699b 240
AjK 0:055897ab699b 241 /** disableRxIrq
AjK 0:055897ab699b 242 */
AjK 0:055897ab699b 243 void disableRxIrq(void);
AjK 0:055897ab699b 244
AjK 0:055897ab699b 245 /** enableTxIrq
AjK 0:055897ab699b 246 */
AjK 0:055897ab699b 247 void enableTxIrq(void);
AjK 0:055897ab699b 248
AjK 0:055897ab699b 249 /** disableTxIrq
AjK 0:055897ab699b 250 */
AjK 0:055897ab699b 251 void disableTxIrq(void);
AjK 0:055897ab699b 252
AjK 0:055897ab699b 253 /** putc
AjK 0:055897ab699b 254 * @param int c The byte to write.
AjK 0:055897ab699b 255 */
AjK 0:055897ab699b 256 int putc(int c);
AjK 0:055897ab699b 257
AjK 0:055897ab699b 258 /** puts
AjK 0:055897ab699b 259 * @param char * The string to print.
AjK 0:055897ab699b 260 */
AjK 0:055897ab699b 261 void puts(char *s);
AjK 0:055897ab699b 262
AjK 0:055897ab699b 263 /** getc
AjK 0:055897ab699b 264 * @return int c The byte read or -1 if no bytes to read.
AjK 0:055897ab699b 265 */
AjK 0:055897ab699b 266 int getc(void);
AjK 0:055897ab699b 267
AjK 0:055897ab699b 268 /** gets
AjK 0:055897ab699b 269 * Get a string. Note, this method blocks until size bytes are read.
AjK 0:055897ab699b 270 * @param char *s where to place the incoming bytes.
AjK 0:055897ab699b 271 * @param int size How many bytes to read.
AjK 0:055897ab699b 272 * @return char * The value of *s passed in.
AjK 0:055897ab699b 273 */
AjK 0:055897ab699b 274 char *gets(char *s, int size);
AjK 0:055897ab699b 275
AjK 0:055897ab699b 276 /** peek
AjK 0:055897ab699b 277 * like getc() but does NOT remove the byte from the buffer.
AjK 0:055897ab699b 278 * @see getc*(
AjK 0:055897ab699b 279 */
AjK 0:055897ab699b 280 int peek(void);
AjK 0:055897ab699b 281
AjK 0:055897ab699b 282 /** readable
AjK 0:055897ab699b 283 * Are any byte(s) available in the RX buffer?
AjK 0:055897ab699b 284 * @return 0 if none, 1 otherwise.
AjK 0:055897ab699b 285 */
AjK 0:055897ab699b 286 int readable(void) { return (rx_buffer_in != rx_buffer_out || rx_buffer_full) ? 1 : 0; }
AjK 0:055897ab699b 287
AjK 0:055897ab699b 288 /** writable
AjK 0:055897ab699b 289 * Can we write a byte to teh serial stream?
AjK 0:055897ab699b 290 * @return non-zero if we can, zero otherwise.
AjK 0:055897ab699b 291 */
AjK 0:055897ab699b 292 int writable(void) { return tx_buffer_full ? 0 : 1; }
AjK 0:055897ab699b 293
AjK 0:055897ab699b 294 /** setDevice
AjK 0:055897ab699b 295 * Give this device an "address".
AjK 0:055897ab699b 296 * @param int i An address to use in callbacks.
AjK 0:055897ab699b 297 */
AjK 0:055897ab699b 298 void setDevice(int i) { _device = i; }
AjK 0:055897ab699b 299
AjK 0:055897ab699b 300 /** flushTxBuffer
AjK 0:055897ab699b 301 *
AjK 0:055897ab699b 302 * Flush the TX buffer.
AjK 0:055897ab699b 303 */
AjK 0:055897ab699b 304 void flushTxBuffer(void) { tx_buffer_in = tx_buffer_out = 0; tx_buffer_full = false; }
AjK 0:055897ab699b 305
AjK 0:055897ab699b 306 /** flushRxBuffer
AjK 0:055897ab699b 307 *
AjK 0:055897ab699b 308 * Flush the RX buffer.
AjK 0:055897ab699b 309 */
AjK 0:055897ab699b 310 void flushRxBuffer(void) { rx_buffer_in = rx_buffer_out = 0; rx_buffer_full = false; }
AjK 0:055897ab699b 311
elelthvd 3:6304e14baed8 312 // /** irqMask
elelthvd 3:6304e14baed8 313 // * Setup the mask for enable/disable interrupts.
elelthvd 3:6304e14baed8 314 // * @see example3.h
elelthvd 3:6304e14baed8 315 // * @param PinName p The InterruptIn pin.
elelthvd 3:6304e14baed8 316 // */
elelthvd 3:6304e14baed8 317 // void irqMask(PinName p);
AjK 1:46c8c60e744a 318
AjK 0:055897ab699b 319 /** attach_cs
AjK 0:055897ab699b 320 * Attach a C style callback function pointer. Used if an external function
AjK 0:055897ab699b 321 * is controlling the chip CS line.
AjK 0:055897ab699b 322 * @param function A C function pointer
AjK 0:055897ab699b 323 */
AjK 0:055897ab699b 324 void attach_cs(void (*function)(int, int) = 0) { _cs_function = function; }
AjK 0:055897ab699b 325
AjK 0:055897ab699b 326 /** attach_cs
AjK 0:055897ab699b 327 * Attach a C++ object/method pointer. Used if an external function
AjK 0:055897ab699b 328 * @param object An object that conatins the callback method.
AjK 0:055897ab699b 329 * @param method The method within the object to call.
AjK 0:055897ab699b 330 */
AjK 0:055897ab699b 331 template<class T>
AjK 1:46c8c60e744a 332 void attach_cs(T* item, void (T::*method)(int, int)) {
AjK 1:46c8c60e744a 333 _cs_obj = (MAX3100Dummy *)item; _cs_method = (void (MAX3100Dummy::*)(int, int))method;
AjK 1:46c8c60e744a 334 }
AjK 0:055897ab699b 335
AjK 2:2a49171453d5 336 /** attach_isr_user
AjK 2:2a49171453d5 337 * is controlling the chip CS line.
AjK 2:2a49171453d5 338 * @param function A C function pointer
AjK 2:2a49171453d5 339 */
AjK 2:2a49171453d5 340 void attach_isr_user(void (*function)(int) = 0) { _isr_user_function = function; }
AjK 2:2a49171453d5 341
AjK 2:2a49171453d5 342 /** attach_isr_user
AjK 2:2a49171453d5 343 * @param object An object that conatins the callback method.
AjK 2:2a49171453d5 344 * @param method The method within the object to call.
AjK 2:2a49171453d5 345 */
AjK 2:2a49171453d5 346 template<class T>
AjK 2:2a49171453d5 347 void attach_isr_user(T* item, void (T::*method)(int)) {
AjK 2:2a49171453d5 348 _isr_user_obj = (MAX3100Dummy *)item; _isr_user_method = (void (MAX3100Dummy::*)(int))method;
AjK 2:2a49171453d5 349 }
AjK 2:2a49171453d5 350
AjK 0:055897ab699b 351 };
AjK 0:055897ab699b 352
AjK 0:055897ab699b 353 }; // namespace AjK ends.
AjK 0:055897ab699b 354
AjK 0:055897ab699b 355 using namespace AjK;
AjK 0:055897ab699b 356
AjK 0:055897ab699b 357 #endif