Last active
December 17, 2015 11:59
-
-
Save marcboon/5606961 to your computer and use it in GitHub Desktop.
Encapsulates a MCP23008 I2C i/o expander for use with electric imp. Emulates the standard Pin class, allows easy moving of i/o from native pins to i/o expander pins.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This class is compatible with the general Pin class | |
class MCP23008Pin { | |
device = null | |
gpio = null | |
constructor(device, gpio) { | |
this.device = device | |
this.gpio = gpio | |
} | |
function configure(mode) { | |
switch(mode) { | |
case DIGITAL_IN: | |
device.setDir(gpio, 1) | |
device.setPullUp(gpio, 0) | |
break | |
case DIGITAL_IN_PULLUP: | |
device.setDir(gpio, 1) | |
device.setPullUp(gpio, 1) | |
break | |
case DIGITAL_OUT: | |
device.setDir(gpio, 0) | |
device.setPullUp(gpio, 0) | |
break | |
default: | |
server.log("MCP23008Pin: Invalid mode") | |
} | |
} | |
function read() { | |
return device.getPin(gpio) | |
} | |
function write(level) { | |
device.setPin(gpio, level) | |
} | |
} | |
class MCP23008 { | |
BASE_ADDR = 0x20 | |
REG_ADDR = | |
{ | |
IODIR = 0x00 | |
IOPOL = 0x01 | |
GPINTEN = 0x02 | |
DEFVAL = 0x03 | |
INTCON = 0x04 | |
IOCON = 0x05 | |
GPPU = 0x06 | |
INTF = 0x07 | |
INTCAP = 0x08 | |
GPIO = 0x09 | |
OLAT = 0x0A | |
} | |
i2cPort = null | |
i2cAddr = null | |
pin1 = null | |
pin2 = null | |
pin3 = null | |
pin4 = null | |
pin5 = null | |
pin6 = null | |
pin7 = null | |
pin8 = null | |
constructor(i2cPort, deviceAddr) { | |
this.i2cPort = i2cPort | |
this.i2cAddr = (BASE_ADDR + deviceAddr) << 1 | |
for(local gpio = 1; gpio <= 8; gpio++) { | |
this["pin" + gpio] = MCP23008Pin(this, gpio - 1) | |
} | |
} | |
// Read a byte | |
function read(reg) | |
{ | |
local data = i2cPort.read(i2cAddr, format("%c", reg), 1); | |
if(data == null) | |
{ | |
server.log("I2C Read Failure"); | |
return -1; | |
} | |
return data[0]; | |
} | |
// Write a byte | |
function write(reg, data) | |
{ | |
i2cPort.write(i2cAddr, format("%c%c", reg, data)); | |
} | |
// Write a bit to a register | |
function writeBit(reg, bitn, level) | |
{ | |
local value = read(reg); | |
value = (level == 0)?(value & ~(1<<bitn)):(value | (1<<bitn)); | |
write(reg, value); | |
} | |
function setValueForRegister(gpio, reg, value) { | |
writeBit(REG_ADDR[reg], gpio&7, value); | |
} | |
function getValueForRegister(gpio, reg) { | |
return (read(REG_ADDR[reg])&(1<<(gpio&7)))?1:0; | |
} | |
function setDir(gpio, input) | |
{ | |
setValueForRegister(gpio, "IODIR", (input?1:0)) | |
} | |
function setPullUp(gpio, pull_up) | |
{ | |
setValueForRegister(gpio, "GPPU", pull_up?1:0); | |
} | |
function setPin(gpio, level) | |
{ | |
setValueForRegister(gpio, "GPIO", level?1:0); | |
} | |
function getPin(gpio) | |
{ | |
return getValueForRegister(gpio, "GPIO") | |
} | |
} | |
// Demo | |
hardware.i2c89.configure(CLOCK_SPEED_100_KHZ) | |
port <- MCP23008(hardware.i2c89, 0) | |
led <- port.pin1 // or hardware.pin1 | |
led.configure(DIGITAL_OUT) | |
function blink() { | |
imp.wakeup(0.5, blink) | |
led.write(1 - led.read()) | |
} | |
blink() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment