diff --git a/source/Core/BSP/MHP30/BSP.cpp b/source/Core/BSP/MHP30/BSP.cpp index d6a31b8b..30eb3fe5 100644 --- a/source/Core/BSP/MHP30/BSP.cpp +++ b/source/Core/BSP/MHP30/BSP.cpp @@ -13,405 +13,451 @@ #include "main.hpp" #include volatile uint16_t PWMSafetyTimer = 0; -volatile uint8_t pendingPWM = 0; -uint16_t totalPWM = 255; -const uint16_t powerPWM = 255; +volatile uint8_t pendingPWM = 0; +uint16_t totalPWM = 255; +const uint16_t powerPWM = 255; -history rawTempFilter = {{0}, 0, 0}; -void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); } +history rawTempFilter = { { 0 }, 0, 0 }; +void resetWatchdog() { + HAL_IWDG_Refresh(&hiwdg); +} #ifdef TEMP_NTC // Lookup table for the NTC // Stored as ADCReading,Temp in degC static const uint16_t NTCHandleLookup[] = { - // ADC Reading , Temp in Cx10 - 808, 1600, // - 832, 1590, // - 848, 1580, // - 872, 1570, // - 888, 1560, // - 912, 1550, // - 936, 1540, // - 960, 1530, // - 984, 1520, // - 1008, 1510, // - 1032, 1500, // - 1056, 1490, // - 1080, 1480, // - 1112, 1470, // - 1136, 1460, // - 1168, 1450, // - 1200, 1440, // - 1224, 1430, // - 1256, 1420, // - 1288, 1410, // - 1328, 1400, // - 1360, 1390, // - 1392, 1380, // - 1432, 1370, // - 1464, 1360, // - 1504, 1350, // - 1544, 1340, // - 1584, 1330, // - 1632, 1320, // - 1672, 1310, // - 1720, 1300, // - 1760, 1290, // - 1808, 1280, // - 1856, 1270, // - 1912, 1260, // - 1960, 1250, // - 2016, 1240, // - 2072, 1230, // - 2128, 1220, // - 2184, 1210, // - 2248, 1200, // - 2304, 1190, // - 2368, 1180, // - 2440, 1170, // - 2504, 1160, // - 2576, 1150, // - 2648, 1140, // - 2720, 1130, // - 2792, 1120, // - 2872, 1110, // - 2952, 1100, // - 3040, 1090, // - 3128, 1080, // - 3216, 1070, // - 3304, 1060, // - 3400, 1050, // - 3496, 1040, // - 3592, 1030, // - 3696, 1020, // - 3800, 1010, // - 3912, 1000, // - 4024, 990, // - 4136, 980, // - 4256, 970, // - 4376, 960, // - 4504, 950, // - 4632, 940, // - 4768, 930, // - 4904, 920, // - 5048, 910, // - 5192, 900, // - 5336, 890, // - 5488, 880, // - 5648, 870, // - 5808, 860, // - 5976, 850, // - 6144, 840, // - 6320, 830, // - 6504, 820, // - 6688, 810, // - 6872, 800, // - 7072, 790, // - 7264, 780, // - 7472, 770, // - 7680, 760, // - 7896, 750, // - 8112, 740, // - 8336, 730, // - 8568, 720, // - 8800, 710, // - 9040, 700, // - 9288, 690, // - 9536, 680, // - 9792, 670, // - 10056, 660, // - 10320, 650, // - 10592, 640, // - 10872, 630, // - 11152, 620, // - 11440, 610, // - 11728, 600, // - 12024, 590, // - 12320, 580, // - 12632, 570, // - 12936, 560, // - 13248, 550, // - 13568, 540, // - 13888, 530, // - 14216, 520, // - 14544, 510, // - 14880, 500, // - 15216, 490, // - 15552, 480, // - 15888, 470, // - 16232, 460, // - 16576, 450, // - 16920, 440, // - 17272, 430, // - 17616, 420, // - 17968, 410, // - 18320, 400, // - 18664, 390, // - 19016, 380, // - 19368, 370, // - 19712, 360, // - 20064, 350, // - 20408, 340, // - 20752, 330, // - 21088, 320, // - 21432, 310, // - 21768, 300, // - 22096, 290, // - 22424, 280, // - 22752, 270, // - 23072, 260, // - 23392, 250, // - 23704, 240, // - 24008, 230, // - 24312, 220, // - 24608, 210, // - 24904, 200, // - 25192, 190, // - 25472, 180, // - 25744, 170, // - 26016, 160, // - 26280, 150, // - 26536, 140, // - 26784, 130, // - 27024, 120, // - 27264, 110, // - 27496, 100, // - 27720, 90, // - 27936, 80, // - 28144, 70, // - 28352, 60, // - 28544, 50, // - 28736, 40, // - 28920, 30, // - 29104, 20, // - 29272, 10, // -}; -const int NTCHandleLookupItems = sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t)); +// ADC Reading , Temp in Cx10 + 808, 1600, // + 832, 1590, // + 848, 1580, // + 872, 1570, // + 888, 1560, // + 912, 1550, // + 936, 1540, // + 960, 1530, // + 984, 1520, // + 1008, 1510, // + 1032, 1500, // + 1056, 1490, // + 1080, 1480, // + 1112, 1470, // + 1136, 1460, // + 1168, 1450, // + 1200, 1440, // + 1224, 1430, // + 1256, 1420, // + 1288, 1410, // + 1328, 1400, // + 1360, 1390, // + 1392, 1380, // + 1432, 1370, // + 1464, 1360, // + 1504, 1350, // + 1544, 1340, // + 1584, 1330, // + 1632, 1320, // + 1672, 1310, // + 1720, 1300, // + 1760, 1290, // + 1808, 1280, // + 1856, 1270, // + 1912, 1260, // + 1960, 1250, // + 2016, 1240, // + 2072, 1230, // + 2128, 1220, // + 2184, 1210, // + 2248, 1200, // + 2304, 1190, // + 2368, 1180, // + 2440, 1170, // + 2504, 1160, // + 2576, 1150, // + 2648, 1140, // + 2720, 1130, // + 2792, 1120, // + 2872, 1110, // + 2952, 1100, // + 3040, 1090, // + 3128, 1080, // + 3216, 1070, // + 3304, 1060, // + 3400, 1050, // + 3496, 1040, // + 3592, 1030, // + 3696, 1020, // + 3800, 1010, // + 3912, 1000, // + 4024, 990, // + 4136, 980, // + 4256, 970, // + 4376, 960, // + 4504, 950, // + 4632, 940, // + 4768, 930, // + 4904, 920, // + 5048, 910, // + 5192, 900, // + 5336, 890, // + 5488, 880, // + 5648, 870, // + 5808, 860, // + 5976, 850, // + 6144, 840, // + 6320, 830, // + 6504, 820, // + 6688, 810, // + 6872, 800, // + 7072, 790, // + 7264, 780, // + 7472, 770, // + 7680, 760, // + 7896, 750, // + 8112, 740, // + 8336, 730, // + 8568, 720, // + 8800, 710, // + 9040, 700, // + 9288, 690, // + 9536, 680, // + 9792, 670, // + 10056, 660, // + 10320, 650, // + 10592, 640, // + 10872, 630, // + 11152, 620, // + 11440, 610, // + 11728, 600, // + 12024, 590, // + 12320, 580, // + 12632, 570, // + 12936, 560, // + 13248, 550, // + 13568, 540, // + 13888, 530, // + 14216, 520, // + 14544, 510, // + 14880, 500, // + 15216, 490, // + 15552, 480, // + 15888, 470, // + 16232, 460, // + 16576, 450, // + 16920, 440, // + 17272, 430, // + 17616, 420, // + 17968, 410, // + 18320, 400, // + 18664, 390, // + 19016, 380, // + 19368, 370, // + 19712, 360, // + 20064, 350, // + 20408, 340, // + 20752, 330, // + 21088, 320, // + 21432, 310, // + 21768, 300, // + 22096, 290, // + 22424, 280, // + 22752, 270, // + 23072, 260, // + 23392, 250, // + 23704, 240, // + 24008, 230, // + 24312, 220, // + 24608, 210, // + 24904, 200, // + 25192, 190, // + 25472, 180, // + 25744, 170, // + 26016, 160, // + 26280, 150, // + 26536, 140, // + 26784, 130, // + 27024, 120, // + 27264, 110, // + 27496, 100, // + 27720, 90, // + 27936, 80, // + 28144, 70, // + 28352, 60, // + 28544, 50, // + 28736, 40, // + 28920, 30, // + 29104, 20, // + 29272, 10, // + }; +const int NTCHandleLookupItems = sizeof(NTCHandleLookup) + / (2 * sizeof(uint16_t)); #endif // These are called by the HAL after the corresponding events from the system // timers. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { - // Period has elapsed - if (htim->Instance == TIM4) { - // STM uses this for internal functions as a counter for timeouts - HAL_IncTick(); - } + // Period has elapsed + if (htim->Instance == TIM4) { + // STM uses this for internal functions as a counter for timeouts + HAL_IncTick(); + } } uint16_t getHandleTemperature() { - int32_t result = getADC(0); - return Utils::InterpolateLookupTable(NTCHandleLookup, NTCHandleLookupItems, result); + int32_t result = getADC(0); + return Utils::InterpolateLookupTable(NTCHandleLookup, NTCHandleLookupItems, + result); } -uint16_t getTipInstantTemperature() { return getADC(2); } +uint16_t getTipInstantTemperature() { + return getADC(2); +} uint16_t getTipRawTemp(uint8_t refresh) { - if (refresh) { - uint16_t lastSample = getTipInstantTemperature(); - rawTempFilter.update(lastSample); - return lastSample; - } else { - return rawTempFilter.average(); - } + if (refresh) { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } else { + return rawTempFilter.average(); + } } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN - // Therefore we can divide down from there - // Multiplying ADC max by 4 for additional calibration options, - // ideal term is 467 - static uint8_t preFillneeded = 10; - static uint32_t samples[BATTFILTERDEPTH]; - static uint8_t index = 0; - if (preFillneeded) { - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - samples[i] = getADC(1); - preFillneeded--; - } - if (sample) { - samples[index] = getADC(1); - index = (index + 1) % BATTFILTERDEPTH; - } - uint32_t sum = 0; + // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN + // Therefore we can divide down from there + // Multiplying ADC max by 4 for additional calibration options, + // ideal term is 467 + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - sum += samples[i]; + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; - sum /= BATTFILTERDEPTH; - if (divisor == 0) { - divisor = 1; - } - return sum * 4 / divisor; + sum /= BATTFILTERDEPTH; + if (divisor == 0) { + divisor = 1; + } + return sum * 4 / divisor; } bool tryBetterPWM(uint8_t pwm) { - // We dont need this for the MHP30 - return false; + // We dont need this for the MHP30 + return false; } void setTipPWM(uint8_t pulse) { - // We can just set the timer directly - htim3.Instance->CCR1 = pulse; + // We can just set the timer directly + htim3.Instance->CCR1 = pulse; } void unstick_I2C() { - GPIO_InitTypeDef GPIO_InitStruct; - int timeout = 100; - int timeout_cnt = 0; + GPIO_InitTypeDef GPIO_InitStruct; + int timeout = 100; + int timeout_cnt = 0; - // 1. Clear PE bit. - hi2c1.Instance->CR1 &= ~(0x0001); - /**I2C1 GPIO Configuration - PB6 ------> I2C1_SCL - PB7 ------> I2C1_SDA - */ - // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + // 1. Clear PE bit. + hi2c1.Instance->CR1 &= ~(0x0001); + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Pin = SCL_Pin; - HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); - HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + GPIO_InitStruct.Pin = SCL_Pin; + HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); - GPIO_InitStruct.Pin = SDA_Pin; - HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); - HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); + GPIO_InitStruct.Pin = SDA_Pin; + HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { - // Move clock to release I2C - HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { + // Move clock to release I2C + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); - timeout_cnt++; - if (timeout_cnt > timeout) - return; - } + timeout_cnt++; + if (timeout_cnt > timeout) + return; + } - // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. - GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Pin = SCL_Pin; - HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); + GPIO_InitStruct.Pin = SCL_Pin; + HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); - GPIO_InitStruct.Pin = SDA_Pin; - HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); + GPIO_InitStruct.Pin = SDA_Pin; + HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); - HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); - HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - // 13. Set SWRST bit in I2Cx_CR1 register. - hi2c1.Instance->CR1 |= 0x8000; + // 13. Set SWRST bit in I2Cx_CR1 register. + hi2c1.Instance->CR1 |= 0x8000; - asm("nop"); + asm("nop"); - // 14. Clear SWRST bit in I2Cx_CR1 register. - hi2c1.Instance->CR1 &= ~0x8000; + // 14. Clear SWRST bit in I2Cx_CR1 register. + hi2c1.Instance->CR1 &= ~0x8000; - asm("nop"); + asm("nop"); - // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register - hi2c1.Instance->CR1 |= 0x0001; + // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register + hi2c1.Instance->CR1 |= 0x0001; - // Call initialization function. - HAL_I2C_Init(&hi2c1); + // Call initialization function. + HAL_I2C_Init(&hi2c1); } -uint8_t getButtonA() { return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? 1 : 0; } -uint8_t getButtonB() { return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? 1 : 0; } +uint8_t getButtonA() { + return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? + 1 : 0; +} +uint8_t getButtonB() { + return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? + 1 : 0; +} -void BSPInit(void) {} +void BSPInit(void) { + WS2812::init(); +} -void reboot() { NVIC_SystemReset(); } +void reboot() { + NVIC_SystemReset(); +} -void delay_ms(uint16_t count) { HAL_Delay(count); } +void delay_ms(uint16_t count) { + HAL_Delay(count); +} void setPlatePullup(bool pullingUp) { - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Pin = PLATE_SENSOR_PULLUP_Pin; - GPIO_InitStruct.Pull = GPIO_NOPULL; - if (pullingUp) { - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - HAL_GPIO_WritePin(PLATE_SENSOR_PULLUP_GPIO_Port, PLATE_SENSOR_PULLUP_Pin, GPIO_PIN_SET); - } else { - // Hi-z - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - HAL_GPIO_WritePin(PLATE_SENSOR_PULLUP_GPIO_Port, PLATE_SENSOR_PULLUP_Pin, GPIO_PIN_RESET); - } - HAL_GPIO_Init(PLATE_SENSOR_PULLUP_GPIO_Port, &GPIO_InitStruct); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Pin = PLATE_SENSOR_PULLUP_Pin; + GPIO_InitStruct.Pull = GPIO_NOPULL; + if (pullingUp) { + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_WritePin(PLATE_SENSOR_PULLUP_GPIO_Port, + PLATE_SENSOR_PULLUP_Pin, GPIO_PIN_SET); + } else { + // Hi-z + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + HAL_GPIO_WritePin(PLATE_SENSOR_PULLUP_GPIO_Port, + PLATE_SENSOR_PULLUP_Pin, GPIO_PIN_RESET); + } + HAL_GPIO_Init(PLATE_SENSOR_PULLUP_GPIO_Port, &GPIO_InitStruct); } uint16_t tipSenseResistancex10Ohms = 0; -bool isTipDisconnected() { - static bool lastTipDisconnectedState = true; - static uint16_t adcReadingPD1Set = 0; - static TickType_t lastMeas = 0; - // For the MHP30 we want to include a little extra logic in here - // As when the tip is first connected we want to measure the ~100 ohm resistor on the base of the tip - // And likewise if its removed we want to clear that measurement - /* - * plate_sensor_res = ((adc5_value_PD1_set - adc5_value_PD1_cleared) / (adc5_value_PD1_cleared + 4096 - adc5_value_PD1_set)) * 1000.0; - * */ +bool isTipDisconnected() { + static bool lastTipDisconnectedState = true; + static uint16_t adcReadingPD1Set = 0; + static TickType_t lastMeas = 0; + // For the MHP30 we want to include a little extra logic in here + // As when the tip is first connected we want to measure the ~100 ohm resistor on the base of the tip + // And likewise if its removed we want to clear that measurement + /* + * plate_sensor_res = ((adc5_value_PD1_set - adc5_value_PD1_cleared) / (adc5_value_PD1_cleared + 4096 - adc5_value_PD1_set)) * 1000.0; + * */ - bool tipDisconnected = getADC(2) > 4090; - // We have to handle here that this ^ will trip while measuring the gain resistor - if (xTaskGetTickCount() - lastMeas < (TICKS_100MS * 2 + (TICKS_100MS / 2))) { - tipDisconnected = false; - } + bool tipDisconnected = getADC(2) > 4090; + // We have to handle here that this ^ will trip while measuring the gain resistor + if (xTaskGetTickCount() - lastMeas + < (TICKS_100MS * 2 + (TICKS_100MS / 2))) { + tipDisconnected = false; + } - if (tipDisconnected != lastTipDisconnectedState) { - if (tipDisconnected) { - // Tip is now disconnected - tipSenseResistancex10Ohms = 0; // zero out the resistance - adcReadingPD1Set = 0; - lastMeas = 0; - } - lastTipDisconnectedState = tipDisconnected; - } - if (!tipDisconnected) { - if (tipSenseResistancex10Ohms == 0) { - if (lastMeas == 0) { - lastMeas = xTaskGetTickCount(); - setPlatePullup(true); - } else if (xTaskGetTickCount() - lastMeas > (TICKS_100MS)) { - lastMeas = xTaskGetTickCount(); - // We are sensing the resistance - if (adcReadingPD1Set == 0) { - // We will record the reading for PD1 being set - adcReadingPD1Set = getADC(3); - setPlatePullup(false); - } else { - // We have taken reading one - uint16_t adcReadingPD1Cleared = getADC(3); - uint32_t a = ((int)adcReadingPD1Set - (int)adcReadingPD1Cleared); - a *= 10000; - uint32_t b = ((int)adcReadingPD1Cleared + (32768 - (int)adcReadingPD1Set)); - if (b) { - tipSenseResistancex10Ohms = a / b; - } else { - tipSenseResistancex10Ohms = adcReadingPD1Set = lastMeas = 0; - } - if (tipSenseResistancex10Ohms > 1100 || tipSenseResistancex10Ohms < 900) { - tipSenseResistancex10Ohms = 0; // out of range - adcReadingPD1Set = 0; - lastMeas = 0; - } - } - } - return true; // we fake tip being disconnected until this is measured - } - } + if (tipDisconnected != lastTipDisconnectedState) { + if (tipDisconnected) { + // Tip is now disconnected + tipSenseResistancex10Ohms = 0; // zero out the resistance + adcReadingPD1Set = 0; + lastMeas = 0; + } + lastTipDisconnectedState = tipDisconnected; + } + if (!tipDisconnected) { + if (tipSenseResistancex10Ohms == 0) { + if (lastMeas == 0) { + lastMeas = xTaskGetTickCount(); + setPlatePullup(true); + } else if (xTaskGetTickCount() - lastMeas > (TICKS_100MS)) { + lastMeas = xTaskGetTickCount(); + // We are sensing the resistance + if (adcReadingPD1Set == 0) { + // We will record the reading for PD1 being set + adcReadingPD1Set = getADC(3); + setPlatePullup(false); + } else { + // We have taken reading one + uint16_t adcReadingPD1Cleared = getADC(3); + uint32_t a = ((int) adcReadingPD1Set + - (int) adcReadingPD1Cleared); + a *= 10000; + uint32_t b = ((int) adcReadingPD1Cleared + + (32768 - (int) adcReadingPD1Set)); + if (b) { + tipSenseResistancex10Ohms = a / b; + } else { + tipSenseResistancex10Ohms = adcReadingPD1Set = + lastMeas = 0; + } + if (tipSenseResistancex10Ohms > 1100 + || tipSenseResistancex10Ohms < 900) { + tipSenseResistancex10Ohms = 0; // out of range + adcReadingPD1Set = 0; + lastMeas = 0; + } + } + } + return true; // we fake tip being disconnected until this is measured + } + } - return tipDisconnected; + return tipDisconnected; } void setStatusLED(const enum StatusLED state) { - WS2812::led_set_color(0, 0xFF, 0, 0); - WS2812::led_update(1); + static enum StatusLED lastState = LED_UNKNOWN; + if (lastState != state) { + switch (state) { + case LED_UNKNOWN: + case LED_OFF: + WS2812::led_set_color(0, 0, 0, 0); + break; + case LED_STANDBY: + WS2812::led_set_color(0, 0, 0xFF, 0); //green + break; + case LED_HEATING: + WS2812::led_set_color(0, 0, 0, 0xFF); //Blue + break; + case LED_HOT: + WS2812::led_set_color(0, 0xFF, 0, 0); //red + break; + case LED_COOLING_STILL_HOT: + WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF); //white + break; + } + WS2812::led_update(); + lastState = state; + } } diff --git a/source/Core/BSP/MHP30/Setup.c b/source/Core/BSP/MHP30/Setup.c index e0851ded..95b72c52 100644 --- a/source/Core/BSP/MHP30/Setup.c +++ b/source/Core/BSP/MHP30/Setup.c @@ -16,8 +16,6 @@ DMA_HandleTypeDef hdma_i2c1_rx; DMA_HandleTypeDef hdma_i2c1_tx; IWDG_HandleTypeDef hiwdg; -TIM_HandleTypeDef htim1; -DMA_HandleTypeDef hdma_tim1_ch1; TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim3; #define ADC_CHANNELS 4 @@ -31,7 +29,6 @@ static void MX_I2C1_Init(void); static void MX_IWDG_Init(void); static void MX_TIM3_Init(void); static void MX_TIM2_Init(void); -static void MX_TIM1_Init(void); static void MX_DMA_Init(void); static void MX_GPIO_Init(void); static void MX_ADC2_Init(void); @@ -47,7 +44,6 @@ void Setup_HAL() { MX_ADC2_Init(); MX_TIM3_Init(); MX_TIM2_Init(); - MX_TIM1_Init(); MX_IWDG_Init(); HAL_ADC_Start(&hadc2); HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADCReadings, @@ -91,9 +87,9 @@ void SystemClock_Config(void) { RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16; // TIM - // 2,3,4,5,6,7,12,13,14 - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 64 mhz to some peripherals and adc + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // TIM + // 2,3,4,5,6,7,12,13,14 + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 64 mhz to some peripherals and adc HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); @@ -222,70 +218,6 @@ static void MX_IWDG_Init(void) { #endif } -/* TIM1 init function */ -void MX_TIM1_Init(void) { - - /* USER CODE BEGIN TIM1_Init 0 */ - - /* USER CODE END TIM1_Init 0 */ - - TIM_ClockConfigTypeDef sClockSourceConfig = {0}; - TIM_MasterConfigTypeDef sMasterConfig = {0}; - TIM_OC_InitTypeDef sConfigOC = {0}; - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; - - /* USER CODE BEGIN TIM1_Init 1 */ - - /* USER CODE END TIM1_Init 1 */ - htim1.Instance = TIM1; - htim1.Init.Prescaler = 0; - htim1.Init.CounterMode = TIM_COUNTERMODE_UP; - htim1.Init.Period = 42; - htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - htim1.Init.RepetitionCounter = 0; - htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; - HAL_TIM_Base_Init(&htim1); - - sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; - HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig); - - HAL_TIM_PWM_Init(&htim1); - - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig); - - sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; - sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; - sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; - HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); - - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.DeadTime = 0; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig); - - __HAL_RCC_GPIOA_CLK_ENABLE(); - GPIO_InitTypeDef GPIO_InitStruct; - /**TIM1 GPIO Configuration - PA8 ------> TIM1_CH1 - */ - GPIO_InitStruct.Pin = WS2812_Pin; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(WS2812_GPIO_Port, &GPIO_InitStruct); - __HAL_AFIO_REMAP_TIM1_DISABLE(); -} - /* TIM3 init function */ static void MX_TIM3_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; @@ -382,9 +314,6 @@ static void MX_DMA_Init(void) { /* DMA1_Channel1_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 10, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); - /* DMA1_Channel1_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 2, 0); // DMA 1 ch2 is used from TIM CH1 for WS2812 - HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn); /* DMA1_Channel6_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); @@ -438,8 +367,13 @@ static void MX_GPIO_Init(void) { GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(OLED_RESET_GPIO_Port, &GPIO_InitStruct); - HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = WS2812_Pin; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(WS2812_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(WS2812_GPIO_Port, WS2812_Pin, GPIO_PIN_RESET); // Pull down LCD reset HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); HAL_Delay(30); diff --git a/source/Core/BSP/MHP30/postRTOS.cpp b/source/Core/BSP/MHP30/postRTOS.cpp index 61e3647b..01fbe5af 100644 --- a/source/Core/BSP/MHP30/postRTOS.cpp +++ b/source/Core/BSP/MHP30/postRTOS.cpp @@ -3,7 +3,6 @@ #include "I2C_Wrapper.hpp" #include "QC3.h" #include "Settings.h" -#include "WS2812.h" #include "cmsis_os.h" #include "fusbpd.h" #include "main.hpp" @@ -13,13 +12,5 @@ // Initialisation to be performed with scheduler active void postRToSInit() { - WS2812::init(); - WS2812::led_set_color(0, 0xAA, 0x00, 0x00); - while (true) { - // osDelay(1); - // WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF); - // WS2812::led_update(1); - osDelay(10); - WS2812::led_update(1); - } + } diff --git a/source/Core/BSP/MHP30/stm32f1xx_hal_msp.c b/source/Core/BSP/MHP30/stm32f1xx_hal_msp.c index e2c57d11..607c4684 100644 --- a/source/Core/BSP/MHP30/stm32f1xx_hal_msp.c +++ b/source/Core/BSP/MHP30/stm32f1xx_hal_msp.c @@ -126,20 +126,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) { - if (htim_base->Instance == TIM1) { - __HAL_RCC_TIM1_CLK_ENABLE(); - __HAL_RCC_DMA1_CLK_ENABLE(); - hdma_tim1_ch1.Instance = DMA1_Channel2; - hdma_tim1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_tim1_ch1.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_tim1_ch1.Init.MemInc = DMA_MINC_ENABLE; - hdma_tim1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_tim1_ch1.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_tim1_ch1.Init.Mode = DMA_CIRCULAR; - hdma_tim1_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH; - HAL_DMA_Init(&hdma_tim1_ch1); - __HAL_LINKDMA(htim_base, hdma[TIM_DMA_ID_CC1], hdma_tim1_ch1); - } else if (htim_base->Instance == TIM3) { + if (htim_base->Instance == TIM3) { __HAL_RCC_TIM3_CLK_ENABLE(); } else if (htim_base->Instance == TIM2) { __HAL_RCC_TIM2_CLK_ENABLE(); diff --git a/source/Core/BSP/MHP30/stm32f1xx_it.c b/source/Core/BSP/MHP30/stm32f1xx_it.c index 40c327d1..955e935f 100644 --- a/source/Core/BSP/MHP30/stm32f1xx_it.c +++ b/source/Core/BSP/MHP30/stm32f1xx_it.c @@ -42,14 +42,11 @@ void DMA1_Channel1_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_adc1); } // ADC interrupt used for DMA void ADC1_2_IRQHandler(void) { HAL_ADC_IRQHandler(&hadc1); } -// Timer 1 has overflowed, used for HAL ticks -void TIM1_UP_IRQHandler(void) { HAL_TIM_IRQHandler(&htim1); } - +//used for hal ticks void TIM4_IRQHandler(void) { HAL_TIM_IRQHandler(&htim4); } void I2C1_EV_IRQHandler(void) { HAL_I2C_EV_IRQHandler(&hi2c1); } void I2C1_ER_IRQHandler(void) { HAL_I2C_ER_IRQHandler(&hi2c1); } -void DMA1_Channel2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_tim1_ch1); } void DMA1_Channel6_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_tx); } void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); } diff --git a/source/Core/Drivers/WS2812.cpp b/source/Core/Drivers/WS2812.cpp index f9060b56..e8cc6b7b 100644 --- a/source/Core/Drivers/WS2812.cpp +++ b/source/Core/Drivers/WS2812.cpp @@ -5,178 +5,106 @@ * Author: Ralim */ -#include "FreeRTOS.h" -#include "task.h" #include +#include "Pins.h" #include -uint8_t WS2812::leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; -volatile uint16_t WS2812::tmp_led_data[2 * WS2812_RAW_BYTES_PER_LED]; -volatile uint8_t WS2812::is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ -volatile uint8_t WS2812::is_updating; /*!< Is updating in progress? */ -volatile uint32_t WS2812::current_led; /*!< Current LED number we are sending */ +uint8_t WS2812::leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; void WS2812::init(void) { - memset(leds_colors, 0, sizeof(leds_colors)); - hdma_tim1_ch1.XferHalfCpltCallback = DMAHalfComplete; - hdma_tim1_ch1.XferCpltCallback = DMAComplete; - htim1.Instance->CCR1 = htim1.Instance->ARR / 2 - 1; - htim1.Instance->DIER |= TIM_DIER_CC1DE; + memset(leds_colors, 0, sizeof(leds_colors)); + } -uint8_t WS2812::led_update(uint8_t block) { - if (is_updating) { /* Check if update in progress already */ - return 0; - } - is_updating = 1; /* We are now updating */ +void WS2812::led_update() { + __disable_irq(); +//Bitbang it out as our cpu irq latency is too high + for (unsigned int i = 0; i < sizeof(leds_colors); i++) { + //Shove out MSB first + for (int x = 0; x < 8; x++) { + WS2812_GPIO_Port->BSRR = WS2812_Pin; + if ((leds_colors[i] & (1 << (7 - x))) == (1 << (7 - x))) { + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + } else { - led_start_reset_pulse(1); /* Start reset pulse */ - if (block) { - while (!led_is_update_finished()) { - vTaskDelay(1); - }; /* Wait to finish */ - } - return 1; + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + } + WS2812_GPIO_Port->BSRR = (uint32_t) WS2812_Pin << 16u; + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + __asm__ __volatile__("nop"); + } + } + __enable_irq(); } void WS2812::led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b) { - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = g; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = r; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; } void WS2812::led_set_color_all(uint8_t r, uint8_t g, uint8_t b) { - for (int index = 0; index < WS2812_LED_COUNT; index++) { - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; - } -} - -uint8_t WS2812::led_is_update_finished(void) { return !is_updating; } - -void WS2812::led_start_reset_pulse(uint8_t num) { - is_reset_pulse = num; /* Set reset pulse flag */ - - memset((void *)tmp_led_data, 0, sizeof(tmp_led_data)); /* Set all bytes to 0 to achieve 50us pulse */ - - if (num == 1) { - tmp_led_data[0] = (htim1.Instance->ARR * 2) / 3; // start with half width pulse - } - - /* Set DMA to normal mode, set memory to beginning of data and length to 40 elements */ - /* 800kHz PWM x 40 samples = ~50us pulse low */ - hdma_tim1_ch1.Instance->CCR &= (~DMA_CCR_CIRC); // clear circular flag -> normal mode - hdma_tim1_ch1.State = HAL_DMA_STATE_READY; - HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED); - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); -} - -void WS2812::DMAHalfComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(0); } - -void WS2812::DMAComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(1); } - -void WS2812::led_update_sequence(uint8_t tc) { - tc = !!tc; /* Convert to 1 or 0 value only */ - - /* Check for reset pulse at the end of PWM stream */ - if (is_reset_pulse == 2) { /* Check for reset pulse at the end */ - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); - is_updating = 0; /* We are not updating anymore */ - return; - } - - /* Check for reset pulse on beginning of PWM stream */ - if (is_reset_pulse == 1) { /* Check if we finished with reset pulse */ - /* - * When reset pulse is active, we have to wait full DMA response, - * before we can start modifying array which is shared with DMA and PWM - */ - if (!tc) { /* We must wait for transfer complete */ - return; /* Return and wait to finish */ - } - - /* Disable timer output and disable DMA stream */ - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); - - is_reset_pulse = 0; /* Not in reset pulse anymore */ - current_led = 0; /* Reset current led */ - } else { - /* - * When we are not in reset mode, - * go to next led and process data for it - */ - current_led++; /* Go to next LED */ - } - - /* - * This part is used to prepare data for "next" led, - * for which update will start once current transfer stops in circular mode - */ - if (current_led < WS2812_LED_COUNT) { - /* - * If we are preparing data for first time (current_led == 0) - * or if there was no TC event (it was HT): - * - * - Prepare first part of array, because either there is no transfer - * or second part (from HT to TC) is now in process for PWM transfer - * - * In other case (TC = 1) - */ - if (current_led == 0 || !tc) { - led_fill_led_pwm_data(current_led, &tmp_led_data[0]); - } else { - led_fill_led_pwm_data(current_led, &tmp_led_data[WS2812_RAW_BYTES_PER_LED]); - } - - /* - * If we are preparing first led (current_led = 0), then: - * - * - We setup first part of array for first led, - * - We have to prepare second part for second led to have one led prepared in advance - * - Set DMA to circular mode and start the transfer + PWM output - */ - if (current_led == 0) { - - current_led++; /* Go to next LED */ - led_fill_led_pwm_data(current_led, &tmp_led_data[WS2812_RAW_BYTES_PER_LED]); /* Prepare second LED too */ - hdma_tim1_ch1.Instance->CCR |= (DMA_CCR_CIRC); // set circular flag for circular mode - hdma_tim1_ch1.State = HAL_DMA_STATE_READY; - HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED); - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); - } - - /* - * When we reached all leds, we have to wait to transmit data for all leds before we can disable DMA and PWM: - * - * - If TC event is enabled and we have EVEN number of LEDS (2, 4, 6, ...) - * - If HT event is enabled and we have ODD number of LEDS (1, 3, 5, ...) - */ - } else if ((!tc && (WS2812_LED_COUNT & 0x01)) || (tc && !(WS2812_LED_COUNT & 0x01))) { - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); - - /* It is time to send final reset pulse, 50us at least */ - led_start_reset_pulse(2); /* Start reset pulse at the end */ - } -} - -void WS2812::led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr) { - size_t i; - uint16_t OnOffValues[] = {2 * htim1.Instance->ARR / 3, (4 * htim1.Instance->ARR) / 3}; - - if (ledx < WS2812_LED_COUNT) { - for (i = 0; i < 8; i++) { - // Also unmux RGB -> GRB in the index order here - ptr[i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 1] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; - ptr[8 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 0] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; - ptr[16 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 2] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; -#if WS2812_LED_CHANNEL_COUNT == 4 - ptr[24 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 3] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; -#endif - } - } else { - // Fill with zero? - } + for (int index = 0; index < WS2812_LED_COUNT; index++) { + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = g; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = r; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; + } } diff --git a/source/Core/Drivers/WS2812.h b/source/Core/Drivers/WS2812.h index 3b2221c3..045dd549 100644 --- a/source/Core/Drivers/WS2812.h +++ b/source/Core/Drivers/WS2812.h @@ -11,7 +11,7 @@ #ifndef CORE_DRIVERS_WS2812_H_ #define CORE_DRIVERS_WS2812_H_ #ifndef WS2812_LED_COUNT -#define WS2812_LED_COUNT 3 +#define WS2812_LED_COUNT 2 #endif #ifndef WS2812_LED_CHANNEL_COUNT #define WS2812_LED_CHANNEL_COUNT 3 @@ -19,23 +19,14 @@ #define WS2812_RAW_BYTES_PER_LED (WS2812_LED_CHANNEL_COUNT * 8) class WS2812 { public: - static void init(void); - static uint8_t led_update(uint8_t block); - static void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b); - static void led_set_color_all(uint8_t r, uint8_t g, uint8_t b); + static void init(void); + static void led_update(); + static void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b); + static void led_set_color_all(uint8_t r, uint8_t g, uint8_t b); private: - static uint8_t led_is_update_finished(void); - static void led_start_reset_pulse(uint8_t num); - static void DMAHalfComplete(DMA_HandleTypeDef *hdma); - static void DMAComplete(DMA_HandleTypeDef *hdma); - static void led_update_sequence(uint8_t tc); - static void led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr); - static uint8_t leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; - static volatile uint16_t tmp_led_data[2 * WS2812_RAW_BYTES_PER_LED]; - static volatile uint8_t is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ - static volatile uint8_t is_updating; /*!< Is updating in progress? */ - static volatile uint32_t current_led; /*!< Current LED number we are sending */ + + static uint8_t leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; }; #endif /* CORE_DRIVERS_WS2812_H_ */ diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 4753fba6..9b11673a 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -26,69 +26,69 @@ extern "C" { #include "policy_engine.h" #endif // File local variables -extern uint32_t currentTempTargetDegC; +extern uint32_t currentTempTargetDegC; extern TickType_t lastMovementTime; extern osThreadId GUITaskHandle; extern osThreadId MOVTaskHandle; extern osThreadId PIDTaskHandle; -static bool shouldBeSleeping(bool inAutoStart = false); -static bool shouldShutdown(); -void showWarnings(); +static bool shouldBeSleeping(bool inAutoStart = false); +static bool shouldShutdown(); +void showWarnings(); #define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ) #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) static TickType_t lastHallEffectSleepStart = 0; -static uint16_t min(uint16_t a, uint16_t b) { - if (a > b) - return b; - else - return a; +static uint16_t min(uint16_t a, uint16_t b) { + if (a > b) + return b; + else + return a; } void warnUser(const char *warning, const int timeout) { - OLED::clearScreen(); - OLED::printWholeScreen(warning); - OLED::refresh(); - waitForButtonPressOrTimeout(timeout); + OLED::clearScreen(); + OLED::printWholeScreen(warning); + OLED::refresh(); + waitForButtonPressOrTimeout(timeout); } void printVoltage() { - uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); - OLED::printNumber(volt / 10, 2, FontStyle::SMALL); - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(volt % 10, 1, FontStyle::SMALL); + uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); + OLED::printNumber(volt / 10, 2, FontStyle::SMALL); + OLED::print(SymbolDot, FontStyle::SMALL); + OLED::printNumber(volt % 10, 1, FontStyle::SMALL); } void GUIDelay() { - // Called in all UI looping tasks, - // This limits the re-draw rate to the LCD and also lets the DMA run - // As the gui task can very easily fill this bus with transactions, which will - // prevent the movement detection from running - osDelay(50); + // Called in all UI looping tasks, + // This limits the re-draw rate to the LCD and also lets the DMA run + // As the gui task can very easily fill this bus with transactions, which will + // prevent the movement detection from running + osDelay(50); } void gui_drawTipTemp(bool symbol, const FontStyle font) { - // Draw tip temp handling unit conversion & tolerance near setpoint - uint32_t Temp = 0; - if (systemSettings.temperatureInF) { - Temp = TipThermoModel::getTipInF(); - } else { - Temp = TipThermoModel::getTipInC(); - } + // Draw tip temp handling unit conversion & tolerance near setpoint + uint32_t Temp = 0; + if (systemSettings.temperatureInF) { + Temp = TipThermoModel::getTipInF(); + } else { + Temp = TipThermoModel::getTipInC(); + } - OLED::printNumber(Temp, 3, font); // Draw the tip temp out - if (symbol) { - if (font == FontStyle::LARGE) { - // Big font, can draw nice symbols - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else - OLED::drawSymbol(1); - } else { - // Otherwise fall back to chars - if (systemSettings.temperatureInF) - OLED::print(SymbolDegF, FontStyle::SMALL); - else - OLED::print(SymbolDegC, FontStyle::SMALL); - } - } + OLED::printNumber(Temp, 3, font); // Draw the tip temp out + if (symbol) { + if (font == FontStyle::LARGE) { + // Big font, can draw nice symbols + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else + OLED::drawSymbol(1); + } else { + // Otherwise fall back to chars + if (systemSettings.temperatureInF) + OLED::print(SymbolDegF, FontStyle::SMALL); + else + OLED::print(SymbolDegC, FontStyle::SMALL); + } + } } #ifdef POW_DC @@ -127,25 +127,25 @@ static bool checkVoltageForExit() { #endif static void gui_drawBatteryIcon() { #if defined(POW_PD) || defined(POW_QC) - if (!getIsPoweredByDCIN()) { - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show dual small ones vertically stacked - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::printNumber(V / 10, 1, FontStyle::SMALL); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1, FontStyle::SMALL); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1, FontStyle::LARGE); - } - return; - } + if (!getIsPoweredByDCIN()) { + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show dual small ones vertically stacked + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1; // round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::printNumber(V / 10, 1, FontStyle::SMALL); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1, FontStyle::SMALL); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1, FontStyle::LARGE); + } + return; + } #endif #ifdef POW_DC if (systemSettings.minDCVoltageCells) { @@ -167,205 +167,240 @@ static void gui_drawBatteryIcon() { #endif } static void gui_solderingTempAdjust() { - uint32_t lastChange = xTaskGetTickCount(); - currentTempTargetDegC = 0; - uint32_t autoRepeatTimer = 0; - uint8_t autoRepeatAcceleration = 0; - bool waitForRelease = false; - ButtonState buttons = getButtonState(); - if (buttons != BUTTON_NONE) { - // Temp adjust entered by long-pressing F button. - waitForRelease = true; - } - for (;;) { - OLED::setCursor(0, 0); - OLED::clearScreen(); - buttons = getButtonState(); - if (buttons) { - if (waitForRelease) { - buttons = BUTTON_NONE; - } - lastChange = xTaskGetTickCount(); - } else { - waitForRelease = false; - } - switch (buttons) { - case BUTTON_NONE: - // stay - autoRepeatAcceleration = 0; - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; + uint32_t lastChange = xTaskGetTickCount(); + currentTempTargetDegC = 0; + uint32_t autoRepeatTimer = 0; + uint8_t autoRepeatAcceleration = 0; + bool waitForRelease = false; + ButtonState buttons = getButtonState(); + if (buttons != BUTTON_NONE) { + // Temp adjust entered by long-pressing F button. + waitForRelease = true; + } + for (;;) { + OLED::setCursor(0, 0); + OLED::clearScreen(); + buttons = getButtonState(); + if (buttons) { + if (waitForRelease) { + buttons = BUTTON_NONE; + } + lastChange = xTaskGetTickCount(); + } else { + waitForRelease = false; + } + switch (buttons) { + case BUTTON_NONE: + // stay + autoRepeatAcceleration = 0; + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_B_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; - break; - case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_F_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 - } else - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 - break; - default: - break; - } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; - } - // constrain between 10-450 C - if (systemSettings.temperatureInF) { - if (systemSettings.SolderingTemp > 850) - systemSettings.SolderingTemp = 850; - if (systemSettings.SolderingTemp < 60) - systemSettings.SolderingTemp = 60; - } else { - if (systemSettings.SolderingTemp > 450) - systemSettings.SolderingTemp = 450; - if (systemSettings.SolderingTemp < 10) - systemSettings.SolderingTemp = 10; - } + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_B_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; + break; + case BUTTON_F_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_F_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; // add 10 + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; // add 10 + break; + default: + break; + } + if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) + < PRESS_ACCEL_INTERVAL_MIN) { + autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX + - PRESS_ACCEL_INTERVAL_MIN; + } + // constrain between 10-450 C + if (systemSettings.temperatureInF) { + if (systemSettings.SolderingTemp > 850) + systemSettings.SolderingTemp = 850; + if (systemSettings.SolderingTemp < 60) + systemSettings.SolderingTemp = 60; + } else { + if (systemSettings.SolderingTemp > 450) + systemSettings.SolderingTemp = 450; + if (systemSettings.SolderingTemp < 10) + systemSettings.SolderingTemp = 10; + } - if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) - return; // exit if user just doesn't press anything for a bit + if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) + return; // exit if user just doesn't press anything for a bit #ifdef OLED_FLIP if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus, FontStyle::LARGE); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus, FontStyle::LARGE); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus, FontStyle::LARGE); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus, FontStyle::LARGE); + } - OLED::print(SymbolSpace, FontStyle::LARGE); - OLED::printNumber(systemSettings.SolderingTemp, 3, FontStyle::LARGE); - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else { - OLED::drawSymbol(1); - } - OLED::print(SymbolSpace, FontStyle::LARGE); + OLED::print(SymbolSpace, FontStyle::LARGE); + OLED::printNumber(systemSettings.SolderingTemp, 3, FontStyle::LARGE); + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else { + OLED::drawSymbol(1); + } + OLED::print(SymbolSpace, FontStyle::LARGE); #ifdef OLED_FLIP if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus, FontStyle::LARGE); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus, FontStyle::LARGE); - } - OLED::refresh(); - GUIDelay(); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus, FontStyle::LARGE); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus, FontStyle::LARGE); + } + OLED::refresh(); + GUIDelay(); + } } static bool shouldShutdown() { - if (systemSettings.ShutdownTime) { // only allow shutdown exit if time > 0 - if (lastMovementTime) { - if (((TickType_t)(xTaskGetTickCount() - lastMovementTime)) > (TickType_t)(systemSettings.ShutdownTime * TICKS_MIN)) { - return true; - } - } - if (lastHallEffectSleepStart) { - if (((TickType_t)(xTaskGetTickCount() - lastHallEffectSleepStart)) > (TickType_t)(systemSettings.ShutdownTime * TICKS_MIN)) { - return true; - } - } - } - return false; + if (systemSettings.ShutdownTime) { // only allow shutdown exit if time > 0 + if (lastMovementTime) { + if (((TickType_t) (xTaskGetTickCount() - lastMovementTime)) + > (TickType_t) (systemSettings.ShutdownTime * TICKS_MIN)) { + return true; + } + } + if (lastHallEffectSleepStart) { + if (((TickType_t) (xTaskGetTickCount() - lastHallEffectSleepStart)) + > (TickType_t) (systemSettings.ShutdownTime * TICKS_MIN)) { + return true; + } + } + } + return false; } static int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) { - // Drop to sleep temperature and display until movement or button press + // Drop to sleep temperature and display until movement or button press - for (;;) { - // user moved or pressed a button, go back to soldering - // If in the first two seconds we disable this to let accelerometer warm up + for (;;) { + // user moved or pressed a button, go back to soldering + // If in the first two seconds we disable this to let accelerometer warm up #ifdef POW_DC if (checkVoltageForExit()) return 1; // return non-zero on error #endif - if (systemSettings.temperatureInF) { - currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); - } else { - currentTempTargetDegC = stayOff ? 0 : min(systemSettings.SleepTemp, systemSettings.SolderingTemp); - } - // draw the lcd - uint16_t tipTemp; - if (systemSettings.temperatureInF) - tipTemp = TipThermoModel::getTipInF(); - else { - tipTemp = TipThermoModel::getTipInC(); - } + if (systemSettings.temperatureInF) { + currentTempTargetDegC = + stayOff ? + 0 : + TipThermoModel::convertFtoC( + min(systemSettings.SleepTemp, + systemSettings.SolderingTemp)); + } else { + currentTempTargetDegC = + stayOff ? + 0 : + min(systemSettings.SleepTemp, + systemSettings.SolderingTemp); + } + // draw the lcd + uint16_t tipTemp; + if (systemSettings.temperatureInF) + tipTemp = TipThermoModel::getTipInF(); + else { + tipTemp = TipThermoModel::getTipInC(); + } - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedSoldering) { - OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL); - OLED::setCursor(0, 8); - OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL); - OLED::printNumber(tipTemp, 3, FontStyle::SMALL); - if (systemSettings.temperatureInF) - OLED::print(SymbolDegF, FontStyle::SMALL); - else { - OLED::print(SymbolDegC, FontStyle::SMALL); - } + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedSoldering) { + OLED::print(translatedString(Tr->SleepingAdvancedString), + FontStyle::SMALL); + OLED::setCursor(0, 8); + OLED::print(translatedString(Tr->SleepingTipAdvancedString), + FontStyle::SMALL); + OLED::printNumber(tipTemp, 3, FontStyle::SMALL); + if (systemSettings.temperatureInF) + OLED::print(SymbolDegF, FontStyle::SMALL); + else { + OLED::print(SymbolDegC, FontStyle::SMALL); + } - OLED::print(SymbolSpace, FontStyle::SMALL); - printVoltage(); - OLED::print(SymbolVolts, FontStyle::SMALL); - } else { - OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE); - OLED::printNumber(tipTemp, 3, FontStyle::LARGE); - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else { - OLED::drawSymbol(1); - } - } + OLED::print(SymbolSpace, FontStyle::SMALL); + printVoltage(); + OLED::print(SymbolVolts, FontStyle::SMALL); + } else { + OLED::print(translatedString(Tr->SleepingSimpleString), + FontStyle::LARGE); + OLED::printNumber(tipTemp, 3, FontStyle::LARGE); + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else { + OLED::drawSymbol(1); + } + } - OLED::refresh(); - GUIDelay(); + OLED::refresh(); + GUIDelay(); #ifdef ACCEL_EXITS_ON_MOVEMENT - // If the accel works in reverse where movement will cause exiting the soldering mode - if (systemSettings.sensitivity) { - if (lastMovementTime) { - if (lastMovementTime > TICKS_SECOND * 10) { - // If we have moved recently; in the last second - // Then exit soldering mode + // If the accel works in reverse where movement will cause exiting the soldering mode + if (systemSettings.sensitivity) { + if (lastMovementTime) { + if (lastMovementTime > TICKS_SECOND * 10) { + // If we have moved recently; in the last second + // Then exit soldering mode - if (((TickType_t)(xTaskGetTickCount() - lastMovementTime)) < (TickType_t)(TICKS_SECOND)) { - currentTempTargetDegC = 0; - return 1; - } - } - } - } + if (((TickType_t) (xTaskGetTickCount() - lastMovementTime)) + < (TickType_t) (TICKS_SECOND)) { + currentTempTargetDegC = 0; + return 1; + } + } + } + } #else if (!shouldBeSleeping(autoStarted)) { @@ -373,13 +408,13 @@ static int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) { } #endif - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode - } - } - return 0; + if (shouldShutdown()) { + // shutdown + currentTempTargetDegC = 0; + return 1; // we want to exit soldering mode + } + } + return 0; } #ifndef NO_SLEEP_MODE @@ -450,176 +485,186 @@ static bool shouldBeSleeping(bool inAutoStart) { } #endif #endif - return false; + return false; } static void gui_solderingMode(uint8_t jumpToSleep) { - /* - * * Soldering (gui_solderingMode) - * -> Main loop where we draw temp, and animations - * --> User presses buttons and they goto the temperature adjust screen - * ---> Display the current setpoint temperature - * ---> Use buttons to change forward and back on temperature - * ---> Both buttons or timeout for exiting - * --> Long hold front button to enter boost mode - * ---> Just temporarily sets the system into the alternate temperature for - * PID control - * --> Long hold back button to exit - * --> Double button to exit - * --> Long hold double button to toggle key lock - */ - bool boostModeOn = false; - bool buttonsLocked = false; + /* + * * Soldering (gui_solderingMode) + * -> Main loop where we draw temp, and animations + * --> User presses buttons and they goto the temperature adjust screen + * ---> Display the current setpoint temperature + * ---> Use buttons to change forward and back on temperature + * ---> Both buttons or timeout for exiting + * --> Long hold front button to enter boost mode + * ---> Just temporarily sets the system into the alternate temperature for + * PID control + * --> Long hold back button to exit + * --> Double button to exit + * --> Long hold double button to toggle key lock + */ + bool boostModeOn = false; + bool buttonsLocked = false; - if (jumpToSleep) { - if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) { - lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit - } - } - for (;;) { - ButtonState buttons = getButtonState(); - if (buttonsLocked && (systemSettings.lockingMode != 0)) { // If buttons locked - switch (buttons) { - case BUTTON_NONE: - boostModeOn = false; - break; - case BUTTON_BOTH_LONG: - // Unlock buttons - buttonsLocked = false; - warnUser(translatedString(Tr->UnlockingKeysString), TICKS_SECOND); - break; - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (systemSettings.BoostTemp && (systemSettings.lockingMode == 1)) { - boostModeOn = true; - } - break; - // fall through - case BUTTON_BOTH: - case BUTTON_B_LONG: - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: - // Do nothing and display a lock warming - warnUser(translatedString(Tr->WarningKeysLockedString), TICKS_SECOND / 2); - break; - default: - break; - } - } else { // Button not locked - switch (buttons) { - case BUTTON_NONE: - // stay - boostModeOn = false; - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - return; // exit on back long hold - break; - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (systemSettings.BoostTemp) - boostModeOn = true; - break; - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { - uint16_t oldTemp = systemSettings.SolderingTemp; - gui_solderingTempAdjust(); // goto adjust temp mode - if (oldTemp != systemSettings.SolderingTemp) { - saveSettings(); // only save on change - } - } break; - case BUTTON_BOTH_LONG: - if (systemSettings.lockingMode != 0) { - // Lock buttons - buttonsLocked = true; - warnUser(translatedString(Tr->LockingKeysString), TICKS_SECOND); - } - break; - default: - break; - } - } - // else we update the screen information - OLED::setCursor(0, 0); - OLED::clearScreen(); - // Draw in the screen details - if (systemSettings.detailedSoldering) { - OLED::print(translatedString(Tr->SolderingAdvancedPowerPrompt), - FontStyle::SMALL); // Power: - OLED::printNumber(x10WattHistory.average() / 10, 2, FontStyle::SMALL); - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(x10WattHistory.average() % 10, 1, FontStyle::SMALL); - OLED::print(SymbolWatts, FontStyle::SMALL); + if (jumpToSleep) { + if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) { + lastButtonTime = xTaskGetTickCount(); + return; // If the function returns non-0 then exit + } + } + for (;;) { + ButtonState buttons = getButtonState(); + if (buttonsLocked && (systemSettings.lockingMode != 0)) { // If buttons locked + switch (buttons) { + case BUTTON_NONE: + boostModeOn = false; + break; + case BUTTON_BOTH_LONG: + // Unlock buttons + buttonsLocked = false; + warnUser(translatedString(Tr->UnlockingKeysString), + TICKS_SECOND); + break; + case BUTTON_F_LONG: + // if boost mode is enabled turn it on + if (systemSettings.BoostTemp + && (systemSettings.lockingMode == 1)) { + boostModeOn = true; + } + break; + // fall through + case BUTTON_BOTH: + case BUTTON_B_LONG: + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: + // Do nothing and display a lock warming + warnUser(translatedString(Tr->WarningKeysLockedString), + TICKS_SECOND / 2); + break; + default: + break; + } + } else { // Button not locked + switch (buttons) { + case BUTTON_NONE: + // stay + boostModeOn = false; + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + return; // exit on back long hold + break; + case BUTTON_F_LONG: + // if boost mode is enabled turn it on + if (systemSettings.BoostTemp) + boostModeOn = true; + break; + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: { + uint16_t oldTemp = systemSettings.SolderingTemp; + gui_solderingTempAdjust(); // goto adjust temp mode + if (oldTemp != systemSettings.SolderingTemp) { + saveSettings(); // only save on change + } + } + break; + case BUTTON_BOTH_LONG: + if (systemSettings.lockingMode != 0) { + // Lock buttons + buttonsLocked = true; + warnUser(translatedString(Tr->LockingKeysString), + TICKS_SECOND); + } + break; + default: + break; + } + } + // else we update the screen information + OLED::setCursor(0, 0); + OLED::clearScreen(); + // Draw in the screen details + if (systemSettings.detailedSoldering) { + OLED::print(translatedString(Tr->SolderingAdvancedPowerPrompt), + FontStyle::SMALL); // Power: + OLED::printNumber(x10WattHistory.average() / 10, 2, + FontStyle::SMALL); + OLED::print(SymbolDot, FontStyle::SMALL); + OLED::printNumber(x10WattHistory.average() % 10, 1, + FontStyle::SMALL); + OLED::print(SymbolWatts, FontStyle::SMALL); #ifndef NO_SLEEP_MODE if (systemSettings.sensitivity && systemSettings.SleepTime) { OLED::print(SymbolSpace, FontStyle::SMALL); display_countdown(getSleepTimeout()); } #endif - OLED::setCursor(0, 8); - OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL); - gui_drawTipTemp(true, FontStyle::SMALL); + OLED::setCursor(0, 8); + OLED::print(translatedString(Tr->SleepingTipAdvancedString), + FontStyle::SMALL); + gui_drawTipTemp(true, FontStyle::SMALL); - if (boostModeOn) { - OLED::print(SymbolPlus, FontStyle::SMALL); - } else { - OLED::print(SymbolSpace, FontStyle::SMALL); - } + if (boostModeOn) { + OLED::print(SymbolPlus, FontStyle::SMALL); + } else { + OLED::print(SymbolSpace, FontStyle::SMALL); + } - printVoltage(); - OLED::print(SymbolVolts, FontStyle::SMALL); - } else { - // We switch the layout direction depending on the orientation of the oled - if (OLED::getRotation()) { - // battery - gui_drawBatteryIcon(); - OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp - gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp + printVoltage(); + OLED::print(SymbolVolts, FontStyle::SMALL); + } else { + // We switch the layout direction depending on the orientation of the oled + if (OLED::getRotation()) { + // battery + gui_drawBatteryIcon(); + OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp + gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace, FontStyle::LARGE); + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace, FontStyle::LARGE); - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - } else { - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace, FontStyle::LARGE); - gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + } else { + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace, FontStyle::LARGE); + gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp - OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp + OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp - gui_drawBatteryIcon(); - } - } - OLED::refresh(); + gui_drawBatteryIcon(); + } + } + OLED::refresh(); - // Update the setpoints for the temperature - if (boostModeOn) { - if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); - else { - currentTempTargetDegC = (systemSettings.BoostTemp); - } - } else { - if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); - else { - currentTempTargetDegC = (systemSettings.SolderingTemp); - } - } + // Update the setpoints for the temperature + if (boostModeOn) { + if (systemSettings.temperatureInF) + currentTempTargetDegC = TipThermoModel::convertFtoC( + systemSettings.BoostTemp); + else { + currentTempTargetDegC = (systemSettings.BoostTemp); + } + } else { + if (systemSettings.temperatureInF) + currentTempTargetDegC = TipThermoModel::convertFtoC( + systemSettings.SolderingTemp); + else { + currentTempTargetDegC = (systemSettings.SolderingTemp); + } + } #ifdef POW_DC // Undervoltage test @@ -629,141 +674,154 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } #endif - if (shouldBeSleeping()) { - if (gui_SolderingSleepingMode(false, false)) { - return; // If the function returns non-0 then exit - } - } - // slow down ui update rate - GUIDelay(); - } + if (shouldBeSleeping()) { + if (gui_SolderingSleepingMode(false, false)) { + return; // If the function returns non-0 then exit + } + } + // slow down ui update rate + GUIDelay(); + } } void showDebugMenu(void) { - uint8_t screen = 0; - ButtonState b; - for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::print(SymbolVersionNumber, FontStyle::SMALL); // Print version number - OLED::setCursor(0, 8); // second line - OLED::print(DebugMenu[screen], FontStyle::SMALL); - switch (screen) { - case 0: // Just prints date - break; - case 1: - // High water mark for GUI - OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5, FontStyle::SMALL); - break; - case 2: - // High water mark for the Movement task - OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5, FontStyle::SMALL); - break; - case 3: - // High water mark for the PID task - OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5, FontStyle::SMALL); - break; - case 4: - // system up time stamp - OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 5, FontStyle::SMALL); - break; - case 5: - // Movement time stamp - OLED::printNumber(lastMovementTime / TICKS_100MS, 5, FontStyle::SMALL); - break; - case 6: - // Raw Tip - { OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 6, FontStyle::SMALL); } - break; - case 7: - // Temp in C - OLED::printNumber(TipThermoModel::getTipInC(), 5, FontStyle::SMALL); - break; - case 8: - // Handle Temp - OLED::printNumber(getHandleTemperature(), 3, FontStyle::SMALL); - break; - case 9: - // Voltage input - printVoltage(); - break; - case 10: - // Print PCB ID number - OLED::printNumber(DetectedAccelerometerVersion, 2, FontStyle::SMALL); - break; - case 11: - // Power negotiation status - if (getIsPoweredByDCIN()) { - OLED::printNumber(0, 1, FontStyle::SMALL); - } else { - // We are not powered via DC, so want to display the appropriate state for PD or QC - bool poweredbyPD = false; + uint8_t screen = 0; + ButtonState b; + for (;;) { + OLED::clearScreen(); // Ensure the buffer starts clean + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::print(SymbolVersionNumber, FontStyle::SMALL); // Print version number + OLED::setCursor(0, 8); // second line + OLED::print(DebugMenu[screen], FontStyle::SMALL); + switch (screen) { + case 0: // Just prints date + break; + case 1: + // High water mark for GUI + OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5, + FontStyle::SMALL); + break; + case 2: + // High water mark for the Movement task + OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5, + FontStyle::SMALL); + break; + case 3: + // High water mark for the PID task + OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5, + FontStyle::SMALL); + break; + case 4: + // system up time stamp + OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 5, + FontStyle::SMALL); + break; + case 5: + // Movement time stamp + OLED::printNumber(lastMovementTime / TICKS_100MS, 5, + FontStyle::SMALL); + break; + case 6: + // Raw Tip + { + OLED::printNumber( + TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), + true), 6, FontStyle::SMALL); + } + break; + case 7: + // Temp in C + OLED::printNumber(TipThermoModel::getTipInC(), 5, FontStyle::SMALL); + break; + case 8: + // Handle Temp + OLED::printNumber(getHandleTemperature(), 3, FontStyle::SMALL); + break; + case 9: + // Voltage input + printVoltage(); + break; + case 10: + // Print PCB ID number + OLED::printNumber(DetectedAccelerometerVersion, 2, + FontStyle::SMALL); + break; + case 11: + // Power negotiation status + if (getIsPoweredByDCIN()) { + OLED::printNumber(0, 1, FontStyle::SMALL); + } else { + // We are not powered via DC, so want to display the appropriate state for PD or QC + bool poweredbyPD = false; #ifdef POW_PD - if (usb_pd_detect()) { - // We are PD capable - if (PolicyEngine::pdHasNegotiated()) { - // We are powered via PD - poweredbyPD = true; - } - } + if (usb_pd_detect()) { + // We are PD capable + if (PolicyEngine::pdHasNegotiated()) { + // We are powered via PD + poweredbyPD = true; + } + } #endif - if (poweredbyPD) { - OLED::printNumber(2, 1, FontStyle::SMALL); - } else { + if (poweredbyPD) { + OLED::printNumber(2, 1, FontStyle::SMALL); + } else { - OLED::printNumber(1, 1, FontStyle::SMALL); - } - } - break; - case 12: - // Max deg C limit - OLED::printNumber(TipThermoModel::getTipMaxInC(), 3, FontStyle::SMALL); - break; - default: - break; - } + OLED::printNumber(1, 1, FontStyle::SMALL); + } + } + break; + case 12: + // Max deg C limit + OLED::printNumber(TipThermoModel::getTipMaxInC(), 3, + FontStyle::SMALL); + break; + default: + break; + } - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) - return; - else if (b == BUTTON_F_SHORT) { - screen++; - screen = screen % 13; - } - GUIDelay(); - } + OLED::refresh(); + b = getButtonState(); + if (b == BUTTON_B_SHORT) + return; + else if (b == BUTTON_F_SHORT) { + screen++; + screen = screen % 13; + } + GUIDelay(); + } } void showWarnings() { - // Display alert if settings were reset - if (settingsWereReset) { - warnUser(translatedString(Tr->SettingsResetMessage), 10 * TICKS_SECOND); - } + // Display alert if settings were reset + if (settingsWereReset) { + warnUser(translatedString(Tr->SettingsResetMessage), 10 * TICKS_SECOND); + } #ifndef NO_WARN_MISSING - // We also want to alert if accel or pd is not detected / not responding - // In this case though, we dont want to nag the user _too_ much - // So only show first 2 times - while (DetectedAccelerometerVersion == ACCELEROMETERS_SCANNING) { - osDelay(5); - } - // Display alert if accelerometer is not detected - if (DetectedAccelerometerVersion == NO_DETECTED_ACCELEROMETER) { - if (systemSettings.accelMissingWarningCounter < 2) { - systemSettings.accelMissingWarningCounter++; - saveSettings(); - warnUser(translatedString(Tr->NoAccelerometerMessage), 10 * TICKS_SECOND); - } - } + // We also want to alert if accel or pd is not detected / not responding + // In this case though, we dont want to nag the user _too_ much + // So only show first 2 times + while (DetectedAccelerometerVersion == ACCELEROMETERS_SCANNING) { + osDelay(5); + } + // Display alert if accelerometer is not detected + if (DetectedAccelerometerVersion == NO_DETECTED_ACCELEROMETER) { + if (systemSettings.accelMissingWarningCounter < 2) { + systemSettings.accelMissingWarningCounter++; + saveSettings(); + warnUser(translatedString(Tr->NoAccelerometerMessage), + 10 * TICKS_SECOND); + } + } #ifdef POW_PD - // We expect pd to be present - if (!usb_pd_detect()) { - if (systemSettings.pdMissingWarningCounter < 2) { - systemSettings.pdMissingWarningCounter++; - saveSettings(); - warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); - } - } + // We expect pd to be present + if (!usb_pd_detect()) { + if (systemSettings.pdMissingWarningCounter < 2) { + systemSettings.pdMissingWarningCounter++; + saveSettings(); + warnUser(translatedString(Tr->NoPowerDeliveryMessage), + 10 * TICKS_SECOND); + } + } #endif #endif } @@ -771,183 +829,198 @@ void showWarnings() { uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { - prepareTranslations(); + prepareTranslations(); - OLED::initialize(); // start up the LCD + OLED::initialize(); // start up the LCD - uint8_t tempWarningState = 0; - bool buttonLockout = false; - bool tempOnDisplay = false; - bool tipDisconnectedDisplay = false; - { - // Generate the flipped screen into ram for later use - // flipped is generated by flipping each row - for (int row = 0; row < 2; row++) { - for (int x = 0; x < 84; x++) { - idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + (83 - x)]; - } - } - } - getTipRawTemp(1); // reset filter - OLED::setRotation(systemSettings.OrientationMode & 1); - uint32_t ticks = xTaskGetTickCount(); - ticks += (TICKS_SECOND * 4); // 4 seconds from now - while (xTaskGetTickCount() < ticks) { - if (showBootLogoIfavailable() == false) - ticks = xTaskGetTickCount(); - ButtonState buttons = getButtonState(); - if (buttons) - ticks = xTaskGetTickCount(); // make timeout now so we will exit - GUIDelay(); - } + uint8_t tempWarningState = 0; + bool buttonLockout = false; + bool tempOnDisplay = false; + bool tipDisconnectedDisplay = false; + { + // Generate the flipped screen into ram for later use + // flipped is generated by flipping each row + for (int row = 0; row < 2; row++) { + for (int x = 0; x < 84; x++) { + idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + + (83 - x)]; + } + } + } + getTipRawTemp(1); // reset filter + OLED::setRotation(systemSettings.OrientationMode & 1); + uint32_t ticks = xTaskGetTickCount(); + ticks += (TICKS_SECOND * 4); // 4 seconds from now + while (xTaskGetTickCount() < ticks) { + if (showBootLogoIfavailable() == false) + ticks = xTaskGetTickCount(); + ButtonState buttons = getButtonState(); + if (buttons) + ticks = xTaskGetTickCount(); // make timeout now so we will exit + GUIDelay(); + } - showWarnings(); + showWarnings(); - if (systemSettings.autoStartMode) { - // jump directly to the autostart mode - gui_solderingMode(systemSettings.autoStartMode - 1); - buttonLockout = true; - } + if (systemSettings.autoStartMode) { + // jump directly to the autostart mode + gui_solderingMode(systemSettings.autoStartMode - 1); + buttonLockout = true; + } - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons != BUTTON_NONE) { - OLED::setDisplayState(OLED::DisplayState::ON); - } - if (tempWarningState == 2) - buttons = BUTTON_F_SHORT; - if (buttons != BUTTON_NONE && buttonLockout) - buttons = BUTTON_NONE; - else - buttonLockout = false; + for (;;) { + ButtonState buttons = getButtonState(); + if (buttons != BUTTON_NONE) { + OLED::setDisplayState(OLED::DisplayState::ON); + } + if (tempWarningState == 2) + buttons = BUTTON_F_SHORT; + if (buttons != BUTTON_NONE && buttonLockout) + buttons = BUTTON_NONE; + else + buttonLockout = false; - switch (buttons) { - case BUTTON_NONE: - // Do nothing - break; - case BUTTON_BOTH: - // Not used yet - // In multi-language this might be used to reset language on a long hold - // or some such - break; + switch (buttons) { + case BUTTON_NONE: + // Do nothing + break; + case BUTTON_BOTH: + // Not used yet + // In multi-language this might be used to reset language on a long hold + // or some such + break; - case BUTTON_B_LONG: - // Show the version information - showDebugMenu(); - break; - case BUTTON_F_LONG: - gui_solderingTempAdjust(); - saveSettings(); - break; - case BUTTON_F_SHORT: - if (!isTipDisconnected()) { - gui_solderingMode(0); // enter soldering mode - buttonLockout = true; - } - break; - case BUTTON_B_SHORT: - enterSettingsMenu(); // enter the settings menu - buttonLockout = true; - break; - default: - break; - } + case BUTTON_B_LONG: + // Show the version information + showDebugMenu(); + break; + case BUTTON_F_LONG: + gui_solderingTempAdjust(); + saveSettings(); + break; + case BUTTON_F_SHORT: + if (!isTipDisconnected()) { + gui_solderingMode(0); // enter soldering mode + buttonLockout = true; + } + break; + case BUTTON_B_SHORT: + enterSettingsMenu(); // enter the settings menu + buttonLockout = true; + break; + default: + break; + } - currentTempTargetDegC = 0; // ensure tip is off - getInputVoltageX10(systemSettings.voltageDiv, 0); - uint32_t tipTemp = TipThermoModel::getTipInC(); + currentTempTargetDegC = 0; // ensure tip is off + getInputVoltageX10(systemSettings.voltageDiv, 0); + uint32_t tipTemp = TipThermoModel::getTipInC(); + if (tipTemp > 55) { + setStatusLED(LED_COOLING_STILL_HOT); + } else { + setStatusLED(LED_OFF); + } + // Preemptively turn the display on. Turn it off if and only if + // the tip temperature is below 50 degrees C *and* motion sleep + // detection is enabled *and* there has been no activity (movement or + // button presses) in a while. + // This is zero cost really as state is only changed on display updates + OLED::setDisplayState(OLED::DisplayState::ON); - // Preemptively turn the display on. Turn it off if and only if - // the tip temperature is below 50 degrees C *and* motion sleep - // detection is enabled *and* there has been no activity (movement or - // button presses) in a while. - // This is zero cost really as state is only changed on display updates - OLED::setDisplayState(OLED::DisplayState::ON); + if ((tipTemp < 50) && systemSettings.sensitivity + && (((xTaskGetTickCount() - lastMovementTime) + > MOVEMENT_INACTIVITY_TIME) + && ((xTaskGetTickCount() - lastButtonTime) + > BUTTON_INACTIVITY_TIME))) { + OLED::setDisplayState(OLED::DisplayState::OFF); + } + // Clear the lcd buffer + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedIDLE) { + if (isTipDisconnected()) { + OLED::print(translatedString(Tr->TipDisconnectedString), + FontStyle::SMALL); + } else { + OLED::print(translatedString(Tr->IdleTipString), + FontStyle::SMALL); + gui_drawTipTemp(false, FontStyle::SMALL); + OLED::print(translatedString(Tr->IdleSetString), + FontStyle::SMALL); + OLED::printNumber(systemSettings.SolderingTemp, 3, + FontStyle::SMALL); + } + OLED::setCursor(0, 8); - if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { - OLED::setDisplayState(OLED::DisplayState::OFF); - } - // Clear the lcd buffer - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedIDLE) { - if (isTipDisconnected()) { - OLED::print(translatedString(Tr->TipDisconnectedString), FontStyle::SMALL); - } else { - OLED::print(translatedString(Tr->IdleTipString), FontStyle::SMALL); - gui_drawTipTemp(false, FontStyle::SMALL); - OLED::print(translatedString(Tr->IdleSetString), FontStyle::SMALL); - OLED::printNumber(systemSettings.SolderingTemp, 3, FontStyle::SMALL); - } - OLED::setCursor(0, 8); + OLED::print(translatedString(Tr->InputVoltageString), + FontStyle::SMALL); + printVoltage(); - OLED::print(translatedString(Tr->InputVoltageString), FontStyle::SMALL); - printVoltage(); - - } else { + } else { #ifdef OLED_FLIP if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::drawArea(12, 0, 84, 16, idleScreenBG); - OLED::setCursor(0, 0); - gui_drawBatteryIcon(); - } else { - OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up - // on right side of screen - OLED::setCursor(84, 0); - gui_drawBatteryIcon(); - } - tipDisconnectedDisplay = false; - if (tipTemp > 55) - tempOnDisplay = true; - else if (tipTemp < 45) - tempOnDisplay = false; - if (isTipDisconnected()) { - tempOnDisplay = false; - tipDisconnectedDisplay = true; - } - if (tempOnDisplay || tipDisconnectedDisplay) { - // draw temp over the start soldering button - // Location changes on screen rotation + OLED::drawArea(12, 0, 84, 16, idleScreenBG); + OLED::setCursor(0, 0); + gui_drawBatteryIcon(); + } else { + OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up + // on right side of screen + OLED::setCursor(84, 0); + gui_drawBatteryIcon(); + } + tipDisconnectedDisplay = false; + if (tipTemp > 55) + tempOnDisplay = true; + else if (tipTemp < 45) + tempOnDisplay = false; + if (isTipDisconnected()) { + tempOnDisplay = false; + tipDisconnectedDisplay = true; + } + if (tempOnDisplay || tipDisconnectedDisplay) { + // draw temp over the start soldering button + // Location changes on screen rotation #ifdef OLED_FLIP if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - // in right handed mode we want to draw over the first part - OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp - OLED::setCursor(56, 0); + // in right handed mode we want to draw over the first part + OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp + OLED::setCursor(56, 0); - } else { - OLED::fillArea(0, 0, 41, 16, 0); // clear the area - OLED::setCursor(0, 0); - } - // If we have a tip connected draw the temp, if not we leave it blank - if (!tipDisconnectedDisplay) { - // draw in the temp - if (!(systemSettings.coolingTempBlink && (xTaskGetTickCount() % 260 < 160))) - gui_drawTipTemp(false, FontStyle::LARGE); // draw in the temp - } else { - // Draw in missing tip symbol + } else { + OLED::fillArea(0, 0, 41, 16, 0); // clear the area + OLED::setCursor(0, 0); + } + // If we have a tip connected draw the temp, if not we leave it blank + if (!tipDisconnectedDisplay) { + // draw in the temp + if (!(systemSettings.coolingTempBlink + && (xTaskGetTickCount() % 260 < 160))) + gui_drawTipTemp(false, FontStyle::LARGE); // draw in the temp + } else { + // Draw in missing tip symbol #ifdef OLED_FLIP if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - // in right handed mode we want to draw over the first part - OLED::drawArea(55, 0, 41, 16, disconnectedTipIcon); + // in right handed mode we want to draw over the first part + OLED::drawArea(55, 0, 41, 16, disconnectedTipIcon); - } else { - OLED::drawArea(0, 0, 41, 16, disconnectedTipIcon); - } - } - } - } + } else { + OLED::drawArea(0, 0, 41, 16, disconnectedTipIcon); + } + } + } + } - OLED::refresh(); - GUIDelay(); - } + OLED::refresh(); + GUIDelay(); + } }