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

Dependents:   FLIGHT_CONTROL_AND_COMMUNICATIONS_SYSTEM

Committer:
AjK
Date:
Fri Aug 03 12:28:27 2012 +0000
Revision:
2:2a49171453d5
Parent:
1:46c8c60e744a
Add example4.h and ISR user callback code

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