diff --git a/AudioOutputCC3200I2S.cpp b/AudioOutputCC3200I2S.cpp index 4586e1a..d4d6a63 100644 --- a/AudioOutputCC3200I2S.cpp +++ b/AudioOutputCC3200I2S.cpp @@ -93,10 +93,12 @@ bool AudioOutputCC3200I2S::ConsumeSample(int16_t sample[2]) ms[1] = sample[1]; MakeSampleStereo16( ms ); - if (this->mono) { + if (this->mono && this->channels == 2) { // Average the two samples and overwrite int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL]; ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff; + } else if (this->channels == 1) { + ms[LEFTCHANNEL] = ms[RIGHTCHANNEL]; } writeBuffer->buffer[writeBuffer->position++] = ms[LEFTCHANNEL]; diff --git a/BoxAccelerometer.cpp b/BoxAccelerometer.cpp index 4c5fea6..3262305 100644 --- a/BoxAccelerometer.cpp +++ b/BoxAccelerometer.cpp @@ -14,21 +14,21 @@ void BoxAccelerometer::begin() { _accel.setupPL(); - _accel.writeRegister(CTRL_REG1, 0x02); //Original 0x02 - _accel.writeRegister(XYZ_DATA_CFG, 0x02); //Original 0x02 - _accel.writeRegister(CTRL_REG2, 0x00); //Original 0x00 + _accel.writeRegister(CTRL_REG1, 0x02); //Original 0x02 //F_READ + _accel.writeRegister(XYZ_DATA_CFG, 0x02); //Original 0x02 //FS1 + _accel.writeRegister(CTRL_REG2, 0x00); //Original 0x00 //Standby _accel.writeRegister(F_SETUP, 0x00); //Original 0x00 - _accel.writeRegister(TRIG_CFG, 0x08); //Original 0x08 - _accel.writeRegister(PULSE_CFG, 0x54); //Original 0x54 + _accel.writeRegister(TRIG_CFG, 0x08); //Original 0x08 //Trig_PULSE/ZSPEFE/ELE + _accel.writeRegister(PULSE_CFG, 0x54); //Original 0x54 //YSPEFE _accel.setupTap(0x1B, 0x3F, 0x3F); //Original 0x1B, 0x3F, 0x3F - _accel.writeRegister(PULSE_TMLT, 0x28); //Original 0x28 - _accel.writeRegister(PULSE_LTCY, 0x7F); //Original 0x7F - _accel.writeRegister(HP_FILTER_CUTOFF, 0x10); //Original 0x10 + _accel.writeRegister(PULSE_TMLT, 0x28); //Original 0x28 //TMLT3/TMLT5 + _accel.writeRegister(PULSE_LTCY, 0x7F); //Original 0x7F //LTCY6/LTCY5/LTCY4/LTCY3/LTCY2/LTCY1/LTCY0 + _accel.writeRegister(HP_FILTER_CUTOFF, 0x10); //Original 0x10 //Pulse_LPF_EN - _accel.writeRegister(CTRL_REG3, 0x12); //Original 0x12 - _accel.writeRegister(CTRL_REG4, 0x40); //Original 0x40 - _accel.writeRegister(CTRL_REG5, 0x40); //Original 0x40 - _accel.writeRegister(CTRL_REG1, 0x03); //Original 0x03 + _accel.writeRegister(CTRL_REG3, 0x12); //Original 0x12 //WAKE_PULSE/IPOL + _accel.writeRegister(CTRL_REG4, 0x40); //Original 0x40 //INT_EN_FIFO + _accel.writeRegister(CTRL_REG5, 0x40); //Original 0x40 //INT_CFG_FIFO INT1 + _accel.writeRegister(CTRL_REG1, 0x03); //Original 0x03 //F_READ/ACTIVE Log.info("...done"); } @@ -51,13 +51,13 @@ void BoxAccelerometer::loop() { uint8_t tap = _accel.readTap(); if (tap) { - bool AxZ = tap&0b1000000; //event on axis - bool AxY = tap&0b0100000; - bool AxX = tap&0b0010000; - //bool DPE = tap&0b0001000; //double - bool PolZ = tap&0b0000100; //0=positive 1=negative - bool PolY = tap&0b0000010; - bool PolX = tap&0b0000001; + bool AxZ = (tap&0b1000000)>0; //event on axis + bool AxY = (tap&0b0100000)>0; + bool AxX = (tap&0b0010000)>0; + //bool DPE = (tap&0b0001000)>0; //double + bool PolZ = !((tap&0b0000100)>0); //0=positive 1=negative + bool PolY = !((tap&0b0000010)>0); + bool PolX = !((tap&0b0000001)>0); //X+ = box bottom //X- = box top @@ -80,22 +80,85 @@ void BoxAccelerometer::loop() { if (AxY && AxZ) { if (PolY && PolZ) { tapOn = TapOn::BACK; - Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Blue, 2); + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Blue, 3); } else if (!PolY && !PolZ) { tapOn = TapOn::FRONT; - Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Violet, 2); + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Violet, 3); } else if (PolY && !PolZ) { tapOn = TapOn::LEFT; - Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Green, 2); + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Green, 3); } else if (!PolY && PolZ) { tapOn = TapOn::RIGHT; - Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::GreenYellow, 2); + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::GreenYellow, 3); + } + } else if (AxY) { + if (PolY) { + tapOn = TapOn::LEFT_BACK; + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Blue, 3); + } else { + tapOn = TapOn::LEFT_FRONT; + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Violet, 3); + } + } else if (AxZ) { + if (PolZ) { + tapOn = TapOn::RIGHT_BACK; + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Green, 3); + } else { + tapOn = TapOn::RIGHT_FRONT; + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::GreenYellow, 3); } } - Log.verbose("Tap recieved %B, direction %X", tap, tapOn); + Log.disableNewline(true); + Log.verbose("Tap recieved %B, direction=%X, ", tap, tapOn); + Log.disableNewline(false); + switch (tapOn) + { + case TapOn::LEFT: + Log.printfln("LEFT"); + break; + + case TapOn::RIGHT: + Log.printfln("RIGHT"); + break; + + case TapOn::FRONT: + Log.printfln("FRONT"); + break; + + case TapOn::BACK: + Log.printfln("BACK"); + break; + + case TapOn::TOP: + Log.printfln("TOP"); + break; + + case TapOn::BOTTOM: + Log.printfln("BOTTOM"); + break; + case TapOn::LEFT_FRONT: + Log.printfln("LEFT_FRONT"); + break; + + case TapOn::RIGHT_FRONT: + Log.printfln("RIGHT_FRONT"); + break; + + case TapOn::LEFT_BACK: + Log.printfln("LEFT_BACK"); + break; + case TapOn::RIGHT_BACK: + Log.printfln("RIGHT_BACK"); + break; + + default: + break; + Log.printfln("OTHER"); + } + } } diff --git a/BoxAccelerometer.h b/BoxAccelerometer.h index 2ce0d3a..da4a017 100644 --- a/BoxAccelerometer.h +++ b/BoxAccelerometer.h @@ -21,13 +21,18 @@ class BoxAccelerometer : public EnhancedThread { EARS_DOWN2 = 0x4 }; enum class TapOn { - NONE = 0x0, - LEFT = 0x1, - RIGHT = 0x2, //17,34,68 - 34 - FRONT = 0x3, //16, 17 - BACK = 0x4, - TOP = 0x5, //16,32,64,68,24 - 16 - BOTTOM = 0x6 //17 + NONE = 0x00, + LEFT = 0x01, + RIGHT = 0x02, //17,34,68 - 34 + FRONT = 0x04, //16, 17 + BACK = 0x08, + TOP = 0x10, //16,32,64,68,24 - 16 + BOTTOM = 0x20, //17 + + LEFT_FRONT = LEFT + FRONT, + RIGHT_FRONT = RIGHT + FRONT, + LEFT_BACK = LEFT + BACK, + RIGHT_BACK = RIGHT + BACK }; void diff --git a/BoxBattery.cpp b/BoxBattery.cpp index d9bc126..c4365b7 100644 --- a/BoxBattery.cpp +++ b/BoxBattery.cpp @@ -8,8 +8,7 @@ void BoxBattery::begin() { _wasLow = false; _wasCritical = false; - _batteryAdcRaw = analogRead(60); - _batteryAdcLowRaw = 9999; + _readBatteryAdc(); batteryTestThread.setInterval(10*60*1000); batteryTestThread.enabled = false; @@ -17,10 +16,10 @@ void BoxBattery::begin() { loop(); logBatteryStatus(); - setInterval(500); + setInterval(100); } void BoxBattery::loop() { - _batteryAdcRaw = analogRead(60); + _readBatteryAdc(); _charger.read(); if (_batteryAdcRaw < _batteryAdcLowRaw || isChargerConnected()) @@ -46,6 +45,11 @@ void BoxBattery::loop() { } } +void BoxBattery::_readBatteryAdc() { + uint16_t adcValue = analogReadAvg(BATTERY_VOLTAGE_PIN, 1); + _batteryAdcRaw = adcValue; +} + bool BoxBattery::isChargerConnected() { if (_charger.isPressed()) return true; @@ -55,10 +59,7 @@ uint16_t BoxBattery::getBatteryAdcRaw() { return _batteryAdcRaw; } uint16_t BoxBattery::getBatteryVoltage() { - if (isChargerConnected()) { - return 10000 * getBatteryAdcRaw() / _batteryVoltageChargerFactor; - } - return 10000 * getBatteryAdcRaw() / _batteryVoltageFactor; + return 1000 * getBatteryAdcRaw() / _batteryVoltageFactor; } bool BoxBattery::isBatteryLow() { if (getBatteryAdcRaw() < _batteryLowAdc) @@ -88,7 +89,6 @@ void BoxBattery::reloadConfig() { ConfigStruct* config = Config.get(); _batteryVoltageFactor = config->battery.voltageFactor; - _batteryVoltageChargerFactor = config->battery.voltageChargerFactor; _batteryLowAdc = config->battery.lowAdc; _batteryCriticalAdc = config->battery.criticalAdc; } @@ -144,7 +144,7 @@ void BoxBattery::startBatteryTest() { file.writeString("Comments"); file.writeString("\r\n"); file.writeString("0;;;;;;"); - sprintf(output, "vFactor=%lu, vChargerFactor=%lu;v2-wav", _batteryVoltageFactor, _batteryVoltageChargerFactor); + sprintf(output, "vFactor=%lu;v3-wav", _batteryVoltageFactor); file.writeString(output); file.writeString("\r\n"); file.close(); diff --git a/BoxBattery.h b/BoxBattery.h index 3df357c..d04a683 100644 --- a/BoxBattery.h +++ b/BoxBattery.h @@ -52,7 +52,6 @@ class BoxBattery : public EnhancedThread { private: uint32_t _batteryVoltageFactor; - uint32_t _batteryVoltageChargerFactor; uint16_t _batteryLowAdc; uint16_t _batteryCriticalAdc; @@ -64,6 +63,9 @@ class BoxBattery : public EnhancedThread { const char* _batteryTestFilename = "/revvox/batteryTest.csv"; uint64_t _batteryTestStartMillis; + + const static uint8_t BATTERY_VOLTAGE_PIN = 60; + void _readBatteryAdc(); }; #endif \ No newline at end of file diff --git a/BoxConfig.cpp b/BoxConfig.cpp index de9423b..89815f5 100644 --- a/BoxConfig.cpp +++ b/BoxConfig.cpp @@ -53,7 +53,6 @@ String BoxConfig::getAsJson() { JsonObject batteryDoc = doc.createNestedObject("battery"); ConfigBattery* batteryCfg = &_config.battery; batteryDoc["voltageFactor"] = batteryCfg->voltageFactor; - batteryDoc["voltageChargerFactor"] = batteryCfg->voltageChargerFactor; batteryDoc["lowAdc"] = batteryCfg->lowAdc; batteryDoc["criticalAdc"] = batteryCfg->criticalAdc; batteryDoc["sleepMinutes"] = batteryCfg->sleepMinutes; @@ -76,6 +75,7 @@ String BoxConfig::getAsJson() { ConfigMisc* miscCfg = &_config.misc; miscDoc["autodump"] = miscCfg->autodump; miscDoc["swd"] = miscCfg->swd; + miscDoc["watchdogSeconds"] = miscCfg->watchdogSeconds; _json = ""; serializeJson(doc, _json); @@ -95,7 +95,6 @@ bool BoxConfig::setFromJson(String json) { JsonObject batteryDoc = doc["battery"]; ConfigBattery* batteryCfg = &_config.battery; batteryCfg->voltageFactor = batteryDoc["voltageFactor"].as(); - batteryCfg->voltageChargerFactor = batteryDoc["voltageChargerFactor"].as(); batteryCfg->lowAdc = batteryDoc["lowAdc"].as(); batteryCfg->criticalAdc = batteryDoc["criticalAdc"].as(); batteryCfg->sleepMinutes = batteryDoc["sleepMinutes"].as(); @@ -118,6 +117,7 @@ bool BoxConfig::setFromJson(String json) { ConfigMisc* miscCfg = &_config.misc; miscCfg->autodump = miscDoc["autodump"].as(); miscCfg->swd = miscDoc["swd"].as(); + miscCfg->watchdogSeconds = miscDoc["watchdogSeconds"].as(); // Convert old config version to latest one. if (_config.version != CONFIG_ACTIVE_VERSION) { @@ -132,6 +132,16 @@ bool BoxConfig::setFromJson(String json) { case 4: miscCfg->swd = false; _config.version = 5; + case 5: + batteryCfg->lowAdc = 9658; + batteryCfg->criticalAdc = 8869; + batteryCfg->voltageFactor = 27850; + _config.version = 6; + case 6: + miscCfg->watchdogSeconds = 10; + if (batteryCfg->voltageFactor == 67690) //Fix for wrong value in previous CFW + batteryCfg->voltageFactor = 27850; + _config.version = 7; write(); break; default: @@ -147,11 +157,12 @@ bool BoxConfig::setFromJson(String json) { void BoxConfig::_initializeConfig() { _config.version = CONFIG_ACTIVE_VERSION; + //(4936,0258+0x59)/(10000/0x663d) = adc + //(10000/0x663d)×13152−0x59 = v-OFW ConfigBattery* battery = &_config.battery; - battery->voltageFactor = 67690; - battery->voltageChargerFactor = 71907; - battery->lowAdc = 2500; - battery->criticalAdc = 2400; + battery->voltageFactor = 27850; + battery->lowAdc = 9658; //OFW 0xE11 (9657,837) + battery->criticalAdc = 8869; //OFW 0xCE3/0xCE4 (8867,4124/8870,0297) battery->sleepMinutes = 15; ConfigButtonEars* buttons = &_config.buttonEars; @@ -173,4 +184,5 @@ void BoxConfig::_initializeConfig() { ConfigMisc* misc = &_config.misc; misc->autodump = false; misc->swd = false; + misc->watchdogSeconds = 10; } \ No newline at end of file diff --git a/BoxConfig.h b/BoxConfig.h index 7c51e16..7062084 100644 --- a/BoxConfig.h +++ b/BoxConfig.h @@ -6,8 +6,8 @@ #include "BoxSD.h" -#define BOXCONFIG_JSON_SIZE 528 -//{"version":255,"battery":{"voltageFactor":4294967295,"voltageChargerFactor":4294967295,"lowAdc":65535,"criticalAdc":65535,"sleepMinutes":255},"buttonEars":{"longPressMs":65535,"veryLongPressMs":65535},"wifi":{"ssid":"12345678901234567890123456789012","password":"1234567890123456789012345678901234567890123456789012345678901234"},"log":{"sdLog":false},"misc":{"autodump":false,"swd":false}} +#define BOXCONFIG_JSON_SIZE 560 +//{"version":255,"battery":{"voltageFactor":4294967295,"voltageChargerFactor":4294967295,"lowAdc":65535,"criticalAdc":65535,"sleepMinutes":255},"buttonEars":{"longPressMs":65535,"veryLongPressMs":65535},"wifi":{"ssid":"12345678901234567890123456789012","password":"1234567890123456789012345678901234567890123456789012345678901234"},"log":{"sdLog":false},"misc":{"autodump":false,"swd":false,"watchdogSeconds":255}} //Size from https://arduinojson.org/v6/assistant/ class BoxConfig { diff --git a/BoxDAC.cpp b/BoxDAC.cpp index ba85bd7..d2cb6dc 100644 --- a/BoxDAC.cpp +++ b/BoxDAC.cpp @@ -119,6 +119,13 @@ void BoxDAC::begin() { Log.info("...done"); + uint8_t headsetDetect = readByte(ADDR_P0_SERIAL::HEADSET_DETECT); + Log.info("Headset detect=%B", headsetDetect); // Always no Headset detected?! TODO + if ((headsetDetect & 0b00100000) == 0b00100000) { + Events.handleHeadphoneEvent(HeadphoneEvent::INSERTED); + } else { + Events.handleHeadphoneEvent(HeadphoneEvent::REMOVED); + } //samSay("Hackiebox by Team Revvox!"); } void BoxDAC::opusTest() { @@ -187,6 +194,7 @@ void BoxDAC::loop() { } } void BoxDAC::loop(uint16_t timeoutMs) { + checkHeadphoneState(); if (audioPlaying) { if (!audioGenerator || !audioSource) { audioPlaying = false; @@ -767,12 +775,55 @@ void BoxDAC::initDACI2C() { send(ADDR::PAGE_CONTROL, PAGE::SERIAL_IO); - //send(ADDR_P0_SERIAL::DAC_DATA_PATH_SETUP, 0xD5); // DAC power on, Left=left, Right=Right, DAC Softstep HP STEREO - send(ADDR_P0_SERIAL::DAC_DATA_PATH_SETUP, 0xF1); // DAC power on, Left=left, Right=Right, DAC Softstep SPEAKER MONO + send(ADDR_P0_SERIAL::DAC_DATA_PATH_SETUP, 0xD5); // DAC power on, Left=left, Right=Right, DAC Softstep HP STEREO + //send(ADDR_P0_SERIAL::DAC_DATA_PATH_SETUP, 0xF1); // DAC power on, Left=left, Right=Right, DAC Softstep SPEAKER MONO send(ADDR_P0_SERIAL::DAC_VOL_L_CTRL, 0xDC); send(ADDR_P0_SERIAL::DAC_VOL_R_CTRL, 0xDC); //Excel 219 // Extract END send(ADDR::PAGE_CONTROL, PAGE::DAC_OUT_VOL); send(ADDR_P1_DAC_OUT::L_VOL_TO_SPK, 128); +} + + +void BoxDAC::muteSpeaker(bool mute) { + send(ADDR::PAGE_CONTROL, PAGE::DAC_OUT_VOL); + uint8_t state = readByte(ADDR_P1_DAC_OUT::SPK_DRIVER); + + if (mute) { + state &= ~(0b00000100); + } else { + state |= 0b00000100; + } + + send(ADDR_P1_DAC_OUT::SPK_DRIVER, state); +} +void BoxDAC::muteHeadphones(bool mute) { + send(ADDR::PAGE_CONTROL, PAGE::DAC_OUT_VOL); + uint8_t stateL = readByte(ADDR_P1_DAC_OUT::HPL_DRIVER); + uint8_t stateR = readByte(ADDR_P1_DAC_OUT::HPR_DRIVER); + + if (mute) { + stateL &= ~(0b00000100); + stateR &= ~(0b00000100); + } else { + stateL |= 0b00000100; + stateR |= 0b00000100; + } + + send(ADDR_P1_DAC_OUT::HPL_DRIVER, stateL); + send(ADDR_P1_DAC_OUT::HPR_DRIVER, stateR); +} + +void BoxDAC::checkHeadphoneState() { + send(ADDR::PAGE_CONTROL, PAGE::SERIAL_IO); + uint8_t intrFlags = readByte(ADDR_P0_SERIAL::DAC_INTR_FLAGS); + if ((intrFlags & 0b00010000) == 0b00010000) { + intrFlags = readByte(ADDR_P0_SERIAL::INTR_FLAGS); + if ((intrFlags & 0b00010000) == 0b00010000) { + Events.handleHeadphoneEvent(HeadphoneEvent::INSERTED); + } else { + Events.handleHeadphoneEvent(HeadphoneEvent::REMOVED); + } + } } \ No newline at end of file diff --git a/BoxDAC.h b/BoxDAC.h index 886a0bf..b57efc8 100755 --- a/BoxDAC.h +++ b/BoxDAC.h @@ -20,6 +20,10 @@ class BoxDAC : public EnhancedThread { public: + enum class HeadphoneEvent { + INSERTED, + REMOVED + }; void begin(), loop(), @@ -113,6 +117,9 @@ class BoxDAC : public EnhancedThread { void logVolume(); void logBeepVolume(uint8_t volume); + void muteSpeaker(bool mute); + void muteHeadphones(bool mute); + void play(), pause(), @@ -149,6 +156,8 @@ class BoxDAC : public EnhancedThread { DAC_DOSR_VAL_LSB = 0x0E, CODEC_IF_CTRL1 = 0x1B, DAC_FLAG_REG = 0x26, + DAC_INTR_FLAGS = 0x2C, + INTR_FLAGS = 0x2E, INT1_CTRL_REG = 0x30, GPIO1_INOUT_CTRL = 0x33, DAC_PROC_BLOCK_SEL = 0x3C, @@ -202,6 +211,7 @@ class BoxDAC : public EnhancedThread { readByte(ADDR_P3_MCLK source_register); void initDACI2C(); + void checkHeadphoneState(); uint8_t getSampleRateIndex(); uint16_t ofwButtonFreqTable[5][4][2] = { diff --git a/BoxEvents.cpp b/BoxEvents.cpp index 425b719..f818235 100644 --- a/BoxEvents.cpp +++ b/BoxEvents.cpp @@ -10,7 +10,7 @@ void BoxEvents::loop() { void BoxEvents::handleEarEvent(BoxButtonEars::EarButton earId, BoxButtonEars::PressedType pressType, BoxButtonEars::PressedTime pressLength) { const char* nameEar; const char* nameType; - const char* nameLength; + const char* nameDuration; switch (earId) { case BoxButtonEars::EarButton::SMALL: @@ -41,22 +41,27 @@ void BoxEvents::handleEarEvent(BoxButtonEars::EarButton earId, BoxButtonEars::Pr switch (pressLength) { case BoxButtonEars::PressedTime::SHORT: - nameLength = "short"; + nameDuration = "short"; break; case BoxButtonEars::PressedTime::LONG: - nameLength = "long"; + nameDuration = "long"; break; case BoxButtonEars::PressedTime::VERY_LONG: - nameLength = "very long"; + nameDuration = "very long"; break; default: - nameLength = "unknown length"; + nameDuration = "unknown length"; break; } - Log.info("%s %s-%s", nameEar, nameLength, nameType); + + Log.info("%s %s-%s", nameEar, nameDuration, nameType); Box.boxPower.feedSleepTimer(); + char earEvent[34]; + snprintf(earEvent, 34, "{\"id\":%i,\"type\":%i,\"duration\":%i}", earId, pressType, pressLength); + Box.webServer.sendEvent("Ear", earEvent, false); + if (pressType == BoxButtonEars::PressedType::PRESS) { if (pressLength == BoxButtonEars::PressedTime::SHORT) { if (earId == BoxButtonEars::EarButton::BIG) { @@ -126,6 +131,10 @@ void BoxEvents::handleEarEvent(BoxButtonEars::EarButton earId, BoxButtonEars::Pr } void BoxEvents::handleBatteryEvent(BoxBattery::BatteryEvent state) { + char batteryEvent[12]; + snprintf(batteryEvent, 12, "{\"state\":%i}", state); + Box.webServer.sendEvent("Battery", batteryEvent, false); + switch (state) { case BoxBattery::BatteryEvent::BAT_CRITICAL: Log.info("Battery is critical, connect the charger, hibernating!"); @@ -167,10 +176,9 @@ void BoxEvents::handleWiFiEvent(WrapperWiFi::ConnectionState state) { Box.boxWiFi.mDnsAdvertiseSetup(); break; case WrapperWiFi::ConnectionState::DISCONNECTED: - //Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Cyan, 3); + Box.boxLEDs.setActiveAnimationByIteration(BoxLEDs::ANIMATION_TYPE::BLINK, BoxLEDs::CRGB::Red, 3); Log.info("WiFi lost"); break; - default: break; } @@ -235,15 +243,24 @@ void BoxEvents::handleAccelerometerOrientationEvent(BoxAccelerometer::Orientatio break; } Log.info("Box' orientation changed to %s", orientText); + + char orientEvent[9]; + snprintf(orientEvent, 9, "{\"id\":%i}", orient); + Box.webServer.sendEvent("Orientation", orientEvent, false); + Box.boxPower.feedSleepTimer(); } void BoxEvents::handleTagEvent(BoxRFID::TAG_EVENT event) { + uint8_t uid[24]; + uid[0] = '\0'; + switch (event) { case BoxRFID::TAG_EVENT::TAG_PLACED: Log.info("Tag placed", event); Box.boxLEDs.setIdleAnimation(BoxLEDs::ANIMATION_TYPE::PARTY, BoxLEDs::CRGB::White); Box.boxRFID.logUID(); + Box.boxRFID.getUID(uid); if (!Box.boxDAC.hasStopped() && (memcmp(Box.boxRFID.tagUid, Box.boxTonie.currentUid, 8) == 0)) { Log.info("Continue playing last file"); @@ -305,5 +322,29 @@ void BoxEvents::handleTagEvent(BoxRFID::TAG_EVENT event) { Log.error("Unknown TAG_EVENT=%X", event); break; } + + + char tagEvent[44]; + snprintf(tagEvent, 44, "{\"event\":%i,\"uid\":\"%s\"}", event, uid, false); + Box.webServer.sendEvent("Tag", tagEvent, false); + Box.boxPower.feedSleepTimer(); +} + +void BoxEvents::handleHeadphoneEvent(BoxDAC::HeadphoneEvent event) { + switch (event){ + case BoxDAC::HeadphoneEvent::INSERTED: + Log.info("Headphones connected"); + Box.boxDAC.muteSpeaker(true); + Box.boxDAC.muteHeadphones(false); + break; + case BoxDAC::HeadphoneEvent::REMOVED: + Log.info("Headphones disconnected"); + Box.boxDAC.muteHeadphones(true); + Box.boxDAC.muteSpeaker(false); + break; + } + char hpEvent[12]; + snprintf(hpEvent, 12, "{\"event\":%i}", hpEvent); + Box.webServer.sendEvent("Headphones", hpEvent, false); } \ No newline at end of file diff --git a/BoxEvents.h b/BoxEvents.h index 5d198c5..ed26969 100644 --- a/BoxEvents.h +++ b/BoxEvents.h @@ -17,7 +17,8 @@ class BoxEvents { WIFI, POWER, ACCELEROMETER, - TAG + TAG, + HEADPHONE }; void @@ -30,6 +31,7 @@ class BoxEvents { void handlePowerEvent(BoxPower::PowerEvent event); void handleAccelerometerOrientationEvent(BoxAccelerometer::Orientation orient); void handleTagEvent(BoxRFID::TAG_EVENT event); + void handleHeadphoneEvent(BoxDAC::HeadphoneEvent event); private: }; diff --git a/ConfigStructures.h b/ConfigStructures.h index 1d31873..1e3abea 100644 --- a/ConfigStructures.h +++ b/ConfigStructures.h @@ -1,11 +1,11 @@ #ifndef ConfigStructures_h #define ConfigStructures_h -#define CONFIG_ACTIVE_VERSION 5 +#define CONFIG_ACTIVE_VERSION 7 typedef struct { uint32_t voltageFactor; - uint32_t voltageChargerFactor; + uint32_t _deprecated_voltageChargerFactor; uint16_t lowAdc; uint16_t criticalAdc; uint8_t sleepMinutes; @@ -42,6 +42,7 @@ typedef struct { typedef struct { bool autodump; bool swd; + uint8_t watchdogSeconds; } ConfigMisc; typedef struct { diff --git a/Hackiebox.cpp b/Hackiebox.cpp index d8eb9e8..89ac260 100755 --- a/Hackiebox.cpp +++ b/Hackiebox.cpp @@ -41,13 +41,15 @@ void crash(crashSource source, uint32_t* sp) { _file.close(); } Log.info("...done"); + + Box.logStreamMulti.flush(); //Write all buffered logs to SD/SSE __asm__ volatile("bkpt"); Box.boxPower.hibernate(); } void Hackiebox::setup() { - if (!watchdog_start()) { + if (!watchdog_start(10)) { watchdog_stop(); //reset box?! } @@ -76,6 +78,8 @@ void Hackiebox::setup() { boxSD.begin(); Config.begin(); //SD Card needed! ConfigStruct* config = Config.get(); + + watchdog_start(config->misc.watchdogSeconds); boxPower.begin(); boxI2C.begin(); @@ -211,22 +215,31 @@ void Hackiebox::watchdog_unfeed() { _watchdog_fed = false; } void watchdog_handler() { - if (Box.watchdog_isFed()) { + if (Box.watchdog_isFed() || !Box.watchdog_enabled) { MAP_WatchdogIntClear(WDT_BASE); Box.watchdog_unfeed(); } } -bool Hackiebox::watchdog_start() { +bool Hackiebox::watchdog_start(uint8_t timeoutS) { watchdog_feed(); - - MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK); - MAP_WatchdogUnlock(WDT_BASE); - MAP_IntPrioritySet(INT_WDT, INT_PRIORITY_LVL_1); - MAP_WatchdogStallEnable(WDT_BASE); //Allow Debugging - MAP_WatchdogIntRegister(WDT_BASE, watchdog_handler); - MAP_WatchdogReloadSet(WDT_BASE, 80000000*10); //10s - MAP_WatchdogEnable(WDT_BASE); - + if (timeoutS == 0) { + watchdog_start(53); + //watchdog_stop(); // Random watchdog triggers?! + watchdog_enabled = false; + } else { + if (timeoutS > 53) + timeoutS = 53; //otherwise uint32_t of WatchdogReloadSet will overflow. + + MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK); + MAP_WatchdogUnlock(WDT_BASE); + MAP_IntPrioritySet(INT_WDT, INT_PRIORITY_LVL_1); + MAP_WatchdogStallEnable(WDT_BASE); //Allow Debugging + MAP_WatchdogIntRegister(WDT_BASE, watchdog_handler); + MAP_WatchdogReloadSet(WDT_BASE, 80000000*timeoutS); + MAP_WatchdogEnable(WDT_BASE); + + watchdog_enabled = true; + } return MAP_WatchdogRunning(WDT_BASE); } void Hackiebox::watchdog_stop() { @@ -234,5 +247,7 @@ void Hackiebox::watchdog_stop() { MAP_WatchdogReloadSet(WDT_BASE, 0xFFFFFFFF); //set timer to high value MAP_WatchdogIntClear(WDT_BASE); MAP_WatchdogIntUnregister(WDT_BASE); + + watchdog_enabled = false; } diff --git a/Hackiebox.h b/Hackiebox.h index aa8b8cb..4106905 100644 --- a/Hackiebox.h +++ b/Hackiebox.h @@ -39,7 +39,7 @@ class Hackiebox { loop(); bool - watchdog_start(), + watchdog_start(uint8_t timeoutS), watchdog_isFed(); void watchdog_stop(), @@ -72,6 +72,7 @@ class Hackiebox { LogStreamSd logStreamSd; LogStreamSse logStreamSse; + bool watchdog_enabled; private:/* typedef void (*fAPPWDTDevCallbk)(); void diff --git a/LogStreamMulti.cpp b/LogStreamMulti.cpp index 153cf1d..f9831fa 100644 --- a/LogStreamMulti.cpp +++ b/LogStreamMulti.cpp @@ -27,6 +27,13 @@ size_t LogStreamMulti::write(const uint8_t *buffer, size_t size) { } memcpy(&_buffer[_getBufferPosition()], buffer+position, size-position); + for (uint8_t i=position; iprint("\" }\n\n"); // Extra newline required by SSE standard tagIsOpen = false; - } - client->flush(); + } } else { if (!_tagIsOpen) { client->print("data: { \"type\":\""); diff --git a/WrapperWebServer.cpp b/WrapperWebServer.cpp index f2c6769..79fdc09 100755 --- a/WrapperWebServer.cpp +++ b/WrapperWebServer.cpp @@ -513,20 +513,27 @@ void WrapperWebServer::handleUploadFlashFile() { handleNotFound(); } -void WrapperWebServer::sendEvent(const char* eventname, const char* content) { +void WrapperWebServer::sendEvent(const char* eventname, const char* content, bool escapeData) { bool clientConnected = false; for (uint8_t i = 0; i < SSE_MAX_CHANNELS; i++) { if (!(subscription[i].clientIP)) continue; + Box.logStreamMulti.flush(); sampleMemory(4); if (subscription[i].client.connected()) { clientConnected = true; subscription[i].client.print("data: { \"type\":\""); subscription[i].client.print(eventname); - subscription[i].client.print("\", \"data\":\""); - subscription[i].client.print(content); - subscription[i].client.print("\" }"); + if (escapeData) { + subscription[i].client.print("\", \"data\":\""); + subscription[i].client.print(content); + subscription[i].client.print("\" }"); + } else { + subscription[i].client.print("\", \"data\":"); + subscription[i].client.print(content); + subscription[i].client.print("}"); + } subscription[i].client.println("\n"); // Extra newline required by SSE standard } else { Log.info("Client not listening on channel %i, remove subscription", i); @@ -538,7 +545,7 @@ void WrapperWebServer::sendEvent(const char* eventname, const char* content) { } } if (clientConnected) - Box.boxPower.feedSleepTimer(); + Box.boxPower.feedSleepTimerSilent(); } void WrapperWebServer::sseKeepAlive() { sendEvent("keep-alive", ""); diff --git a/WrapperWebServer.h b/WrapperWebServer.h index 20b8f89..3b40c42 100755 --- a/WrapperWebServer.h +++ b/WrapperWebServer.h @@ -20,6 +20,10 @@ class WrapperWebServer : public EnhancedThread { void begin(), loop(); + + void + sendEvent(const char* eventname, const char* content, bool escapeData = true); + //sendEventJSON(char* eventname, xyzjsondoc jsonContent) private: void @@ -37,9 +41,7 @@ class WrapperWebServer : public EnhancedThread { void sseHandler(uint8_t channel), - sseKeepAlive(), - sendEvent(const char* eventname, const char* content); - //sendEventJSON(char* eventname, xyzjsondoc jsonContent); + sseKeepAlive(); bool diff --git a/WrapperWiFi.cpp b/WrapperWiFi.cpp index ea94f39..63c47bf 100755 --- a/WrapperWiFi.cpp +++ b/WrapperWiFi.cpp @@ -57,6 +57,7 @@ void WrapperWiFi::loop() { Events.handleWiFiEvent(_state); setInterval(5000); } + break; case ConnectionState::CONNECTED: if (WiFi.status() != WL_CONNECTED) { _state = ConnectionState::DISCONNECTED;