diff --git a/src/DuetNG/DueXn.cpp b/src/DuetNG/DueXn.cpp index 4f23199fa5..cb529c6bab 100644 --- a/src/DuetNG/DueXn.cpp +++ b/src/DuetNG/DueXn.cpp @@ -24,11 +24,16 @@ namespace DuetExpansion static ExpansionBoardType dueXnBoardType = ExpansionBoardType::none; const uint8_t AdditionalIoExpanderAddress = 0x71; // address of the SX1509B we allow for general I/O expansion + const uint8_t AdditionalIoExpanderAddress2 = 0x3F; static SX1509 additionalIoExpander; static bool additionalIoExpanderPresent = false; static uint16_t additionalIoInputBits = 0; + static SX1509 additionalIoExpander2; + static bool additionalIoExpanderPresent2 = false; + static uint16_t additionalIoInputBits2 = 0; + static volatile bool taskWaiting = false; static volatile bool inputsChanged = false; @@ -161,6 +166,7 @@ namespace DuetExpansion void AdditionalOutputInit() { I2C::Init(); // initialise I2C + delay(200); // the SX1509B has an independent power on reset, so give it some time bool ret; unsigned int attempts = 0; @@ -178,6 +184,24 @@ namespace DuetExpansion additionalIoInputBits = additionalIoExpander.digitalReadAll(); additionalIoExpanderPresent = true; } + + bool ret2; + unsigned int attempts2 = 0; + do + { + ++attempts2; + delay(50); + ret2 = additionalIoExpander2.begin(AdditionalIoExpanderAddress2); + } while (!ret2 && attempts2 < 5); + (void)I2C_IFACE.GetErrorCounts(true); // clear the error counts in case there wasn't a device there or we didn't find it first time + + if (ret2) + { + additionalIoExpander2.pinModeMultiple((1u << 16) - 1, INPUT_PULLDOWN); + additionalIoInputBits2 = additionalIoExpander2.digitalReadAll(); + additionalIoExpanderPresent2 = true; + } + } // Return the name of the expansion board, or nullptr if no expansion board @@ -199,7 +223,21 @@ namespace DuetExpansion // Return the name of the additional expansion board, or nullptr if no expansion board const char* _ecv_array null GetAdditionalExpansionBoardName() { - return (additionalIoExpanderPresent) ? "SX1509B expander" : nullptr; + if (additionalIoExpanderPresent && additionalIoExpanderPresent2) + { + return "SX1509B expander (0x71 & 0x3F)"; + } + else if (additionalIoExpanderPresent) + { + return "SX1509B expander (0x71)"; + } + else if (additionalIoExpanderPresent2) + { + return "SX1509B expander (0x3F)"; + } else + { + return nullptr; + } } // Set the I/O mode of a pin @@ -236,12 +274,16 @@ namespace DuetExpansion dueXnExpander.pinMode(pin, mode); } } - else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 16) + else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 32) { - if (additionalIoExpanderPresent) + if (additionalIoExpanderPresent && pin < AdditionalIoExpansionStart + 16) { additionalIoExpander.pinMode(pin - AdditionalIoExpansionStart, mode); } + else if (additionalIoExpanderPresent2 && pin >= AdditionalIoExpansionStart + 16) + { + additionalIoExpander2.pinMode(pin - (AdditionalIoExpansionStart + 16), mode); + } } } @@ -262,9 +304,9 @@ namespace DuetExpansion return (dueXnInputBits & (1u << (pin - DueXnExpansionStart))) != 0; } } - else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 16) + else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 32) { - if (additionalIoExpanderPresent) + if (additionalIoExpanderPresent && pin < AdditionalIoExpansionStart + 16) { // We don't have an interrupt from the additional I/O expander, so always read fresh data. // If this is called from inside an ISR, we will get stale data. @@ -275,6 +317,17 @@ namespace DuetExpansion return (additionalIoInputBits & (1u << (pin - AdditionalIoExpansionStart))) != 0; } + else if (additionalIoExpanderPresent2 && pin >= AdditionalIoExpansionStart + 16) + { + // We don't have an interrupt from the additional I/O expander, so always read fresh data. + // If this is called from inside an ISR, we will get stale data. + if (!inInterrupt() && __get_BASEPRI() == 0) // we must not call expander.digitalRead() from within an ISR + { + additionalIoInputBits2 = additionalIoExpander2.digitalReadAll(); + } + + return (additionalIoInputBits2 & (1u << (pin - (AdditionalIoExpansionStart + 16)))) != 0; + } } return false; @@ -290,12 +343,16 @@ namespace DuetExpansion dueXnExpander.digitalWrite(pin - DueXnExpansionStart, high); } } - else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 16) + else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 32) { - if (additionalIoExpanderPresent) + if (additionalIoExpanderPresent && pin < AdditionalIoExpansionStart + 16) { additionalIoExpander.digitalWrite(pin - AdditionalIoExpansionStart, high); } + else if (additionalIoExpanderPresent2 && pin >= AdditionalIoExpansionStart + 16) + { + additionalIoExpander2.digitalWrite(pin - (AdditionalIoExpansionStart + 16), high); + } } } @@ -309,12 +366,16 @@ namespace DuetExpansion dueXnExpander.analogWrite(pin - DueXnExpansionStart, (uint8_t)(constrain(pwm, 0.0, 1.0) * 255)); } } - else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 16) + else if (pin >= AdditionalIoExpansionStart && pin < AdditionalIoExpansionStart + 32) { - if (additionalIoExpanderPresent) + if (additionalIoExpanderPresent && pin < AdditionalIoExpansionStart + 16) { additionalIoExpander.analogWrite(pin - AdditionalIoExpansionStart, (uint8_t)(constrain(pwm, 0.0, 1.0) * 255)); } + else if (additionalIoExpanderPresent2 && pin >= AdditionalIoExpansionStart + 16) + { + additionalIoExpander2.analogWrite(pin - (AdditionalIoExpansionStart + 16), (uint8_t)(constrain(pwm, 0.0, 1.0) * 255)); + } } } diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index 11d2bdfce6..1df88a3bbb 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -102,7 +102,7 @@ constexpr Pin UsbVBusPin = PortCPin(22); // Pin used to monitor VBUS on USB po #define I2C_IRQn WIRE_ISR_ID // The interrupt number it uses constexpr Pin DueXnExpansionStart = 200; // Pin numbers 200-215 are on the I/O expander -constexpr Pin AdditionalIoExpansionStart = 220; // Pin numbers 220-235 are on the additional I/O expander +constexpr Pin AdditionalIoExpansionStart = 220; // Pin numbers 220-251 are on the additional I/O expander // The numbers of entries in each array must correspond with the values of DRIVES, AXES, or HEATERS. Set values to NoPin to flag unavailability. @@ -298,22 +298,38 @@ constexpr PinEntry PinTable[] = { 210, PinCapability::rwpwm, "duex.gp2" }, { 209, PinCapability::rwpwm, "duex.gp3" }, { 208, PinCapability::rwpwm, "duex.gp4" }, - { 220, PinCapability::rwpwm, "sx1509b.0" }, - { 221, PinCapability::rwpwm, "sx1509b.1" }, - { 222, PinCapability::rwpwm, "sx1509b.2" }, - { 223, PinCapability::rwpwm, "sx1509b.3" }, - { 224, PinCapability::rwpwm, "sx1509b.4" }, - { 225, PinCapability::rwpwm, "sx1509b.5" }, - { 226, PinCapability::rwpwm, "sx1509b.6" }, - { 227, PinCapability::rwpwm, "sx1509b.7" }, - { 228, PinCapability::rwpwm, "sx1509b.8" }, - { 229, PinCapability::rwpwm, "sx1509b.9" }, - { 230, PinCapability::rwpwm, "sx1509b.10" }, - { 231, PinCapability::rwpwm, "sx1509b.11" }, - { 232, PinCapability::rwpwm, "sx1509b.12" }, - { 233, PinCapability::rwpwm, "sx1509b.13" }, - { 234, PinCapability::rwpwm, "sx1509b.14" }, - { 235, PinCapability::rwpwm, "sx1509b.15" } + { 220, PinCapability::rwpwm, "sx1509b.0,0x71.0" }, + { 221, PinCapability::rwpwm, "sx1509b.1,0x71.1" }, + { 222, PinCapability::rwpwm, "sx1509b.2,0x71.2" }, + { 223, PinCapability::rwpwm, "sx1509b.3,0x71.3" }, + { 224, PinCapability::rwpwm, "sx1509b.4,0x71.4" }, + { 225, PinCapability::rwpwm, "sx1509b.5,0x71.5" }, + { 226, PinCapability::rwpwm, "sx1509b.6,0x71.6" }, + { 227, PinCapability::rwpwm, "sx1509b.7,0x71.7" }, + { 228, PinCapability::rwpwm, "sx1509b.8,0x71.8" }, + { 229, PinCapability::rwpwm, "sx1509b.9,0x71.9" }, + { 230, PinCapability::rwpwm, "sx1509b.10,0x71.10" }, + { 231, PinCapability::rwpwm, "sx1509b.11,0x71.11" }, + { 232, PinCapability::rwpwm, "sx1509b.12,0x71.12" }, + { 233, PinCapability::rwpwm, "sx1509b.13,0x71.13" }, + { 234, PinCapability::rwpwm, "sx1509b.14,0x71.14" }, + { 235, PinCapability::rwpwm, "sx1509b.15,0x71.15" }, + { 236, PinCapability::rwpwm, "sx1509b2.0,0x3f.0" }, + { 237, PinCapability::rwpwm, "sx1509b2.1,0x3f.1" }, + { 238, PinCapability::rwpwm, "sx1509b2.2,0x3f.2" }, + { 239, PinCapability::rwpwm, "sx1509b2.3,0x3f.3" }, + { 240, PinCapability::rwpwm, "sx1509b2.4,0x3f.4" }, + { 241, PinCapability::rwpwm, "sx1509b2.5,0x3f.5" }, + { 242, PinCapability::rwpwm, "sx1509b2.6,0x3f.6" }, + { 243, PinCapability::rwpwm, "sx1509b2.7,0x3f.7" }, + { 244, PinCapability::rwpwm, "sx1509b2.8,0x3f.8" }, + { 245, PinCapability::rwpwm, "sx1509b2.9,0x3f.9" }, + { 246, PinCapability::rwpwm, "sx1509b2.10,0x3f.10" }, + { 247, PinCapability::rwpwm, "sx1509b2.11,0x3f.11" }, + { 248, PinCapability::rwpwm, "sx1509b2.12,0x3f.12" }, + { 249, PinCapability::rwpwm, "sx1509b2.13,0x3f.13" }, + { 250, PinCapability::rwpwm, "sx1509b2.14,0x3f.14" }, + { 251, PinCapability::rwpwm, "sx1509b2.15,0x3f.15" } }; constexpr unsigned int NumNamedPins = ARRAY_SIZE(PinTable); diff --git a/src/RepRap.cpp b/src/RepRap.cpp index bffe8faf4a..9a68c733a7 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -726,6 +726,8 @@ void RepRap::Diagnostics(MessageType mtype) noexcept platform->MessageF(mtype, "%s version %s running on %s", FIRMWARE_NAME, VERSION, platform->GetElectronicsString()); const char* const expansionName = DuetExpansion::GetExpansionBoardName(); platform->MessageF(mtype, (expansionName == nullptr) ? "\n" : " + %s\n", expansionName); + const char* additionalExpansionName = DuetExpansion::GetAdditionalExpansionBoardName(); + platform->MessageF(mtype, (additionalExpansionName == nullptr) ? "\n" : " + %s\n", additionalExpansionName); #elif defined(__LPC17xx__) platform->MessageF(mtype, "%s (%s) version %s running on %s at %dMhz\n", FIRMWARE_NAME, lpcBoardName, VERSION, platform->GetElectronicsString(), (int)SystemCoreClock/1000000); #else