diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index 2b0acd931..216a61db9 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -158,7 +158,7 @@ int http_fn_index(http_request_t *request) { hprintf128(request,"Humidity Channel %i value %f Percent
",i, fValue); - } else if(BIT_CHECK(relayFlags,i)) { + } else if(BIT_CHECK(relayFlags,i) || channelType == ChType_Toggle) { const char *c; if(CHANNEL_Check(i)) { c = "r"; diff --git a/src/i2c/drv_i2c_local.h b/src/i2c/drv_i2c_local.h index 741f5be3f..4e52bc8fe 100644 --- a/src/i2c/drv_i2c_local.h +++ b/src/i2c/drv_i2c_local.h @@ -2,6 +2,7 @@ enum i2cDeviceType_e { I2CDEV_UNKNOWN, I2CDEV_TC74, + I2CDEV_MCP23017, }; typedef enum i2cBusType_e { @@ -37,9 +38,22 @@ typedef struct i2cDevice_SM2135_s { int sourceChannel_C; int sourceChannel_W; } i2cDevice_SM2135_t; + +// Right now, MCP23017 port expander supports only output mode +// (map channel to MCP23017 output) +typedef struct i2cDevice_MCP23017_s { + i2cDevice_t base; + // private MCP23017 variables + // Channel indices (0xff = none) + byte pinMapping[16]; + // is pin an output or input? + //int pinDirections; +} i2cDevice_MCP23017_t; void DRV_I2C_Write(UINT8 addr, UINT8 data); void DRV_I2C_Read(UINT8 addr, UINT8 *data); int DRV_I2C_Begin(int dev_adr, int busID); void DRV_I2C_Close(); +// drv_i2c_mcp23017.c +int DRV_I2C_MCP23017_MapPinToChannel(const void *context, const char *cmd, const char *args); diff --git a/src/i2c/drv_i2c_main.c b/src/i2c/drv_i2c_main.c index cec672544..c594118aa 100644 --- a/src/i2c/drv_i2c_main.c +++ b/src/i2c/drv_i2c_main.c @@ -85,6 +85,41 @@ void DRV_I2C_AddNextDevice(i2cDevice_t *t) { t->next = g_i2c_devices; g_i2c_devices = t; } +void DRV_I2C_AddDevice_MCP23017_Internal(int busType,int address) { + i2cDevice_MCP23017_t *dev; + + dev = malloc(sizeof(i2cDevice_MCP23017_t)); + + dev->base.addr = address; + dev->base.busType = busType; + dev->base.type = I2CDEV_MCP23017; + dev->base.next = 0; + memset(dev->pinMapping,0xff,sizeof(dev->pinMapping)); + + DRV_I2C_AddNextDevice(dev); +} +i2cDevice_t *DRV_I2C_FindDevice(int busType,int address) { + i2cDevice_t *dev; + + dev = g_i2c_devices; + while(dev!=0) { + if(dev->addr == address && dev->busType == busType) + return dev; + dev = dev->next; + } + return 0; +} +i2cDevice_t *DRV_I2C_FindDeviceExt(int busType,int address, int devType) { + i2cDevice_t *dev; + + dev = g_i2c_devices; + while(dev!=0) { + if(dev->addr == address && dev->busType == busType && dev->type == devType) + return dev; + dev = dev->next; + } + return 0; +} void DRV_I2C_AddDevice_TC74_Internal(int busType,int address, int targetChannel) { i2cDevice_TC74_t *dev; @@ -108,11 +143,16 @@ int DRV_I2C_AddDevice_TC74(const void *context, const char *cmd, const char *arg i2cModuleStr = Tokenizer_GetArg(0); address = Tokenizer_GetArgInteger(1); targetChannel = Tokenizer_GetArgInteger(2); - - //addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_TC74: module %s, address %i, target %i\n", i2cModuleStr, address, targetChannel); busType = DRV_I2C_ParseBusType(i2cModuleStr); + if(DRV_I2C_FindDevice(busType,address)) { + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_TC74: there is already some device on this bus with such addr\n"); + return 1; + } + + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_TC74: module %s, address %i, target %i\n", i2cModuleStr, address, targetChannel); + DRV_I2C_AddDevice_TC74_Internal(busType,address,targetChannel); return 1; @@ -120,21 +160,50 @@ int DRV_I2C_AddDevice_TC74(const void *context, const char *cmd, const char *arg int DRV_I2C_AddDevice_MCP23017(const void *context, const char *cmd, const char *args) { const char *i2cModuleStr; int address; - int targetChannel; i2cBusType_t busType; Tokenizer_TokenizeString(args); i2cModuleStr = Tokenizer_GetArg(0); address = Tokenizer_GetArgInteger(1); - - addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"addI2CDevice_MCP23017: module %s, address %i\n", i2cModuleStr, address); busType = DRV_I2C_ParseBusType(i2cModuleStr); -// DRV_I2C_AddDevice_MCP23017_Internal(busType,address,targetChannel); + if(DRV_I2C_FindDevice(busType,address)) { + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_MCP23017: there is already some device on this bus with such addr\n"); + return 1; + } + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_MCP23017: module %s, address %i\n", i2cModuleStr, address); + + + DRV_I2C_AddDevice_MCP23017_Internal(busType,address); return 1; } + +int DRV_I2C_AddDevice_LCM1602(const void *context, const char *cmd, const char *args) { + const char *i2cModuleStr; + int address; + i2cBusType_t busType; + + Tokenizer_TokenizeString(args); + i2cModuleStr = Tokenizer_GetArg(0); + address = Tokenizer_GetArgInteger(1); + + busType = DRV_I2C_ParseBusType(i2cModuleStr); + + if(DRV_I2C_FindDevice(busType,address)) { + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_LCM1602: there is already some device on this bus with such addr\n"); + return 1; + } + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_AddDevice_LCM1602: module %s, address %i\n", i2cModuleStr, address); + + // DRV_I2C_AddDevice_LCM1602_Internal(busType,address); + + return 1; +} +// +// TC74 - I2C temperature sensor - read only single integer value, temperature in C +// // TC74 A0 (address type 0) // setChannelType 5 temperature // addI2CDevice_TC74 I2C1 0x48 5 @@ -142,13 +211,25 @@ int DRV_I2C_AddDevice_MCP23017(const void *context, const char *cmd, const char // setChannelType 6 temperature // addI2CDevice_TC74 I2C1 0x4A 6 +// +// MCP23017 - I2C 16 bit port expander - both inputs and outputs, right now we use it only as outputs +// // MCP23017 with A0=1, A1=1, A2=1 -// addI2CDevice_MCP23017 I2C1 0x4E 6 +// addI2CDevice_MCP23017 I2C1 0x27 + +// maps channels 5 and 6 to GPIO A7 and A6 of MCP23017 +// backlog setChannelType 5 toggle; setChannelType 6 toggle; addI2CDevice_MCP23017 I2C1 0x27; MCP23017_MapPinToChannel I2C1 0x27 7 5; MCP23017_MapPinToChannel I2C1 0x27 6 6 + +// maps channels 5 6 7 8 etc +// backlog setChannelType 5 toggle; setChannelType 6 toggle; setChannelType 7 toggle; setChannelType 8 toggle; setChannelType 9 toggle; setChannelType 10 toggle; setChannelType 11 toggle; addI2CDevice_MCP23017 I2C1 0x27; MCP23017_MapPinToChannel I2C1 0x27 7 5; MCP23017_MapPinToChannel I2C1 0x27 6 6; MCP23017_MapPinToChannel I2C1 0x27 5 7; MCP23017_MapPinToChannel I2C1 0x27 4 8; MCP23017_MapPinToChannel I2C1 0x27 3 9; MCP23017_MapPinToChannel I2C1 0x27 2 10; MCP23017_MapPinToChannel I2C1 0x27 1 11 + void DRV_I2C_Init() { CMD_RegisterCommand("addI2CDevice_TC74","",DRV_I2C_AddDevice_TC74, "Adds a new I2C device", NULL); CMD_RegisterCommand("addI2CDevice_MCP23017","",DRV_I2C_AddDevice_MCP23017, "Adds a new I2C device", NULL); - + CMD_RegisterCommand("addI2CDevice_LCM1602","",DRV_I2C_AddDevice_LCM1602, "Adds a new I2C device", NULL); + CMD_RegisterCommand("MCP23017_MapPinToChannel","",DRV_I2C_MCP23017_MapPinToChannel, "Adds a new I2C device", NULL); + } void DRC_I2C_RunDevice(i2cDevice_t *dev) { @@ -157,6 +238,9 @@ void DRC_I2C_RunDevice(i2cDevice_t *dev) case I2CDEV_TC74: DRV_I2C_TC74_RunDevice(dev); break; + case I2CDEV_MCP23017: + DRV_I2C_MCP23017_RunDevice(dev); + break; default: addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRC_I2C_RunDevice: error, device of type %i at adr %i not handled\n", dev->type, dev->addr); break; @@ -175,3 +259,32 @@ void DRV_I2C_EverySecond() cur = cur->next; } } +void I2C_OnChannelChanged_Device(i2cDevice_t *dev, int channel, int iVal) +{ + switch(dev->type) + { + case I2CDEV_TC74: + // not needed + break; + case I2CDEV_MCP23017: + DRV_I2C_MCP23017_OnChannelChanged(dev, channel, iVal); + break; + default: + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"I2C_OnChannelChanged: error, device of type %i at adr %i not handled\n", dev->type, dev->addr); + break; + + + } +} +void I2C_OnChannelChanged(int channel,int iVal) { + i2cDevice_t *cur; + + cur = g_i2c_devices; + while(cur) { + //addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_EverySecond: going to run device of type %i with addr %i\n", cur->type, cur->addr); + I2C_OnChannelChanged_Device(cur,channel,iVal); + cur = cur->next; + } +} + + diff --git a/src/i2c/drv_i2c_mcp23017.c b/src/i2c/drv_i2c_mcp23017.c new file mode 100644 index 000000000..03668ac07 --- /dev/null +++ b/src/i2c/drv_i2c_mcp23017.c @@ -0,0 +1,158 @@ +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +#include "../new_cmd.h" +#include "../logging/logging.h" +#include "drv_i2c_local.h" +// addresses, banks, etc, defines +#include "drv_i2c_mcp23017.h" + +static byte MCP23017_readByte(i2cDevice_MCP23017_t *mcp, byte tgRegAddr ) +{ + byte bufferRead; + + DRV_I2C_Begin(mcp->base.addr, mcp->base.busType); + DRV_I2C_Read( tgRegAddr, &bufferRead ); + DRV_I2C_Close(); + + return bufferRead; +} +static void MCP23017_writeByte( i2cDevice_MCP23017_t *mcp, byte tgRegAddr, byte toWrite ) +{ + DRV_I2C_Begin(mcp->base.addr, mcp->base.busType); + DRV_I2C_Write( tgRegAddr, toWrite ); + DRV_I2C_Close(); +} +static void MCP23017_setBits( i2cDevice_MCP23017_t *mcp, byte tgRegAddr, byte bitMask ) +{ + byte temp; + + temp = MCP23017_readByte( mcp, tgRegAddr ); + + temp |= bitMask; + + MCP23017_writeByte( mcp, tgRegAddr, temp ); +} +static void MCP23017_clearBits( i2cDevice_MCP23017_t *mcp, byte tgRegAddr, byte bitMask ) +{ + byte temp; + + temp = MCP23017_readByte( mcp, tgRegAddr ); + + temp &= ~bitMask; + + MCP23017_writeByte( mcp, tgRegAddr, temp ); +} +static void MCP23017_toggleBits( i2cDevice_MCP23017_t *mcp, byte tgRegAddr, byte bitMask ) +{ + byte temp; + + temp = MCP23017_readByte( mcp, tgRegAddr ); + + temp ^= bitMask; + + MCP23017_writeByte( mcp, tgRegAddr, temp ); +} +static void MCP23017_setDirectionPortA( i2cDevice_MCP23017_t *mcp, byte toWrite ) +{ + MCP23017_writeByte( mcp, _MCP23017_IODIRA_BANK0, toWrite ); +} + +static void MCP23017_setDirectionPortB( i2cDevice_MCP23017_t *mcp, byte toWrite ) +{ + MCP23017_writeByte( mcp, _MCP23017_IODIRB_BANK0, toWrite ); +} +static void MCP23017_writePortA( i2cDevice_MCP23017_t *mcp, byte toWrite ) +{ + MCP23017_writeByte( mcp, _MCP23017_OLATA_BANK0, toWrite ); +} +static void MCP23017_toggleBitPortA( i2cDevice_MCP23017_t *mcp, byte bitMask ) +{ + MCP23017_toggleBits( mcp, _MCP23017_OLATA_BANK0, bitMask ); +} + + +void DRV_I2C_MCP23017_OnChannelChanged(i2cDevice_t *dev, int channel, int iVal) +{ + i2cDevice_MCP23017_t *mcp; + int i; + int bank; + int localBitIndex; + int mask; + + mcp = (i2cDevice_MCP23017_t*)dev; + + MCP23017_setDirectionPortA(mcp, _MCP23017_PORT_DIRECTION_OUTPUT); + MCP23017_setDirectionPortB(mcp, _MCP23017_PORT_DIRECTION_OUTPUT); + + // test only + //MCP23017_toggleBitPortA(mcp, 0xFF); + + for(i = 0; i < 16; i++) { + if(mcp->pinMapping[i] == channel) { + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_MCP23017_OnChannelChanged: will set pin %i to %i for ch %i\n", i, iVal, channel); + + // split 0-16 indices into two 8 bit ports - port A and port B + if(i>=8) { + localBitIndex = i - 8; + bank = _MCP23017_OLATB_BANK0; + } else { + localBitIndex = i; + bank = _MCP23017_OLATA_BANK0; + } + mask = 1 << localBitIndex; + if(iVal) { + //addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_MCP23017_OnChannelChanged: calling MCP23017_setBits mask %i\n", mask); + MCP23017_setBits(mcp, bank, mask); + } else { + //addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_MCP23017_OnChannelChanged: calling MCP23017_clearBits mask %i\n", mask); + MCP23017_clearBits(mcp, bank, mask); + } + } + } +} +int DRV_I2C_MCP23017_MapPinToChannel(const void *context, const char *cmd, const char *args) { + const char *i2cModuleStr; + int address; + int targetPin; + int targetChannel; + i2cBusType_t busType; + i2cDevice_MCP23017_t *mcp; + + Tokenizer_TokenizeString(args); + i2cModuleStr = Tokenizer_GetArg(0); + address = Tokenizer_GetArgInteger(1); + targetPin = Tokenizer_GetArgInteger(2); + targetChannel = Tokenizer_GetArgInteger(3); + + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_MCP23017_MapPinToChannel: module %s, address %i, pin %i, ch %i\n", i2cModuleStr, address,targetPin,targetChannel ); + + busType = DRV_I2C_ParseBusType(i2cModuleStr); + + mcp = DRV_I2C_FindDeviceExt( busType, address,I2CDEV_MCP23017); + if(mcp == 0) { + addLogAdv(LOG_INFO, LOG_FEATURE_I2C,"DRV_I2C_MCP23017_MapPinToChannel: no such device exists\n" ); + return 0; + } + + mcp->pinMapping[targetPin] = targetChannel; + + // send refresh + DRV_I2C_MCP23017_OnChannelChanged(mcp, targetChannel, CHANNEL_Get(targetChannel)); + + return 1; +} +void DRV_I2C_MCP23017_RunDevice(i2cDevice_t *dev) +{ + i2cDevice_MCP23017_t *mcp; + + mcp = (i2cDevice_MCP23017_t*)dev; + + // old test code, used only to make MCP23017 blink +#if 0 + MCP23017_setDirectionPortA(mcp, _MCP23017_PORT_DIRECTION_OUTPUT); + MCP23017_toggleBitPortA(mcp, 0xFF); +#endif + + // Nothing to do here right now, as we are using on change pin callback +} \ No newline at end of file diff --git a/src/i2c/drv_i2c_mcp23017.h b/src/i2c/drv_i2c_mcp23017.h new file mode 100644 index 000000000..533223d56 --- /dev/null +++ b/src/i2c/drv_i2c_mcp23017.h @@ -0,0 +1,83 @@ + + +const byte _MCP23017_I2C__MODULE_ADDRESS_0 = 0x00; +const byte _MCP23017_I2C__MODULE_ADDRESS_1 = 0x01; +const byte _MCP23017_I2C__MODULE_ADDRESS_2 = 0x02; +const byte _MCP23017_I2C__MODULE_ADDRESS_3 = 0x03; +const byte _MCP23017_I2C__MODULE_ADDRESS_4 = 0x04; +const byte _MCP23017_I2C__MODULE_ADDRESS_5 = 0x05; +const byte _MCP23017_I2C__MODULE_ADDRESS_6 = 0x06; +const byte _MCP23017_I2C__MODULE_ADDRESS_7 = 0x07; + +// Port Direction +const byte _MCP23017_PORT_DIRECTION_OUTPUT = 0x00; +const byte _MCP23017_PORT_DIRECTION_INPUT = 0xFF; + +// BANK 1 register configuration +const byte _MCP23017_IODIRA_BANK1 = 0x00; +const byte _MCP23017_IPOLA_BANK1 = 0x01; +const byte _MCP23017_GPINTENA_BANK1 = 0x02; +const byte _MCP23017_DEFVALA_BANK1 = 0x03; +const byte _MCP23017_INTCONA_BANK1 = 0x04; +const byte _MCP23017_IOCON_BANK1 = 0x05; +const byte _MCP23017_GPPUA_BANK1 = 0x06; +const byte _MCP23017_INTFA_BANK1 = 0x07; +const byte _MCP23017_INTCAPA_BANK1 = 0x08; +const byte _MCP23017_GPIOA_BANK1 = 0x09; +const byte _MCP23017_OLATA_BANK1 = 0x0A; +const byte _MCP23017_IODIRB_BANK1 = 0x10; +const byte _MCP23017_IPOLB_BANK1 = 0x11; +const byte _MCP23017_GPINTENB_BANK1 = 0x12; +const byte _MCP23017_DEFVALB_BANK1 = 0x13; +const byte _MCP23017_INTCONB_BANK1 = 0x14; +const byte _MCP23017_IOCONO_BANK1 = 0x15; +const byte _MCP23017_GPPUB_BANK1 = 0x16; +const byte _MCP23017_INTFB_BANK1 = 0x17; +const byte _MCP23017_INTCAPB_BANK1 = 0x18; +const byte _MCP23017_GPIOB_BANK1 = 0x19; +const byte _MCP23017_OLATB_BANK1 = 0x1A; + +// BANK 0 register configuration +const byte _MCP23017_IODIRA_BANK0 = 0x00; +const byte _MCP23017_IODIRB_BANK0 = 0x01; +const byte _MCP23017_IPOLA_BANK0 = 0x02; +const byte _MCP23017_IPOLB_BANK0 = 0x03; +const byte _MCP23017_GPINTENA_BANK0 = 0x04; +const byte _MCP23017_GPINTENB_BANK0 = 0x05; +const byte _MCP23017_DEFVALA_BANK0 = 0x06; +const byte _MCP23017_DEFVALB_BANK0 = 0x07; +const byte _MCP23017_INTCONA_BANK0 = 0x08; +const byte _MCP23017_INTCONB_BANK0 = 0x09; +const byte _MCP23017_IOCON_BANK0 = 0x0A; +const byte _MCP23017_GPPUA_BANK0 = 0x0C; +const byte _MCP23017_GPPUB_BANK0 = 0x0D; +const byte _MCP23017_INTFA_BANK0 = 0x0E; +const byte _MCP23017_INTFB_BANK0 = 0x0F; +const byte _MCP23017_INTCAPA_BANK0 = 0x10; +const byte _MCP23017_INTCAPB_BANK0 = 0x11; +const byte _MCP23017_GPIOA_BANK0 = 0x12; +const byte _MCP23017_GPIOB_BANK0 = 0x13; +const byte _MCP23017_OLATA_BANK0 = 0x14; +const byte _MCP23017_OLATB_BANK0 = 0x15; + +const byte _MCP23017_HD1_PA0 = 0x01; +const byte _MCP23017_HD1_PA1 = 0x02; +const byte _MCP23017_HD1_PA2 = 0x04; +const byte _MCP23017_HD1_PA3 = 0x08; +const byte _MCP23017_HD1_PA4 = 0x10; +const byte _MCP23017_HD1_PA5 = 0x20; +const byte _MCP23017_HD1_PA6 = 0x40; +const byte _MCP23017_HD1_PA7 = 0x80; + +const byte _MCP23017_HD2_PB0 = 0x01; +const byte _MCP23017_HD2_PB1 = 0x02; +const byte _MCP23017_HD2_PB2 = 0x04; +const byte _MCP23017_HD2_PB3 = 0x08; +const byte _MCP23017_HD2_PB4 = 0x10; +const byte _MCP23017_HD2_PB5 = 0x20; +const byte _MCP23017_HD2_PB6 = 0x40; +const byte _MCP23017_HD2_PB7 = 0x80; + +const byte _MCP23017_HD_START_POSITION = 0x01; + +const byte _MCP23017_INT_ERR = 0xFF; \ No newline at end of file diff --git a/src/new_pins.c b/src/new_pins.c index a0826ceba..0772583d8 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -938,6 +938,8 @@ void Channel_OnChanged(int ch) { iVal = g_channelValues[ch]; bOn = iVal > 0; + I2C_OnChannelChanged(ch,iVal); + for(i = 0; i < GPIO_MAX; i++) { if(g_pins.channels[i] == ch) { if(g_pins.roles[i] == IOR_Relay || g_pins.roles[i] == IOR_LED) { @@ -1203,6 +1205,8 @@ int CHANNEL_ParseChannelType(const char *s) { return ChType_Humidity_div10; if(!stricmp(s,"temperature_div10")) return ChType_Temperature_div10; + if(!stricmp(s,"toggle")) + return ChType_Toggle; if(!stricmp(s,"default") ) return ChType_Default; return ChType_Error; diff --git a/src/new_pins.h b/src/new_pins.h index b808bc1be..99e95b865 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -33,7 +33,7 @@ enum ChannelType { // TuyaMCU sends 225 instead of 22.5% ChType_Humidity_div10, ChType_Temperature_div10, - + ChType_Toggle, }; // NOTE: you must keep size of this structure in sync with // structures in flash config code for both BK7231 and XR809 diff --git a/windowsTest_msvc2008.vcproj b/windowsTest_msvc2008.vcproj index c75577468..b062d32dc 100644 --- a/windowsTest_msvc2008.vcproj +++ b/windowsTest_msvc2008.vcproj @@ -203,6 +203,18 @@ /> + + + + + @@ -356,7 +368,7 @@