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

Dependents:   FLIGHT_CONTROL_AND_COMMUNICATIONS_SYSTEM

Revision:
0:055897ab699b
Child:
1:46c8c60e744a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX3100.h	Sun Jan 16 18:27:44 2011 +0000
@@ -0,0 +1,314 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+
+#ifndef AJK_MAX31000_H
+#define AJK_MAX31000_H
+
+#ifndef MBED_H
+#include "mbed.h"
+#endif
+
+#ifndef MAX3100_TX_BUFFER_SIZE
+#define MAX3100_TX_BUFFER_SIZE  32
+#endif
+
+#ifndef MAX3100_RX_BUFFER_SIZE
+#define MAX3100_RX_BUFFER_SIZE  32
+#endif
+
+#ifndef MAX3100_SPI_FREQ
+#define MAX3100_SPI_FREQ    5000000
+#endif
+
+#define MAX3100_CONF_WR     (3U << 14)
+#define MAX3100_CONF_RD     (1U << 14)
+#define MAX3100_CONF_T      (1U << 14)
+#define MAX3100_CONF_R      (1U << 15)
+#define MAX3100_FEN(x)      (x << 13)
+#define MAX3100_SHDNi(x)    (x << 12)
+#define MAX3100_TM(x)       (x << 11)
+#define MAX3100_RM(x)       (x << 10)
+#define MAX3100_PM(x)       (x <<  9)
+#define MAX3100_RAM(x)      (x <<  8)
+#define MAX3100_IR(x)       (x <<  7)
+#define MAX3100_ST(x)       (x <<  6)
+#define MAX3100_PE(x)       (x <<  5)
+#define MAX3100_L(x)        (x <<  4)
+#define MAX3100_BAUD(x)     (x <<  0)        
+
+#define MAX3100_DATA_WR     (2U << 14)
+#define MAX3100_DATA_RD     (0)
+#define MAX3100_TE(x)       (x << 10)
+#define MAX3100_RAFE(x)     (x << 10)
+#define MAX3100_RTS(x)      (x <<  9)
+#define MAX3100_CTS(x)      (x <<  9)
+#define MAX3100_PT(x)       (x <<  8)
+#define MAX3100_PR(x)       (x <<  8)
+
+namespace AjK {
+
+class MAX3100Dummy;
+
+/** MAX3100 An external serial IO device.
+ *
+ * The MAX3100 librray is designed to allow the easy attachment of additional
+ * serial ports to the Mbed. We all know that the Mbed already has 3 potential
+ * serial ports. But maybe you need more ports or maybe you need to use the Mbed
+ * pins for an alternative function. The MAX3100 may well be able to help in 
+ * situations like these. 
+ *
+ * Each MAX3100 device you create in is TX/RX buffered with 32 characters in a circular
+ * buffer system.
+ *
+ * The MAX3100 uses at least one Mbed SPI port and additional DigitalOut and InterruptIn
+ * pins to work. However, you can attach multiple MAX3100 devices to a single SPI "bus".
+ *
+ * For more information on attaching multiple devices see all the examples listed below.
+ *
+ * @see example1.h
+ * @see example2.h
+ * @see example3.h
+ * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
+ */
+class MAX3100 : public Stream {
+
+protected:
+    
+    SPI         *_spi;
+    DigitalOut  *_cs;
+    InterruptIn *_irq;
+    
+    uint16_t tx_buffer[MAX3100_TX_BUFFER_SIZE];
+    int  tx_buffer_in;
+    int  tx_buffer_out;
+    bool tx_buffer_full;
+    
+    uint16_t rx_buffer[MAX3100_RX_BUFFER_SIZE];
+    int  rx_buffer_in;
+    int  rx_buffer_out;
+    bool rx_buffer_full;
+    
+    uint16_t    config;
+    int         _device;
+    int         _parity;
+    
+    virtual int _putc(int c) { return putc(c); }
+    virtual int _getc()      { return getc(); }
+
+    /** init
+     *
+     * Initialise the device.
+     * @param PinName SPI mosi
+     * @param PinName SPI miso
+     * @param PinName SPI sclk
+     * @param PinName DigitalOut cs
+     * @param PinName InterruptIn irq
+     * @param SPI * A pointer to a shared SPI bus
+     */
+    void init(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, SPI *spi = (SPI *)NULL);    
+    
+    uint16_t spiwrite(uint16_t val);        
+    uint16_t config_write(uint16_t val);
+    uint16_t config_read(void);
+
+    // C style callback function pointer for external CS control.    
+    void (*_cs_function)(int, int); 
+    
+    // C++ style callback method pointer for external CS control
+    MAX3100Dummy  *_cs_obj;
+    void (MAX3100Dummy::*_cs_method)(int, int);
+
+    // Internal CS control.
+    void cs_value(int);
+    
+    // calculate byte parity.
+    int parityCal(uint8_t c);
+    
+    // http://mbed.org/forum/bugs-suggestions/topic/1498
+    void topic_1498(PinName p); 
+
+public:
+    
+    /** Constructor
+     */
+    MAX3100() { error( "No pins supplied to constructor" ); }
+    
+    /** Constructor
+     */
+    MAX3100(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, int device = 0) {
+        _device = device;
+        init( mosi, miso, sclk, cs, irq);
+    }
+    
+    /** Constructor
+     */
+    MAX3100(SPI *spi, PinName cs, PinName irq, int device = 0) {
+        _device = device;
+        init( NC, NC, NC, cs, irq, spi);
+    }
+    
+    /** Destructor
+     */
+    virtual ~MAX3100() { 
+        if ( _spi )     delete( _spi );
+        if ( _irq )     delete( _irq );
+        if ( _cs  )     delete( _cs );
+    }
+
+    enum Parity {
+        None = 0
+        , Odd
+        , Even
+        , Forced1   
+        , Forced0
+    };    
+    
+    /** setParity
+     *
+     * Set the parity of the system. Default is None.
+     *
+     * @param Parity None, Odd, Even
+     */
+    void setParity(int p) { _parity = p; }
+    
+    /** setStopBits
+     *
+     * Set the number of stop bits. Default is One.
+     *
+     * @param int 1 or 2
+     */
+    void setStopBits(int i);
+    
+    /** System interrupt service routine.
+     */
+    void isr(void);
+    
+    /** baud
+     * Set the system baud. Default is "10" (9600). Note,
+     * this is not like Mbed's Serial where you pass the
+     * baud rate you want. The MAX3100 has 16 possible 
+     * preset prescalers you can choose from. See the datasheet
+     * for more info. 
+     *
+     * @see http://pdfserv.maxim-ic.com/en/ds/MAX3100.pdf
+     * @param int A number from 0 to 15 indicating which prescaler to use.
+     */
+    void baud(int baudrate);
+    
+    /** enableRxIrq
+     */
+    void enableRxIrq(void);
+    
+    /** disableRxIrq
+     */
+    void disableRxIrq(void);
+    
+    /** enableTxIrq
+     */
+    void enableTxIrq(void);
+    
+    /** disableTxIrq
+     */
+    void disableTxIrq(void);
+    
+    /** putc
+     * @param int c The byte to write.
+     */
+    int  putc(int c);
+    
+    /** puts
+     * @param char * The string to print.
+     */
+    void puts(char *s);
+    
+    /** getc
+     * @return int c The byte read or -1 if no bytes to read.
+     */
+    int  getc(void); 
+    
+    /** gets
+     * Get a string. Note, this method blocks until size bytes are read.
+     * @param char *s where to place the incoming bytes.
+     * @param int size How many bytes to read.
+     * @return char * The value of *s passed in.
+     */
+    char *gets(char *s, int size);   
+    
+    /** peek
+     * like getc() but does NOT remove the byte from the buffer.
+     * @see getc*(
+     */
+    int  peek(void);
+    
+    /** readable
+     * Are any byte(s) available in the RX buffer?
+     * @return 0 if none, 1 otherwise.
+     */
+    int  readable(void) { return (rx_buffer_in != rx_buffer_out || rx_buffer_full) ? 1 : 0; }
+    
+    /** writable
+     * Can we write a byte to teh serial stream?
+     * @return non-zero if we can, zero otherwise.
+     */
+    int  writable(void) { return tx_buffer_full ? 0 : 1; }
+    
+    /** setDevice
+     * Give this device an "address".
+     * @param int i An address to use in callbacks.
+     */
+    void setDevice(int i) { _device = i; }
+    
+    /** flushTxBuffer
+     *
+     * Flush the TX buffer.
+     */
+    void flushTxBuffer(void) { tx_buffer_in = tx_buffer_out = 0; tx_buffer_full = false; }
+    
+    /** flushRxBuffer
+     *
+     * Flush the RX buffer.
+     */
+    void flushRxBuffer(void) { rx_buffer_in = rx_buffer_out = 0; rx_buffer_full = false; }
+    
+    /** attach_cs
+     * Attach a C style callback function pointer. Used if an external function
+     * is controlling the chip CS line.
+     * @param function A C function pointer
+     */
+    void attach_cs(void (*function)(int, int) = 0) { _cs_function = function; }
+    
+    /** attach_cs
+     * Attach a C++ object/method pointer. Used if an external function
+     * @param object An object that conatins the callback method.
+     * @param method The method within the object to call.
+     */
+    template<class T> 
+    void attach_cs(T* item, void (T::*method)(int, int)) { _cs_obj = (MAX3100Dummy *)item; _cs_method = (void (MAX3100Dummy::*)(int, int))method; }
+    
+};
+
+}; // namespace AjK ends.
+
+using namespace AjK;
+
+#endif