libraries / Mitov / Mitov_Microchip_MCP23017.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_MICROCHIP_MCP23017_h
  11#define _MITOV_MICROCHIP_MCP23017_h
  12
  13#include <Mitov.h>
  14#include <Mitov_Basic_GPIO.h>
  15
  16namespace Mitov
  17{
  18//---------------------------------------------------------------------------
  19        class Microchip_MCP23017 : public Mitov::BasicGPIO<OpenWire::Component>
  20        {
  21                typedef Mitov::BasicGPIO<OpenWire::Component> inherited;
  22
  23        public:
  24                byte    Address = 0;
  25
  26        public:
  27                enum TRegisterIndex { riDirection, riPullUp, riInvert, riValue };
  28
  29        protected:
  30                uint16_t        FRegValues[ 4 ][ 2 ];
  31                uint16_t        FReadRegisterMap = 0;
  32                uint16_t        FReadBits = 0;
  33
  34
  35        protected:
  36                void BeginTransmissionAt( byte ARegister )
  37                {
  38                        byte AAddress = 0b0100000 | ( Address & 0b111 );
  39
  40                        Wire.beginTransmission( AAddress );
  41
  42                        Wire.write( ARegister );
  43                }
  44
  45                void WriteAt( byte ARegister, uint16_t AData )
  46                {
  47//                      Serial.print( "WriteAt: " ); Serial.print( ARegister ); Serial.print( " " ); Serial.println( AData ); 
  48                        BeginTransmissionAt( ARegister );
  49
  50                        Wire.write( (byte *)&AData, 2 );
  51
  52                        Wire.endTransmission();
  53                }
  54
  55                void StartReadFrom( byte ARegister, int ALength )
  56                {
  57                        BeginTransmissionAt( ARegister );
  58                        Wire.endTransmission();
  59                        Wire.requestFrom( 0b0100000 | ( Address & 0b111 ), ALength );
  60                        while( Wire.available() < ALength );
  61                }
  62
  63                void UpdateAll()
  64                {
  65                        const byte CPorts[] = 
  66                        { 
  67                                0x00,   // IODIR register
  68                                0x02,   // IPOL register
  69                                0x0C,   // GPPU register
  70                                0x14    // OLAT register
  71                        };
  72
  73                        for( int i = 0; i < 4; ++i )
  74                                if( FRegValues[ i ][ 0 ] != FRegValues[ i ][ 1 ] )
  75                                {
  76                                        WriteAt( CPorts[ i ], FRegValues[ i ][ 0 ] );
  77                                        FRegValues[ i ][ 1 ] = FRegValues[ i ][ 0 ];
  78                                }
  79
  80/*
  81                        // Read the port 
  82                        BeginTransmissionAt( 0x12 ); // GPIO register
  83                        Wire.endTransmission();
  84
  85                        Wire.requestFrom( 0b0100000 | ( Address & 0b111 ), 2 );
  86                        uint16_t        AValue;
  87                        ((byte *)&AValue )[ 0 ] = Wire.read();
  88                        ((byte *)&AValue )[ 1 ] = Wire.read();
  89
  90                        for( int i = 0; i < FChannels.size(); ++i )
  91                                FChannels[ i ]->UpdateOutput( AValue & ( 1 << i ) != 0 );
  92*/
  93                }
  94
  95                virtual void PerformRead()
  96                {
  97                        if( ! FReadRegisterMap )
  98                                return;
  99
 100//                      Serial.println( FReadRegisterMap );
 101
 102                        if( FReadRegisterMap & 0x0F )
 103                        {
 104                                if( FReadRegisterMap & 0xF0 )
 105                                {
 106                                        StartReadFrom( 0x12, 2 ); // GPIO register
 107                                        ((byte *)&FReadBits )[ 0 ] = Wire.read();
 108                                        ((byte *)&FReadBits )[ 1 ] = Wire.read();
 109                                }
 110
 111                                else
 112                                {
 113                                        StartReadFrom( 0x12, 1 ); // GPIO register
 114                                        ((byte *)&FReadBits )[ 0 ] = Wire.read();
 115                                        ((byte *)&FReadBits )[ 1 ] = 0;
 116
 117//                                      Serial.print( "FReadBits: " ); Serial.println( FReadBits );
 118                                }
 119                        }
 120                        else
 121                        {
 122                                // Read the port 
 123                                StartReadFrom( 0x13, 1 ); // GPIO register
 124                                ((byte *)&FReadBits )[ 0 ] = 0;
 125                                ((byte *)&FReadBits )[ 1 ] = Wire.read();
 126                        }
 127
 128                        for( int i = 0; i < FChannels.size(); ++i )
 129                                FChannels[ i ]->UpdateInput();
 130
 131                }
 132
 133        public:
 134                bool GetBitValue( uint32_t AIndex )
 135                {
 136                        return( ( FReadBits & ( ((uint32_t)1 ) << AIndex )) != 0 );
 137                }
 138
 139        public:
 140                void SetChannelValue( int AIndex, bool AValue )
 141                {
 142                        SetChannelRegisterValue( AIndex, Microchip_MCP23017::riValue, AValue );
 143                }
 144
 145        protected:
 146                virtual void SystemStart()
 147                {
 148                        inherited::SystemStart();
 149
 150                        for( int i = 0; i < 4; ++i )
 151                                FRegValues[ i ][ 1 ] = ~FRegValues[ i ][ 0 ];
 152
 153                        UpdateAll();
 154
 155                        for( int i = 0; i < FChannels.size(); ++i )
 156                                FChannels[ i ]->SendOutput();
 157                }
 158
 159                virtual void SystemLoopUpdateHardware()
 160                {
 161                        UpdateAll();
 162                        inherited::SystemLoopUpdateHardware();
 163                }
 164
 165        public:
 166                void SetChannelRegisterValue( int AIndex, int ARegisterIndex, bool AValue )
 167                {
 168                        FRegValues[ ARegisterIndex ][ 0 ] &= ~( ((uint16_t) 0b1 ) << AIndex );
 169                        FRegValues[ ARegisterIndex ][ 0 ] |= ( (uint16_t)( AValue & 1 ) ) << AIndex;
 170
 171                        if( ARegisterIndex == Microchip_MCP23017::riDirection )
 172                        {
 173                                if( AValue )
 174                                        FReadRegisterMap |= ((uint16_t) 1) << AIndex;
 175
 176                                else
 177                                        FReadRegisterMap &= ~( ((uint16_t) 1) << AIndex );
 178                        }
 179                }
 180
 181        public:
 182                Microchip_MCP23017()
 183                {
 184                        for( int i = 0; i < 4; ++i )
 185                                FRegValues[ i ][ 0 ] = 0;
 186                }
 187
 188        };
 189//---------------------------------------------------------------------------
 190        class Microchip_MCP23017_Channel : public OwnedBasicGPIOChannel<Microchip_MCP23017>
 191        {
 192                typedef OwnedBasicGPIOChannel<Microchip_MCP23017> inherited;
 193                
 194        public:
 195        void SetIsInverted( bool AValue )
 196        {
 197            if( FIsInverted == AValue )
 198                return;
 199
 200            FIsInverted = AValue;
 201            PinDirectionsInit();
 202        }
 203
 204        protected:
 205        bool FIsInverted;
 206
 207        public:
 208                virtual void UpdateInput()
 209                {                       
 210                        UpdateOutput( FOwner.GetBitValue( FIndex ));
 211                }
 212
 213        protected:
 214        virtual void PinDirectionsInit()
 215        {
 216                        FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riDirection, ! FIsOutput );
 217                        FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riPullUp, FIsPullUp );
 218                        FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riInvert, FIsInverted );
 219        }
 220
 221        public:
 222                Microchip_MCP23017_Channel( Microchip_MCP23017 &AOwner, int AIndex, bool AInitialValue, bool AIsOutput, bool AIsPullUp, bool AIsCombinedInOut, bool AIsInverted ) :
 223                        inherited( AOwner, AIndex, AInitialValue, AIsOutput, AIsPullUp, AIsCombinedInOut ),
 224                        FIsInverted( AIsInverted )
 225                {
 226                        PinDirectionsInit();
 227                }
 228
 229        };
 230//---------------------------------------------------------------------------
 231}
 232
 233#endif