The iPod controller that I submitted for the mbed challenge
Dependencies: mbed Motordriver PID
Diff: user_interface/MCP23017.cpp
- Revision:
- 0:371773dd3dd1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/user_interface/MCP23017.cpp Wed May 04 15:41:13 2011 +0000 @@ -0,0 +1,179 @@ +/* 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 +*/ + +#include "mbed.h" +#include "MCP23017.h" + +DigitalOut Busy(LED4); + +/** 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 MSC23017 +*/ +MCP23017::MCP23017(I2C &i2c, char deviceAddress) : _i2c(i2c) { +printf("creating mcp23017\n"); + _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write + _readOpcode = deviceAddress | 0x01; // low order bit = 1 for read + busy = false; + posted = false; + _init(); + readW(INTFA); + readW(GPIOA); +printf("mcp23017 created\n"); +} + +/** Read from specified MCP23017 register +* +* @param char address the internal registeraddress of the MSC23017 +* @returns data from register +*/ +short MCP23017::_read(char address) {//blocks on busy and still waits for completion + char data[2]; + i2c_status s; + data[0] = address; + do { + s = _read(address, data, 1); + } while (s == i2c_busy); + return (s == i2c_ok) ? data[0] : -2; +} + +MCP23017::i2c_status MCP23017::_read(char reg, char *data, int size) {//returns on busy but still waits for completion + if (testbusy()) return i2c_busy; + _i2c.write(_writeOpcode, ®, 1, true); //in a future version of the i2c lib write should return a status like ACK or NACK or busy + int result = _i2c.read(_readOpcode, data, size); + releasebusy(); + return result ? i2c_nack : i2c_ok; +} + +int MCP23017::readW(char address) {//blocks on busy and still waits for completion + char data[2]; + i2c_status s; + data[0] = address; + do { + s = _read(address, data, 2); + } while (s == i2c_busy); + return (s == i2c_ok) ? *(unsigned short*)data : -1; +} + + +/** Write to specified MCP23017 register +* +* @param char address the internal registeraddress of the MSC23017 +*/ +void MCP23017::_write(char address, char byte) {//blocks on busy and still waits for completion + i2c_status s; + char data[2]; + data[0] = address; + data[1] = byte; + do { + s = _write(data, 2); + } while (s == i2c_busy); +// _i2c.write(_writeOpcode, data, 2); // Write data to selected Register + return ; //s; //in the future return the status +} + +MCP23017::i2c_status MCP23017::_write(char *data, int size, bool rpt) {//returns on busy but still waits for completion + if (testbusy()) return i2c_busy; + int result = 0; + _i2c.write(_writeOpcode, data, size, rpt); // Write data to selected Register + releasebusy(); + return result ? i2c_nack : i2c_ok; +} + +/** Init MCP23017 +* +* @param +* @returns +*/ +void MCP23017::_init() { + _write(IOCON, (IOCON_BYTE_MODE | IOCON_ODR )); // Open drain interrupt, 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(port + IODIRA, 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(port + GPPUA, offOrOn); +} + +void MCP23017::interruptEnable(Port port, char interruptsEnabledMask) { + _write(port + GPINTENA, interruptsEnabledMask); +} + +void MCP23017::mirrorInterrupts(bool mirror) { + char iocon = _read(IOCON); + if (mirror) { + iocon = iocon | INTERRUPT_MIRROR_BIT; + } else { + iocon = iocon & ~INTERRUPT_MIRROR_BIT; + } + _write(IOCON, iocon); + +} + +void MCP23017::interruptPolarity(Polarity polarity) { + char iocon = _read(IOCON); + if (polarity == ACTIVE_LOW) { + iocon = iocon & ~INTERRUPT_POLARITY_BIT; + } else { + iocon = iocon | INTERRUPT_POLARITY_BIT; + } + _write(IOCON, iocon); +} + +void MCP23017::defaultValue(Port port, char valuesToCompare) { + _write(port + DEFVALA, valuesToCompare); +} + +void MCP23017::interruptControl(Port port, char interruptControlBits) { + _write(port + INTCONA, 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(port + OLATA, 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(port + GPIOA); +} + +void MCP23017::write(Port port, const char *buffer, int len, bool rpt) { + len++; + char *data = new char[len]; + data[0] = port+OLATA; + i2c_status s; + for (int k=1; k< len; k++) data[k] = buffer[k-1]; + do { + s = _write(data, len, rpt);//toggle A and B, start with port + } while (s == i2c_busy); + delete[] data; +} \ No newline at end of file