New project

Dependencies:   mbed TextLCD

Files at this revision

API Documentation at this revision

Comitter:
jasminealice
Date:
Wed Jun 13 09:06:55 2018 +0000
Parent:
21:31647d80614f
Child:
23:bb57966cb776
Commit message:
Try new mcp

Changed in this revision

MCP23017.cpp Show annotated file Show diff for this revision Revisions of this file
MCP23017.h Show annotated file Show diff for this revision Revisions of this file
MCP23017.lib Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017.cpp	Wed Jun 13 09:06:55 2018 +0000
@@ -0,0 +1,169 @@
+/* MCP23017 - drive the Microchip MCP23017 16-bit Port Extender using I2C
+* Copyright (c) 2010 Wim Huiskamp, Romilly Cocking (original version for SPI)
+*
+* Released under the MIT License: http://mbed.org/license/mit
+*
+* version 0.2 Initial Release
+* version 0.3 Cleaned up
+* version 0.4 Fixed problem with _read method
+* version 0.5 Added support for 'Banked' access to registers
+*/
+
+#include "mbed.h"
+#include "MCP23017.h"
+
+/** Create an MCP23017 object connected to the specified I2C object and using the specified deviceAddress
+*
+* @param I2C &i2c the I2C port to connect to 
+* @param char deviceAddress the address of the MCP23017
+*/
+MCP23017::MCP23017(I2C &i2c, char deviceAddress) : _i2c(i2c) {
+    _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
+    _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read
+    _init();
+}
+
+/** Read from specified MCP23017 register
+*
+* @param char address the internal registeraddress of the MCP23017
+* @returns data from register 
+*/
+char MCP23017::_read(char address) {
+    char data[2];
+
+    data[0] = address;
+    _i2c.write(_writeOpcode, data, 1);     // Select Register for reading
+    _i2c.read(_readOpcode, data, 1);       // Read from selected Register
+    
+    return data[0];
+}
+
+
+/** Write to specified MCP23017 register
+*
+* @param char address the internal registeraddress of the MCP23017
+*/
+void MCP23017::_write(char address, char byte) {
+    char data[2];
+
+    data[0] = address;
+    data[1] = byte;
+    _i2c.write(_writeOpcode, data, 2);    // Write data to selected Register
+}
+
+
+/** Init MCP23017
+*
+* @param
+* @returns 
+*/
+void MCP23017::_init() {
+  
+  _bankMode = NOT_BNK;  // This may not be true after software reset without hardware reset !!!
+  
+  _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BYTE_MODE | IOCON_HAEN )); // Hardware addressing on, no-autoincrement, 16 bit mode (operations toggle between A and B registers)
+
+}
+
+/** Set I/O direction of specified MCP23017 Port
+*
+* @param Port Port address (Port_A or Port_B)
+* @param char direction pin direction (0 = output, 1 = input)
+*/
+void MCP23017::direction(Port port, char direction) {
+    _write(IODIR_AB[_bankMode][port], direction);
+}
+
+/** Set Pull-Up Resistors on specified MCP23017 Port
+*
+* @param Port Port address (Port_A or Port_B)
+* @param char offOrOn per pin (0 = off, 1 = on)
+*/
+void MCP23017::configurePullUps(Port port, char offOrOn) {
+  
+  _write(GPPU_AB[_bankMode][port], offOrOn); 
+}
+
+/** Configere the Banked or Non-Banked mode
+*
+* @param Bank bankMode
+* @param char offOrOn per pin (0 = off, 1 = on)
+*/
+void MCP23017::configureBanked(Bank bankMode) {
+
+    if (bankMode == NOT_BNK) {
+      // Non-Banked sequential registers (default POR)
+      // Hardware addressing on, , no-autoincrement, 16 bit mode (operations do toggle between A and B registers)          
+      _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BYTE_MODE | IOCON_HAEN ));
+      _bankMode = NOT_BNK;
+    }  
+    else {
+      // Banked registers
+      // Hardware addressing on, no-autoincrement, 8 bit mode           
+      _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BANK | IOCON_BYTE_MODE | IOCON_HAEN ));
+      _bankMode = BNK;
+    }
+}
+
+
+void MCP23017::interruptEnable(Port port, char interruptsEnabledMask) {
+  
+  _write(GPINTEN_AB[_bankMode][port], interruptsEnabledMask);    
+   
+}
+
+void MCP23017::mirrorInterrupts(bool mirror) {
+  char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
+
+  if (mirror) {
+    iocon = iocon | INTERRUPT_MIRROR_BIT;
+  }
+  else {
+    iocon = iocon & ~INTERRUPT_MIRROR_BIT;
+  }
+
+  _write(IOCON_AB[_bankMode][PORT_A], iocon);
+
+}
+
+void  MCP23017::interruptPolarity(Polarity polarity) {
+    char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
+    
+    if (polarity == ACTIVE_LOW) {
+        iocon = iocon & ~INTERRUPT_POLARITY_BIT;
+    } else {
+        iocon = iocon | INTERRUPT_POLARITY_BIT;
+    }
+    _write(IOCON_AB[_bankMode][PORT_A], iocon);
+}
+
+void MCP23017::defaultValue(Port port, char valuesToCompare) {
+    
+  _write(DEFVAL_AB[_bankMode][port], valuesToCompare);
+    
+}
+
+void MCP23017::interruptControl(Port port, char interruptControlBits) {
+    
+  _write(INTCON_AB[_bankMode][port], interruptControlBits);
+    
+}
+
+/** Write to specified MCP23017 Port
+*
+* @param Port Port address (Port_A or Port_B)
+* @param char byte data to write
+*/
+void MCP23017::write(Port port, char byte) {
+    _write(OLAT_AB[_bankMode][port], byte);
+}
+    
+/** Read from specified MCP23017 Port
+*
+* @param Port Port address (Port_A or Port_B)
+* @returns data from Port 
+*/
+char MCP23017::read(Port port) {
+    return _read(GPIO_AB[_bankMode][port]);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017.h	Wed Jun 13 09:06:55 2018 +0000
@@ -0,0 +1,170 @@
+/* MCP23017 - drive the Microchip MCP23017 16-bit Port Extender using I2C
+* Copyright (c) 2010 Wim Huiskamp, Romilly Cocking (original version for SPI)
+*
+* Changed by Jacco van Splunter:
+* The _read and _write functions are moved from protected -> public
+*
+* Released under the MIT License: http://mbed.org/license/mit
+*
+* version 0.2 Initial Release
+* version 0.3 Cleaned up
+* version 0.4 Fixed problem with _read method
+* version 0.5 Added support for 'Banked' access to registers
+*/
+#include "mbed.h"
+
+#ifndef  MCP23017_H
+#define  MCP23017_H
+
+// All register addresses assume IOCON.BANK = 0 (POR default)
+#define IODIRA   0x00
+#define IODIRB   0x01
+#define IPOLA    0x02
+#define IPOLB    0x03
+#define GPINTENA 0x04
+#define GPINTENB 0x05
+#define DEFVALA  0x06
+#define DEFVALB  0x07
+#define INTCONA  0x08
+#define INTCONB  0x09
+#define IOCONA   0x0A
+#define IOCONB   0x0B
+#define GPPUA    0x0C
+#define GPPUB    0x0D
+#define INTFA    0x0E
+#define INTFB    0x0F
+#define INTCAPA  0x10
+#define INTCAPB  0x11
+#define GPIOA    0x12
+#define GPIOB    0x13
+#define OLATA    0x14
+#define OLATB    0x15
+
+// The following register addresses assume IOCON.BANK = 1 
+#define IODIRA_BNK   0x00
+#define IPOLA_BNK    0x01
+#define GPINTENA_BNK 0x02
+#define DEFVALA_BNK  0x03
+#define INTCONA_BNK  0x04
+#define IOCONA_BNK   0x05
+#define GPPUA_BNK    0x06
+#define INTFA_BNK    0x07
+#define INTCAPA_BNK  0x08
+#define GPIOA_BNK    0x09
+#define OLATA_BNK    0x0A
+
+#define IODIRB_BNK   0x10
+#define IPOLB_BNK    0x11
+#define GPINTENB_BNK 0x12
+#define DEFVALB_BNK  0x13
+#define INTCONB_BNK  0x14
+#define IOCONB_BNK   0x15
+#define GPPUB_BNK    0x16
+#define INTFB_BNK    0x17
+#define INTCAPB_BNK  0x18
+#define GPIOB_BNK    0x19
+#define OLATB_BNK    0x1A
+
+// This array allows structured access to Port_A and Port_B registers for both bankModes
+const int IODIR_AB[2][2]   = {{IODIRA, IODIRB},     {IODIRA_BNK, IODIRB_BNK}};
+const int IPOL_AB[2][2]    = {{IPOLA, IPOLB},       {IPOLA_BNK, IPOLB_BNK}};
+const int GPINTEN_AB[2][2] = {{GPINTENA, GPINTENB}, {GPINTENA_BNK, GPINTENB_BNK}};
+const int DEFVAL_AB[2][2]  = {{DEFVALA, DEFVALB},   {DEFVALA_BNK, DEFVALB_BNK}};
+const int INTCON_AB[2][2]  = {{INTCONA, INTCONB},   {INTCONA_BNK, INTCONB_BNK}};
+const int IOCON_AB[2][2]   = {{IOCONA, IOCONB},     {IOCONA_BNK, IOCONB_BNK}};
+const int GPPU_AB[2][2]    = {{GPPUA, GPPUB},       {GPPUA_BNK, GPPUB_BNK}};
+const int INTF_AB[2][2]    = {{INTFA, INTFB},       {INTFA_BNK, INTFB_BNK}};
+const int INTCAP_AB[2][2]  = {{INTCAPA, INTCAPB},   {INTCAPA_BNK, INTCAPB_BNK}};
+const int GPIO_AB[2][2]    = {{GPIOA, GPIOB},       {GPIOA_BNK, GPIOB_BNK}};
+const int OLAT_AB[2][2]    = {{OLATA, OLATB},       {OLATA_BNK, OLATB_BNK}};
+
+
+// Control settings
+#define IOCON_BANK      0x80 // Banked registers for Port A and B
+#define IOCON_BYTE_MODE 0x20 // Disables sequential operation, Address Ptr does not increment
+                             //   If Disabled and Bank = 0, operations toggle between Port A and B registers
+                             //   If Disabled and Bank = 1, operations do not increment registeraddress                             
+#define IOCON_HAEN      0x08 // Hardware address enable
+
+#define INTERRUPT_POLARITY_BIT 0x02
+#define INTERRUPT_MIRROR_BIT   0x40
+
+#define PORT_DIR_OUT   0x00
+#define PORT_DIR_IN    0xFF
+
+enum Polarity { ACTIVE_LOW , ACTIVE_HIGH };
+enum Port { PORT_A=0, PORT_B=1 };
+enum Bank { NOT_BNK=0, BNK=1 };
+
+class MCP23017 {
+public:
+    /** Create an MCP23017 object connected to the specified I2C object and using the specified deviceAddress
+    *
+    * @param I2C &i2c the I2C port to connect to 
+    * @param char deviceAddress the address of the MCP23017
+    */
+    MCP23017(I2C &i2c, char deviceAddress);
+
+    /** Set I/O direction of specified MCP23017 Port
+    *
+    * @param Port Port address (Port_A or Port_B)
+    * @param char direction pin direction (0 = output, 1 = input)
+    */
+    void direction(Port port, char direction);
+
+    /** Set Pull-Up Resistors on specified MCP23017 Port
+    *
+    * @param Port Port address (Port_A or Port_B)
+    * @param char offOrOn per pin (0 = off, 1 = on)
+    */    
+    void configurePullUps(Port port, char offOrOn);
+
+    void configureBanked(Bank bankmode);  
+    void interruptEnable(Port port, char interruptsEnabledMask);
+    void interruptPolarity(Polarity polarity);
+    void mirrorInterrupts(bool mirror);
+    void defaultValue(Port port, char valuesToCompare);
+    void interruptControl(Port port, char interruptControlBits);
+
+    /** Read from specified MCP23017 Port
+    *
+    * @param Port Port address (Port_A or Port_B)
+    * @returns data from Port 
+    */
+    char read(Port port);
+    
+    /** Write to specified MCP23017 Port
+    *
+    * @param Port Port address (Port_A or Port_B)
+    * @param char byte data to write
+    */    
+    void write(Port port, char byte);
+    
+    /** Write to specified MCP23017 register
+    *
+    * @param char address the internal registeraddress of the MCP23017
+    */
+    void _write(char address, char byte);
+
+    /** Read from specified MCP23017 register
+    *
+    * @param char address the internal registeraddress of the MCP23017
+    * @returns data from register 
+    */
+    char _read(char address);
+
+protected:
+    I2C &_i2c;
+    char _readOpcode;
+    char _writeOpcode;
+    Bank _bankMode; 
+    
+    /** Init MCP23017
+    *
+    * @param
+    * @returns 
+    */    
+    void _init();
+};
+
+#endif
\ No newline at end of file
--- a/MCP23017.lib	Tue Jun 12 15:02:44 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://os.mbed.com/users/jimherd/code/MCP23017/#d57de266cf19
--- a/main.cpp	Tue Jun 12 15:02:44 2018 +0000
+++ b/main.cpp	Wed Jun 13 09:06:55 2018 +0000
@@ -5,6 +5,7 @@
 #include "Switch.h"
 #include "Track.h"
 #include "Detector.h"
+#include "MCP23017.h"
 
 //Board 1
 /*----------------------------------------------------------------------------
@@ -35,8 +36,9 @@
 DigitalIn sw4(p12);
 
 //InterruptIn sw1(p5);
-InterruptIn inter0(p13);
-InterruptIn inter1(p14);
+InterruptIn int0(p13);
+InterruptIn int1(p14);
+I2C i2c(p28, p27);
 MCP23017 *mcp;
 
 /*----------------------------------------------------------------------------
@@ -77,7 +79,12 @@
 *----------------------------------------------------------------------------*/
 bool readDetector(DigitalIn detector);
 bool readSwitch(DigitalIn theSwitch);
-void initialize_mcp();
+//void initialize_mcp();
+void on_int0_change();
+void on_int1_change();
+void init_mcp();
+void init();
+
 
 
 //Trains
@@ -99,23 +106,32 @@
     sw1.fall(&testInterupt);
     inter0.rise(&riseFunction);
     inter1.rise(&riseFunction);*/
-    
-    initialize_mcp();
-    int res[2] = {2,4};
+    lcd.printf("Start journey");
+    init_mcp();
+    init();
+    /*int res[2] = {2,4};
     dect.reserveDetector(res); //Run trains counterclockwise and reserve the 
     int res2[2] = {12,13};
     dect.reserveDetector(res2);//detectors in front 
-
+    */
     while(1){ 
+        
         if(readSwitch(sw1)){ //Control switches
-        switch1.switchOn();    
+        /*switch1.switchOn();    
         lcd.printf("Switch 1 on");
         //switch2.switchOn();  // Need to turn it off immediately!!!
         switch3.switchOn();
-        switch4.switchOn();
+        switch4.switchOn();*/
+        
+            // Clear current interrupts
+            mcp->_read(GPIOA);
+            mcp->_read(GPIOB);
+            // Register callbacks
+            int0.fall(&on_int0_change);
+            int1.fall(&on_int1_change);
     
         }
-        else{
+        /*else{
         //DCC_send_command(DCCaddress_switch,DCCinst_deactive_switch,10);
         switch1.switchOff();
         //switch2.switchOff();
@@ -140,8 +156,8 @@
             else
                 silverTrain.changeSpeed(DCCinst_step2);
         
-    }
-} 
+        }
+    } */
     
     /*lcd.printf("Start the journey");
     time_t tstart, tend; 
@@ -150,6 +166,7 @@
     lcd.printf("%d", data);
     wait(2);
     */
+    }
 }
 
 /*----------------------------------------------------------------------------
@@ -158,7 +175,7 @@
 
 
 bool testInterupt(){
-    int pos = mcp->readRegister(0x12); 
+    int pos = 0;// mcp->readRegister(0x12); 
     lcd.cls();
     //Check which train got the interupt
     Train *temptrain;
@@ -179,6 +196,7 @@
     switch(pos){
     case 0:
     case 1:
+        //Slow down
     case 2:
         //IF Clock 2->1
             //Disable Switch2
@@ -335,7 +353,7 @@
 
 bool readSwitch(DigitalIn theSwitch){
     int val = theSwitch.read();
-    lcd.printf("%d", val);
+    //lcd.printf("%d", val);
     if(val == 1)
     return true;
     else
@@ -354,21 +372,53 @@
     return false;
 }
 
-void initialize_mcp(){
-    mcp = new MCP23017(p28, p27, 0x40);
-    mcp->reset();     
-    mcp->writeRegister(0x00, (unsigned char )0xff);     
-    mcp->writeRegister(0x01, (unsigned char )0xff);     
-    mcp->writeRegister(0x02, (unsigned char )0x00);     
-    mcp->writeRegister(0x03, (unsigned char )0x00);
-    mcp->writeRegister(0x04, (unsigned char )0xff);     
-    mcp->writeRegister(0x05, (unsigned char )0xff);     
-    mcp->writeRegister(0x06, (unsigned char )0xff);     
-    mcp->writeRegister(0x07, (unsigned char )0xff);     
-    mcp->writeRegister(0x08, (unsigned char )0xff);     
-    mcp->writeRegister(0x09, (unsigned char )0xff);     
-    mcp->writeRegister(0x0a, (unsigned char )0x42);     
-    mcp->writeRegister(0x0b, (unsigned char )0x42);     
-    mcp->writeRegister(0x0c, (unsigned char )0x00);     
-    mcp->writeRegister(0x0d, (unsigned char )0x00);
+void init_mcp() {
+    // Initialisation of MCP registers,documentation on registers is availableatNiels/Jacco/Natalia
+    mcp = new MCP23017(i2c, 0x40);
+    mcp->_write(IODIRA, (unsigned char )0xff);
+    mcp->_write(IODIRB, (unsigned char )0xff);
+    mcp->_write(IPOLA, (unsigned char )0x00);
+    mcp->_write(IPOLB, (unsigned char )0x00);
+    mcp->_write(DEFVALA, (unsigned char )0xff);
+    mcp->_write(DEFVALB, (unsigned char )0xff);
+    mcp->_write(INTCONA, (unsigned char )0xff);
+    mcp->_write(INTCONB, (unsigned char )0xff);
+    mcp->_write(IOCONA, (unsigned char )0x2);
+    mcp->_write(IOCONB, (unsigned char )0x2);
+    mcp->_write(GPPUA, (unsigned char )0xff);
+    mcp->_write(GPPUB, (unsigned char )0xff);
 }
+
+void init() {
+    // Clear current interrupts
+    mcp->_read(GPIOA);
+    mcp->_read(GPIOB);
+    // Register callbacks
+    int0.fall(&on_int0_change);
+    int1.fall(&on_int1_change);
+    // Enable interrupts on MCP
+    mcp->_write(GPINTENA, (unsigned char )0xff);
+    mcp->_write(GPINTENB, (unsigned char )0xff);// Ready to go!
+}
+
+void on_int0_change() {
+    lcd.printf("In int0)");
+    // In your code, you might want to move this logic out of the interrupt routine
+    // (for instance, by setting a flag and checking this flagin your main-loop)
+    wait_us(200000);
+    int sensor_data = mcp->_read(INTCAPA);
+    // The only thing we do with the interrupt signal is printing it
+    lcd.cls();
+    lcd.printf("GOT INT0 (0x%x)\n", sensor_data);
+}
+
+void on_int1_change() {
+    lcd.printf("In int1)");
+    // In your code, you might want to move this logic out of the interrupt routine
+    // (for instance, by setting a flag and checking this flagin your main-loop)
+    wait_us(200000);
+    int sensor_data = mcp->_read(INTCAPB);
+    // The only thing we do with the interrupt signal is printing it
+    lcd.cls();
+    lcd.printf("GOT INT0 (1) (0x%x)\n", sensor_data);
+}
\ No newline at end of file