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

Dependents:   FLIGHT_CONTROL_AND_COMMUNICATIONS_SYSTEM

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX3100.h Source File

MAX3100.h

00001 /*
00002     Copyright (c) 2011 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021 */
00022 
00023 
00024 #ifndef AJK_MAX31000_H
00025 #define AJK_MAX31000_H
00026 
00027 #ifndef MBED_H
00028 #include "mbed.h"
00029 #endif
00030 
00031 #ifndef MAX3100_TX_BUFFER_SIZE
00032 #define MAX3100_TX_BUFFER_SIZE  32
00033 #endif
00034 
00035 #ifndef MAX3100_RX_BUFFER_SIZE
00036 #define MAX3100_RX_BUFFER_SIZE  32
00037 #endif
00038 
00039 #ifndef MAX3100_SPI_FREQ
00040 #define MAX3100_SPI_FREQ    5000000
00041 #endif
00042 
00043 #define MAX3100_CONF_WR     (3U << 14)
00044 #define MAX3100_CONF_RD     (1U << 14)
00045 #define MAX3100_CONF_T      (1U << 14)
00046 #define MAX3100_CONF_R      (1U << 15)
00047 #define MAX3100_FEN(x)      (x << 13)
00048 #define MAX3100_SHDNi(x)    (x << 12)
00049 #define MAX3100_TM(x)       (x << 11)
00050 #define MAX3100_RM(x)       (x << 10)
00051 #define MAX3100_PM(x)       (x <<  9)
00052 #define MAX3100_RAM(x)      (x <<  8)
00053 #define MAX3100_IR(x)       (x <<  7)
00054 #define MAX3100_ST(x)       (x <<  6)
00055 #define MAX3100_PE(x)       (x <<  5)
00056 #define MAX3100_L(x)        (x <<  4)
00057 #define MAX3100_BAUD(x)     (x <<  0)        
00058 
00059 #define MAX3100_DATA_WR     (2U << 14)
00060 #define MAX3100_DATA_RD     (0)
00061 #define MAX3100_TE(x)       (x << 10)
00062 #define MAX3100_RAFE(x)     (x << 10)
00063 #define MAX3100_RTS(x)      (x <<  9)
00064 #define MAX3100_CTS(x)      (x <<  9)
00065 #define MAX3100_PT(x)       (x <<  8)
00066 #define MAX3100_PR(x)       (x <<  8)
00067 
00068 namespace AjK {
00069 
00070 class MAX3100Dummy;
00071 
00072 /** MAX3100 An external serial IO device.
00073  *
00074  * The MAX3100 librray is designed to allow the easy attachment of additional
00075  * serial ports to the Mbed. We all know that the Mbed already has 3 potential
00076  * serial ports. But maybe you need more ports or maybe you need to use the Mbed
00077  * pins for an alternative function. The MAX3100 may well be able to help in 
00078  * situations like these. 
00079  *
00080  * Each MAX3100 device you create in is TX/RX buffered with 32 characters in a circular
00081  * buffer system.
00082  *
00083  * The MAX3100 uses at least one Mbed SPI port and additional DigitalOut and InterruptIn
00084  * pins to work. However, you can attach multiple MAX3100 devices to a single SPI "bus".
00085  *
00086  * For more information on attaching multiple devices see all the examples listed below.
00087  *
00088  * @see example1.h
00089  * @see example2.h
00090  * @see example3.h
00091  * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
00092  */
00093 class MAX3100 : public Stream {
00094 
00095 protected:
00096     
00097     SPI         *_spi;
00098     DigitalOut  *_cs;
00099     InterruptIn *_irq;
00100     
00101     uint16_t tx_buffer[MAX3100_TX_BUFFER_SIZE];
00102     int  tx_buffer_in;
00103     int  tx_buffer_out;
00104     bool tx_buffer_full;
00105     
00106     uint16_t rx_buffer[MAX3100_RX_BUFFER_SIZE];
00107     int  rx_buffer_in;
00108     int  rx_buffer_out;
00109     bool rx_buffer_full;
00110     
00111     uint16_t    config;
00112     int         _device;
00113     int         _parity;
00114     
00115     uint32_t _irqMask0, _irqMask2;
00116     
00117     void irqDisable(void);
00118     void irqEnable(void);
00119         
00120     virtual int _putc(int c) { return putc(c); }
00121     virtual int _getc()      { return getc(); }
00122 
00123     /** init
00124      *
00125      * Initialise the device.
00126      * @param PinName SPI mosi
00127      * @param PinName SPI miso
00128      * @param PinName SPI sclk
00129      * @param PinName DigitalOut cs
00130      * @param PinName InterruptIn irq
00131      * @param SPI * A pointer to a shared SPI bus
00132      */
00133     void init(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, SPI *spi = (SPI *)NULL);    
00134     
00135     uint16_t spiwrite(uint16_t val);        
00136     uint16_t config_write(uint16_t val);
00137     uint16_t config_read(void);
00138 
00139     // C style callback function pointer for external CS control.    
00140     void (*_cs_function)(int, int); 
00141     
00142     // C++ style callback method pointer for external CS control
00143     MAX3100Dummy  *_cs_obj;
00144     void (MAX3100Dummy::*_cs_method)(int, int);
00145 
00146     // C style callback function pointer for user isr callback.    
00147     void (*_isr_user_function)(int); 
00148 
00149     // C++ style callback method pointer for external CS control
00150     MAX3100Dummy  *_isr_user_obj;
00151     void (MAX3100Dummy::*_isr_user_method)(int);
00152     
00153     // Internal CS control.
00154     void cs_value(int);
00155     
00156     // calculate byte parity.
00157     int parityCal(uint8_t c);
00158 
00159     // http://mbed.org/forum/bugs-suggestions/topic/1498
00160     void topic_1498(PinName p); 
00161 
00162 public:
00163     
00164     static const int ISR    = 0;
00165     
00166     static const int ISR_RX = 1;
00167     
00168     static const int ISR_TX = 2;
00169     
00170     /** Constructor
00171      */
00172     MAX3100() { error( "No pins supplied to constructor" ); }
00173     
00174     /** Constructor
00175      */
00176     MAX3100(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, int device = 0) {
00177         _device = device;
00178         init( mosi, miso, sclk, cs, irq);
00179     }
00180     
00181     /** Constructor
00182      */
00183     MAX3100(SPI *spi, PinName cs, PinName irq, int device = 0) {
00184         _device = device;
00185         init( NC, NC, NC, cs, irq, spi);
00186     }
00187     
00188     /** Destructor
00189      */
00190     virtual ~MAX3100() { 
00191         if ( _spi )     delete( _spi );
00192         if ( _irq )     delete( _irq );
00193         if ( _cs  )     delete( _cs );
00194     }
00195 
00196     enum Parity {
00197         None = 0
00198         , Odd
00199         , Even
00200         , Forced1   
00201         , Forced0
00202     };    
00203     
00204     /** setParity
00205      *
00206      * Set the parity of the system. Default is None.
00207      *
00208      * @param Parity None, Odd, Even
00209      */
00210     void setParity(int p) { _parity = p; }
00211     
00212     /** setStopBits
00213      *
00214      * Set the number of stop bits. Default is One.
00215      *
00216      * @param int 1 or 2
00217      */
00218     void setStopBits(int i);
00219     
00220     /** System interrupt service routine.
00221      */
00222     void isr(void);
00223     
00224     /** baud
00225      * Set the system baud. Default is "10" (9600). Note,
00226      * this is not like Mbed's Serial where you pass the
00227      * baud rate you want. The MAX3100 has 16 possible 
00228      * preset prescalers you can choose from. See the datasheet
00229      * for more info. 
00230      *
00231      * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
00232      * @param int A number from 0 to 15 indicating which prescaler to use.
00233      */
00234     void baud(int baudrate);
00235     
00236     /** enableRxIrq
00237      */
00238     void enableRxIrq(void);
00239     
00240     /** disableRxIrq
00241      */
00242     void disableRxIrq(void);
00243     
00244     /** enableTxIrq
00245      */
00246     void enableTxIrq(void);
00247     
00248     /** disableTxIrq
00249      */
00250     void disableTxIrq(void);
00251     
00252     /** putc
00253      * @param int c The byte to write.
00254      */
00255     int  putc(int c);
00256     
00257     /** puts
00258      * @param char * The string to print.
00259      */
00260     void puts(char *s);
00261     
00262     /** getc
00263      * @return int c The byte read or -1 if no bytes to read.
00264      */
00265     int  getc(void); 
00266     
00267     /** gets
00268      * Get a string. Note, this method blocks until size bytes are read.
00269      * @param char *s where to place the incoming bytes.
00270      * @param int size How many bytes to read.
00271      * @return char * The value of *s passed in.
00272      */
00273     char *gets(char *s, int size);   
00274     
00275     /** peek
00276      * like getc() but does NOT remove the byte from the buffer.
00277      * @see getc*(
00278      */
00279     int  peek(void);
00280     
00281     /** readable
00282      * Are any byte(s) available in the RX buffer?
00283      * @return 0 if none, 1 otherwise.
00284      */
00285     int  readable(void) { return (rx_buffer_in != rx_buffer_out || rx_buffer_full) ? 1 : 0; }
00286     
00287     /** writable
00288      * Can we write a byte to teh serial stream?
00289      * @return non-zero if we can, zero otherwise.
00290      */
00291     int  writable(void) { return tx_buffer_full ? 0 : 1; }
00292     
00293     /** setDevice
00294      * Give this device an "address".
00295      * @param int i An address to use in callbacks.
00296      */
00297     void setDevice(int i) { _device = i; }
00298     
00299     /** flushTxBuffer
00300      *
00301      * Flush the TX buffer.
00302      */
00303     void flushTxBuffer(void) { tx_buffer_in = tx_buffer_out = 0; tx_buffer_full = false; }
00304     
00305     /** flushRxBuffer
00306      *
00307      * Flush the RX buffer.
00308      */
00309     void flushRxBuffer(void) { rx_buffer_in = rx_buffer_out = 0; rx_buffer_full = false; }
00310     
00311     /** irqMask
00312      * Setup the mask for enable/disable interrupts.
00313      * @see example3.h
00314      * @param PinName p The InterruptIn pin.
00315      */
00316     void irqMask(PinName p);
00317 
00318     /** attach_cs
00319      * Attach a C style callback function pointer. Used if an external function
00320      * is controlling the chip CS line.
00321      * @param function A C function pointer
00322      */
00323     void attach_cs(void (*function)(int, int) = 0) { _cs_function = function; }
00324     
00325     /** attach_cs
00326      * Attach a C++ object/method pointer. Used if an external function
00327      * @param object An object that conatins the callback method.
00328      * @param method The method within the object to call.
00329      */
00330     template<class T> 
00331     void attach_cs(T* item, void (T::*method)(int, int)) { 
00332         _cs_obj = (MAX3100Dummy *)item; _cs_method = (void (MAX3100Dummy::*)(int, int))method; 
00333     }
00334     
00335     /** attach_isr_user
00336      * is controlling the chip CS line.
00337      * @param function A C function pointer
00338      */
00339     void attach_isr_user(void (*function)(int) = 0) { _isr_user_function = function; }
00340     
00341     /** attach_isr_user
00342      * @param object An object that conatins the callback method.
00343      * @param method The method within the object to call.
00344      */
00345     template<class T> 
00346     void attach_isr_user(T* item, void (T::*method)(int)) { 
00347         _isr_user_obj = (MAX3100Dummy *)item; _isr_user_method = (void (MAX3100Dummy::*)(int))method; 
00348     }
00349     
00350 };
00351 
00352 }; // namespace AjK ends.
00353 
00354 using namespace AjK;
00355 
00356 #endif