Removing timer as wont work & replace with bit bang
Cant keep up with irq
This commit is contained in:
@@ -13,405 +13,451 @@
|
||||
#include "main.hpp"
|
||||
#include <IRQ.h>
|
||||
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<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0};
|
||||
void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); }
|
||||
history<uint16_t, PID_TIM_HZ> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -5,178 +5,106 @@
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include <WS2812.h>
|
||||
#include "Pins.h"
|
||||
#include <string.h>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user