Wiljan Arias / MCP23S17

Fork of MCP23S17 by Romilly Cocking

Revision:
1:5abd129839e7
Parent:
0:930da696072e
--- a/main.cpp	Wed Aug 18 12:30:39 2010 +0000
+++ b/main.cpp	Sat Aug 21 07:05:21 2010 +0000
@@ -1,46 +1,88 @@
 #include "mbed.h"
 
-/* first attempt at driving an MCP23S17
-*
-* Turns alternate bits of B register on and off
+/* 
+*  next baby step towards towards a library for MCP23S17
+*  I'm proposing to allow 8-bit and 16-bit conditioning, reads, and writes
+*  and interrupt conditioning
 * 
-* I have not added many comments yet.
-* This is a proof of concept,
-* not a finished example.
+*  Unless someone asks for them, I'm not going to implement
+*  multi-reads or writes where a sequence of many bytes are read from or written
+*  to the same register
+* 
+* This is currently experimental code. I'm still checking that I've understood the chip API.
 */
 
-DigitalOut myled(LED1);
+
+// all register addresses assume IOVCON.BANK = 0 (POR default)
+ 
+#define IODIRA 0x00
+#define IODIRB 0x01
+#define IOCON  0x0A
+#define GPIOA  0x12
+#define GPIOB  0x13
+#define OLATA  0x14
+#define OLATB  0x15
+
+// Control settings
+
+#define IOCON_BANK  0x80 // Banked registers
+#define IOCON_BYTE_MODE 0x20 // Disables sequential operation. If bank = 0, operations toggle between A and B registers
+#define IOCON_HAEN  0x08 // Hardware address enable
 
 SPI spi(p5, p6, p7);
-DigitalOut ncs(p20);
+DigitalOut ncs(p20);  // not chip select; bring this low to enable the chip
+char writeOpcode = 0x40; // A0, A1, A2 are tied to ground on the breadboard.
+char readOpcode = writeOpcode | 1; // low order bit = 1 for read
 
-void write(char command, char address, char data) {
+void _write(char address, char data) {
     ncs = 0;
-    spi.write(command);
+    spi.write(writeOpcode);
     spi.write(address);
     spi.write(data);
     ncs = 1;
 }
 
+char _read(char address) {
+    ncs = 0;
+    spi.write(readOpcode); 
+    spi.write(address);
+    char result = spi.write(0);
+    ncs = 1;
+    return result;
+}
+
 void init() {
-    write(0x40, 0x0A, 0xA0);
-    write(0x40, 0x10, 0x00);
+    _write(IOCON, (IOCON_BYTE_MODE | IOCON_HAEN )); // Hardware addressing on, operations toggle between A and B registers
 }
 
-void output(char byte) {
-    ncs = 0;
-     write(0x40,0x1A, byte); // configures for multi-write - could send a series of bytes for immediate output
-    ncs = 1;  
+void directionA(char direction) {
+     _write(IODIRA, direction); 
+}
+
+void directionB(char direction) {
+     _write(IODIRB, direction); 
+}
+
+void outputA(char byte) {
+    _write(OLATA, byte); 
+}
+
+void outputB(char byte) {
+    _write(OLATB, byte); 
+}
+
+char inputA() {
+    return _read(GPIOA);
 }
 
 int main() {
     init();
+    directionA(0xFF); // all 8 bits set to input
+    directionB(0x00); // all 8 bits set to ouptut
     while(1) {
-        myled = 1;
         wait(0.2);
-        output(0xAA);
-        myled = 0;
-        wait(0.2);
-        output(0x55);
+        // copy inputs from A to outputs on B
+        outputB(inputA());
+        
     }
 }