The iPod controller that I submitted for the mbed challenge
Dependencies: mbed Motordriver PID
user_interface/MCP23017.cpp
- Committer:
- networker
- Date:
- 2011-05-04
- Revision:
- 0:371773dd3dd1
File content as of revision 0:371773dd3dd1:
/* 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; }