diff --git a/examples/UPS/UPS.ino b/examples/UPS/UPS.ino index e908b1b..bd8b8d1 100644 --- a/examples/UPS/UPS.ino +++ b/examples/UPS/UPS.ino @@ -20,7 +20,7 @@ const byte bOEMVendor = IOEMVENDOR; PresentStatus iPresentStatus = {}, iPreviousStatus = {}; byte bRechargable = 1; -byte bCapacityMode = 2; // units are in %% +byte bCapacityMode = 1; // units are in mWh // Physical parameters const uint16_t iConfigVoltage = 1380; @@ -43,76 +43,74 @@ const byte bCapacityGranularity1 = 1; const byte bCapacityGranularity2 = 1; byte iFullChargeCapacity = 100; -byte iRemaining =0, iPrevRemaining=0; +byte iRemaining[BATTERY_COUNT] = {48, 50, 51, 49, 50, 52}, iPrevRemaining=0; int iRes=0; void setup() { - - Serial.begin(57600); - - PowerDevice.begin(); + + for (int i = 0; i < BATTERY_COUNT; i++) { + PowerDevice[i].begin(); - // Serial No is set in a special way as it forms Arduino port name - PowerDevice.setSerial(STRING_SERIAL); - - // Used for debugging purposes. - PowerDevice.setOutput(Serial); + // Serial No is set in a special way as it forms Arduino port name + PowerDevice[i].setSerial(STRING_SERIAL); + } pinMode(CHGDCHPIN, INPUT_PULLUP); // ground this pin to simulate power failure. pinMode(RUNSTATUSPIN, OUTPUT); // output flushing 1 sec indicating that the arduino cycle is running. pinMode(COMMLOSTPIN, OUTPUT); // output is on once communication is lost with the host, otherwise off. - - PowerDevice.setFeature(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus)); + for (int i = 0; i < BATTERY_COUNT; i++) { + PowerDevice[i].SetFeature(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus)); - PowerDevice.setFeature(HID_PD_RUNTIMETOEMPTY, &iRunTimeToEmpty, sizeof(iRunTimeToEmpty)); - PowerDevice.setFeature(HID_PD_AVERAGETIME2FULL, &iAvgTimeToFull, sizeof(iAvgTimeToFull)); - PowerDevice.setFeature(HID_PD_AVERAGETIME2EMPTY, &iAvgTimeToEmpty, sizeof(iAvgTimeToEmpty)); - PowerDevice.setFeature(HID_PD_REMAINTIMELIMIT, &iRemainTimeLimit, sizeof(iRemainTimeLimit)); - PowerDevice.setFeature(HID_PD_DELAYBE4REBOOT, &iDelayBe4Reboot, sizeof(iDelayBe4Reboot)); - PowerDevice.setFeature(HID_PD_DELAYBE4SHUTDOWN, &iDelayBe4ShutDown, sizeof(iDelayBe4ShutDown)); + PowerDevice[i].SetFeature(HID_PD_RUNTIMETOEMPTY, &iRunTimeToEmpty, sizeof(iRunTimeToEmpty)); + PowerDevice[i].SetFeature(HID_PD_AVERAGETIME2FULL, &iAvgTimeToFull, sizeof(iAvgTimeToFull)); + PowerDevice[i].SetFeature(HID_PD_AVERAGETIME2EMPTY, &iAvgTimeToEmpty, sizeof(iAvgTimeToEmpty)); + PowerDevice[i].SetFeature(HID_PD_REMAINTIMELIMIT, &iRemainTimeLimit, sizeof(iRemainTimeLimit)); + PowerDevice[i].SetFeature(HID_PD_DELAYBE4REBOOT, &iDelayBe4Reboot, sizeof(iDelayBe4Reboot)); + PowerDevice[i].SetFeature(HID_PD_DELAYBE4SHUTDOWN, &iDelayBe4ShutDown, sizeof(iDelayBe4ShutDown)); - PowerDevice.setFeature(HID_PD_RECHARGEABLE, &bRechargable, sizeof(bRechargable)); - PowerDevice.setFeature(HID_PD_CAPACITYMODE, &bCapacityMode, sizeof(bCapacityMode)); - PowerDevice.setFeature(HID_PD_CONFIGVOLTAGE, &iConfigVoltage, sizeof(iConfigVoltage)); - PowerDevice.setFeature(HID_PD_VOLTAGE, &iVoltage, sizeof(iVoltage)); + PowerDevice[i].SetFeature(HID_PD_RECHARGEABLE, &bRechargable, sizeof(bRechargable)); + PowerDevice[i].SetFeature(HID_PD_CAPACITYMODE, &bCapacityMode, sizeof(bCapacityMode)); + PowerDevice[i].SetFeature(HID_PD_CONFIGVOLTAGE, &iConfigVoltage, sizeof(iConfigVoltage)); + PowerDevice[i].SetFeature(HID_PD_VOLTAGE, &iVoltage, sizeof(iVoltage)); - PowerDevice.setStringFeature(HID_PD_IDEVICECHEMISTRY, &bDeviceChemistry, STRING_DEVICECHEMISTRY); - PowerDevice.setStringFeature(HID_PD_IOEMINFORMATION, &bOEMVendor, STRING_OEMVENDOR); + PowerDevice[i].setStringFeature(HID_PD_IDEVICECHEMISTRY, &bDeviceChemistry, STRING_DEVICECHEMISTRY); + PowerDevice[i].setStringFeature(HID_PD_IOEMINFORMATION, &bOEMVendor, STRING_OEMVENDOR); - PowerDevice.setFeature(HID_PD_AUDIBLEALARMCTRL, &iAudibleAlarmCtrl, sizeof(iAudibleAlarmCtrl)); + PowerDevice[i].SetFeature(HID_PD_AUDIBLEALARMCTRL, &iAudibleAlarmCtrl, sizeof(iAudibleAlarmCtrl)); - PowerDevice.setFeature(HID_PD_DESIGNCAPACITY, &iDesignCapacity, sizeof(iDesignCapacity)); - PowerDevice.setFeature(HID_PD_FULLCHRGECAPACITY, &iFullChargeCapacity, sizeof(iFullChargeCapacity)); - PowerDevice.setFeature(HID_PD_REMAININGCAPACITY, &iRemaining, sizeof(iRemaining)); - PowerDevice.setFeature(HID_PD_WARNCAPACITYLIMIT, &iWarnCapacityLimit, sizeof(iWarnCapacityLimit)); - PowerDevice.setFeature(HID_PD_REMNCAPACITYLIMIT, &iRemnCapacityLimit, sizeof(iRemnCapacityLimit)); - PowerDevice.setFeature(HID_PD_CPCTYGRANULARITY1, &bCapacityGranularity1, sizeof(bCapacityGranularity1)); - PowerDevice.setFeature(HID_PD_CPCTYGRANULARITY2, &bCapacityGranularity2, sizeof(bCapacityGranularity2)); + PowerDevice[i].SetFeature(HID_PD_DESIGNCAPACITY, &iDesignCapacity, sizeof(iDesignCapacity)); + PowerDevice[i].SetFeature(HID_PD_FULLCHRGECAPACITY, &iFullChargeCapacity, sizeof(iFullChargeCapacity)); + PowerDevice[i].SetFeature(HID_PD_REMAININGCAPACITY, &iRemaining[i], sizeof(iRemaining[i])); + PowerDevice[i].SetFeature(HID_PD_WARNCAPACITYLIMIT, &iWarnCapacityLimit, sizeof(iWarnCapacityLimit)); + PowerDevice[i].SetFeature(HID_PD_REMNCAPACITYLIMIT, &iRemnCapacityLimit, sizeof(iRemnCapacityLimit)); + PowerDevice[i].SetFeature(HID_PD_CPCTYGRANULARITY1, &bCapacityGranularity1, sizeof(bCapacityGranularity1)); + PowerDevice[i].SetFeature(HID_PD_CPCTYGRANULARITY2, &bCapacityGranularity2, sizeof(bCapacityGranularity2)); uint16_t year = 2024, month = 10, day = 12; iManufacturerDate = (year - 1980)*512 + month*32 + day; // from 4.2.6 Battery Settings in "Universal Serial Bus Usage Tables for HID Power Devices" - PowerDevice.setFeature(HID_PD_MANUFACTUREDATE, &iManufacturerDate, sizeof(iManufacturerDate)); + PowerDevice[i].SetFeature(HID_PD_MANUFACTUREDATE, &iManufacturerDate, sizeof(iManufacturerDate)); + } } void loop() { //*********** Measurements Unit **************************** - bool bCharging = digitalRead(CHGDCHPIN); + bool bCharging = false; digitalRead(CHGDCHPIN); bool bACPresent = bCharging; // TODO - replace with sensor bool bDischarging = !bCharging; // TODO - replace with sensor - int iBattSoc = analogRead(BATTSOCPIN); // TODO - this is for debug only. Replace with charge estimation + int iBattSoc = 400; //analogRead(BATTSOCPIN); // TODO - this is for debug only. Replace with charge estimation - iRemaining = (byte)(round((float)iFullChargeCapacity*iBattSoc/1024)); - iRunTimeToEmpty = (uint16_t)round((float)iAvgTimeToEmpty*iRemaining/iFullChargeCapacity); + //iRemaining = (byte)(round((float)iFullChargeCapacity*iBattSoc/1024)); + iRunTimeToEmpty = (uint16_t)round((float)iAvgTimeToEmpty*iRemaining[0]/iFullChargeCapacity); // Charging iPresentStatus.Charging = bCharging; iPresentStatus.ACPresent = bACPresent; - iPresentStatus.FullyCharged = (iRemaining == iFullChargeCapacity); + iPresentStatus.FullyCharged = (iRemaining[0] == iFullChargeCapacity); // Discharging if(bDischarging) { @@ -130,7 +128,6 @@ void loop() { // Shutdown requested if(iDelayBe4ShutDown > 0 ) { iPresentStatus.ShutdownRequested = 1; - Serial.println("shutdown requested"); } else iPresentStatus.ShutdownRequested = 0; @@ -139,7 +136,6 @@ void loop() { if((iPresentStatus.ShutdownRequested) || (iPresentStatus.RemainingTimeLimitExpired)) { iPresentStatus.ShutdownImminent = 1; - Serial.println("shutdown imminent"); } else iPresentStatus.ShutdownImminent = 0; @@ -164,11 +160,13 @@ void loop() { //************ Bulk send or interrupt *********************** - if((iPresentStatus != iPreviousStatus) || (iRemaining != iPrevRemaining) || (iRunTimeToEmpty != iPrevRunTimeToEmpty) || (iIntTimer>MINUPDATEINTERVAL) ) { + if((iPresentStatus != iPreviousStatus) || (iRemaining[0] != iPrevRemaining) || (iRunTimeToEmpty != iPrevRunTimeToEmpty) || (iIntTimer>MINUPDATEINTERVAL) ) { - PowerDevice.sendReport(HID_PD_REMAININGCAPACITY, &iRemaining, sizeof(iRemaining)); - if(bDischarging) PowerDevice.sendReport(HID_PD_RUNTIMETOEMPTY, &iRunTimeToEmpty, sizeof(iRunTimeToEmpty)); - iRes = PowerDevice.sendReport(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus)); + for (int i = 0; i < BATTERY_COUNT; i++) { + PowerDevice[i].SendReport(HID_PD_REMAININGCAPACITY, &iRemaining[0], sizeof(iRemaining[0])); + if(bDischarging) PowerDevice[i].SendReport(HID_PD_RUNTIMETOEMPTY, &iRunTimeToEmpty, sizeof(iRunTimeToEmpty)); + iRes = PowerDevice[i].SendReport(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus)); + } if(iRes <0 ) { digitalWrite(COMMLOSTPIN, HIGH); @@ -178,13 +176,8 @@ void loop() { iIntTimer = 0; iPreviousStatus = iPresentStatus; - iPrevRemaining = iRemaining; + iPrevRemaining = iRemaining[0]; iPrevRunTimeToEmpty = iRunTimeToEmpty; } - - Serial.println(iRemaining); - Serial.println(iRunTimeToEmpty); - Serial.println(iRes); - } diff --git a/src/HID/HID.cpp b/src/HID/HID.cpp index e9b969a..64758e5 100644 --- a/src/HID/HID.cpp +++ b/src/HID/HID.cpp @@ -21,20 +21,13 @@ #if defined(USBCON) -HID_& HID() -{ - static HID_ obj; - return obj; -} - int HID_::getInterface(uint8_t* interfaceCount) { *interfaceCount += 1; // uses 1 HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 2, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(HID_TX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x14), - D_ENDPOINT(USB_ENDPOINT_OUT(HID_RX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x0A) + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x14) }; return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } @@ -168,9 +161,9 @@ bool HID_::LockFeature(uint16_t id, bool lock) { int HID_::SendReport(uint16_t id, const void* data, int len) { - auto ret = USB_Send(HID_TX, &id, 1); + auto ret = USB_Send(pluggedEndpoint, &id, 1); if (ret < 0) return ret; - auto ret2 = USB_Send(HID_TX | TRANSFER_RELEASE, data, len); + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); if (ret2 < 0) return ret2; return ret + ret2; } @@ -254,12 +247,11 @@ bool HID_::setup(USBSetup& setup) return false; } -HID_::HID_(void) : PluggableUSBModule(2, 1, epType), +HID_::HID_(void) : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), protocol(HID_REPORT_PROTOCOL), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; - epType[1] = EP_TYPE_INTERRUPT_OUT; PluggableUSB().plug(this); } diff --git a/src/HID/HID.h b/src/HID/HID.h index bb55aa2..666832a 100644 --- a/src/HID/HID.h +++ b/src/HID/HID.h @@ -61,14 +61,6 @@ #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 -#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface -#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) -#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT) -#define HID_ENDPOINT_OUT (HID_FIRST_ENDPOINT+1) - -#define HID_TX HID_ENDPOINT_INT -#define HID_RX HID_ENDPOINT_OUT //++ EP HID_RX for ease of use with USB_Available & USB_Rec - typedef struct { uint8_t len; // 9 @@ -87,7 +79,6 @@ typedef struct InterfaceDescriptor hid; HIDDescDescriptor desc; EndpointDescriptor in; - EndpointDescriptor out; //added } HIDDescriptor; class HIDReport { @@ -139,7 +130,7 @@ class HID_ : public PluggableUSBModule uint8_t getShortName(char* name) override; private: - uint8_t epType[2]; + uint8_t epType[1]; HIDSubDescriptor* rootNode; uint16_t descriptorSize; @@ -157,11 +148,6 @@ class HID_ : public PluggableUSBModule }; -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -HID_& HID(); - #define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0x21, 1, 0x22, lowByte(length), highByte(length) } #endif // USBCON diff --git a/src/HIDPowerDevice.cpp b/src/HIDPowerDevice.cpp index 5217e04..d49ffa5 100755 --- a/src/HIDPowerDevice.cpp +++ b/src/HIDPowerDevice.cpp @@ -224,56 +224,40 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = { HIDPowerDevice_::HIDPowerDevice_(void) { static HIDSubDescriptor node(_hidReportDescriptor, sizeof (_hidReportDescriptor)); - HID().AppendDescriptor(&node); + AppendDescriptor(&node); } void HIDPowerDevice_::begin(void) { - HID().begin(); + HID_::begin(); // set string ID here - HID().SetFeature(HID_PD_IPRODUCT, &bProduct, sizeof(bProduct)); - HID().SetFeature(HID_PD_SERIAL, &bSerial, sizeof(bSerial)); - HID().SetFeature(HID_PD_MANUFACTURER, &bManufacturer, sizeof(bManufacturer)); + SetFeature(HID_PD_IPRODUCT, &bProduct, sizeof(bProduct)); + SetFeature(HID_PD_SERIAL, &bSerial, sizeof(bSerial)); + SetFeature(HID_PD_MANUFACTURER, &bManufacturer, sizeof(bManufacturer)); } -void HIDPowerDevice_::setOutput(Serial_& out) { - HID().setOutput(out); -} - -void HIDPowerDevice_::setSerial(const char* s) { - HID().setSerial(s); -} - void HIDPowerDevice_::end(void) { } int HIDPowerDevice_::sendDate(uint16_t id, uint16_t year, uint8_t month, uint8_t day) { uint16_t bval = (year - 1980)*512 + month * 32 + day; - return HID().SendReport(id, &bval, sizeof (bval)); -} - -int HIDPowerDevice_::sendReport(uint16_t id, const void* bval, int len) { - return HID().SendReport(id, bval, len); -} - -int HIDPowerDevice_::setFeature(uint16_t id, const void *data, int len) { - return HID().SetFeature(id, data, len); + return SendReport(id, &bval, sizeof (bval)); } int HIDPowerDevice_::setStringFeature(uint8_t id, const uint8_t* index, const char* data) { - int res = HID().SetFeature(id, index, 1); + int res = SetFeature(id, index, 1); if(res == 0) return 0; - res += HID().SetFeature(0xFF00 | *index , data, strlen_P(data)); + res += SetFeature(0xFF00 | *index , data, strlen_P(data)); return res; } -HIDPowerDevice_ PowerDevice; +HIDPowerDevice_ PowerDevice[BATTERY_COUNT]; #endif diff --git a/src/HIDPowerDevice.h b/src/HIDPowerDevice.h index 888b860..ef27c27 100755 --- a/src/HIDPowerDevice.h +++ b/src/HIDPowerDevice.h @@ -102,7 +102,7 @@ static_assert(sizeof(PresentStatus) == sizeof(uint16_t)); -class HIDPowerDevice_ { +class HIDPowerDevice_ : public HID_ { private: @@ -114,24 +114,17 @@ class HIDPowerDevice_ { HIDPowerDevice_(void); void begin(void); - void setOutput(Serial_&); - - void setSerial(const char*); - - void end(void); int sendDate(uint16_t id, uint16_t year, uint8_t month, uint8_t day); - int sendReport(uint16_t id, const void* bval, int len); - - int setFeature(uint16_t id, const void* data, int len); int setStringFeature(uint8_t id, const uint8_t* index, const char* data); - }; -extern HIDPowerDevice_ PowerDevice; +// as many batteries as supported by the HW +#define BATTERY_COUNT (USB_ENDPOINTS - CDC_FIRST_ENDPOINT - CDC_ENPOINT_COUNT) // 3 by default; 6 if defining CDC_DISABLED +extern HIDPowerDevice_ PowerDevice[BATTERY_COUNT]; #endif #endif