simplified main loop with coroutines
This commit is contained in:
parent
9566b8da48
commit
adabc92f1c
150
fw/main.c
150
fw/main.c
@ -33,6 +33,26 @@ static inline bool timer_expired(struct timer *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Button
|
||||||
|
struct button {
|
||||||
|
bool now, prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void button_init(struct button *btn, bool pullup)
|
||||||
|
{
|
||||||
|
btn->now = btn->prev = pullup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void button_update(struct button *btn, bool state)
|
||||||
|
{
|
||||||
|
btn->prev = btn->now;
|
||||||
|
btn->now = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define button_rising(btn) ((btn).now == true && (btn).prev == false)
|
||||||
|
#define button_falling(btn) ((btn).now == false && (btn).prev == true)
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ Global State ------------------------------ */
|
/* ------------------------------ Global State ------------------------------ */
|
||||||
u8g2_t *u8g2; // Display state
|
u8g2_t *u8g2; // Display state
|
||||||
int16_t encoder; // Rotary encoder counter
|
int16_t encoder; // Rotary encoder counter
|
||||||
@ -45,7 +65,6 @@ uint16_t vbus_mv; // USB bus voltage in mV
|
|||||||
uint16_t current_ma; // USB bus current to the heater in mA
|
uint16_t current_ma; // USB bus current to the heater in mA
|
||||||
uint16_t power; // Current power provided to the heater
|
uint16_t power; // Current power provided to the heater
|
||||||
uint16_t duty; // Current mosfet driver duty cycle (0-100%)
|
uint16_t duty; // Current mosfet driver duty cycle (0-100%)
|
||||||
bool pwm = false; // PWM status (on-off)
|
|
||||||
bool enabled = false; // Power electronics enabled
|
bool enabled = false; // Power electronics enabled
|
||||||
|
|
||||||
|
|
||||||
@ -493,10 +512,69 @@ static inline void update_tip_and_vcc(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// coroutine to draw the "main" ui which draws the current tip temperature, power
|
||||||
|
// pwm state, etc.
|
||||||
|
coro_state_t cs_ui;
|
||||||
|
coroutine c_draw_main_ui(coro_state_t *state)
|
||||||
|
{
|
||||||
|
static struct timer t;
|
||||||
|
coro_begin(state);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
// Wait for the next frame, roughly 30 fps
|
||||||
|
timer_set(&t, 33);
|
||||||
|
coro_wait_until(state, timer_expired(&t));
|
||||||
|
|
||||||
|
// Draw UI
|
||||||
|
u8g2_ClearBuffer(u8g2);
|
||||||
|
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||||
|
draw_temp(u8g2, x_off+0, y_off+0, tip_temp_c, true);
|
||||||
|
u8g2_DrawStr(u8g2, x_off+32, y_off+6, "A:");
|
||||||
|
u8g2_DrawStr(u8g2, x_off+42, y_off+6, u16toa((current_ma+500)/1000));
|
||||||
|
u8g2_DrawStr(u8g2, x_off+60, y_off+6, "V:");
|
||||||
|
u8g2_DrawStr(u8g2, x_off+70, y_off+6, u16toa((vbus_mv+500)/1000));
|
||||||
|
uint8_t p = (power*100)/pd_profile.set_power;
|
||||||
|
uint8_t w = (uint16_t)(p*54)/100;
|
||||||
|
u8g2_DrawBox(u8g2, x_off+42, y_off+14, w, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
coro_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// coroutine to update the tip temperature, vcc and compute the new pid value
|
||||||
|
// this has to be called periodically but only with pwm disabled
|
||||||
|
coro_state_t cs_duty;
|
||||||
|
coroutine c_update_duty(coro_state_t *state)
|
||||||
|
{
|
||||||
|
static struct timer t;
|
||||||
|
coro_begin(state);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
timer_set(&t, 50);
|
||||||
|
coro_wait_until(state, timer_expired(&t));
|
||||||
|
|
||||||
|
pwm_set(0);
|
||||||
|
Delay_Ms(TURN_OFF_DELAY);
|
||||||
|
update_tip_and_vcc();
|
||||||
|
if (enabled) {
|
||||||
|
duty = pid((int16_t)pd_profile.set_temp - tip_temp_c, pd_profile.max_duty);
|
||||||
|
} else {
|
||||||
|
duty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coro_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
__attribute__((noreturn)) int main(void)
|
__attribute__((noreturn)) int main(void)
|
||||||
{
|
{
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
coro_init(&cs_ui);
|
||||||
|
coro_init(&cs_duty);
|
||||||
|
|
||||||
u8g2_ClearBuffer(u8g2);
|
u8g2_ClearBuffer(u8g2);
|
||||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "Negotiating...");
|
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "Negotiating...");
|
||||||
@ -539,33 +617,21 @@ __attribute__((noreturn)) int main(void)
|
|||||||
STATE_MENU,
|
STATE_MENU,
|
||||||
STATE_HEATING,
|
STATE_HEATING,
|
||||||
} state = STATE_MENU;
|
} state = STATE_MENU;
|
||||||
|
|
||||||
|
/* ============================== Main Loop =============================== */
|
||||||
|
struct button btn;
|
||||||
|
button_init(&btn, true);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
u32 start = funSysTick32();
|
button_update(&btn, funDigitalRead(PIN_BTN));
|
||||||
|
|
||||||
u8g2_ClearBuffer(u8g2);
|
|
||||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
|
||||||
|
|
||||||
static uint8_t count = 0; // Loop cycles with PWM on
|
|
||||||
static s32 elapsed = 0;
|
|
||||||
static bool prev_btn = true;
|
|
||||||
bool btn = funDigitalRead(PIN_BTN);
|
|
||||||
|
|
||||||
if (has_pd) {
|
|
||||||
update_power_and_temperature();
|
update_power_and_temperature();
|
||||||
|
|
||||||
// Update the tip temperature only when the PWM is not running
|
c_update_duty(&cs_duty);
|
||||||
if (!pwm || !enabled) {
|
|
||||||
Delay_Ms(TURN_OFF_DELAY);
|
|
||||||
update_tip_and_vcc();
|
|
||||||
if (enabled) {
|
|
||||||
duty = pid((int16_t)pd_profile.set_temp - tip_temp_c, pd_profile.max_duty);
|
|
||||||
} else {
|
|
||||||
duty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_MENU:
|
case STATE_MENU:
|
||||||
|
u8g2_ClearBuffer(u8g2);
|
||||||
|
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TEMP:");
|
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TEMP:");
|
||||||
u8g2_DrawStr(u8g2, x_off+25, y_off+7, u8g2_u16toa(pd_profile.set_temp, 4));
|
u8g2_DrawStr(u8g2, x_off+25, y_off+7, u8g2_u16toa(pd_profile.set_temp, 4));
|
||||||
|
|
||||||
@ -576,53 +642,31 @@ __attribute__((noreturn)) int main(void)
|
|||||||
if (pd_profile.set_temp > MAX_TIP_SET_TEMP) pd_profile.set_temp = MAX_TIP_SET_TEMP;
|
if (pd_profile.set_temp > MAX_TIP_SET_TEMP) pd_profile.set_temp = MAX_TIP_SET_TEMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btn == 0 && prev_btn == 1) {
|
if (button_falling(btn)) {
|
||||||
state = STATE_HEATING;
|
state = STATE_HEATING;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATE_HEATING:
|
case STATE_HEATING:
|
||||||
// Draw UI
|
c_draw_main_ui(&cs_ui);
|
||||||
draw_temp(u8g2, x_off+0, y_off+0, tip_temp_c, true);
|
|
||||||
u8g2_DrawStr(u8g2, x_off+32, y_off+6, "A:");
|
|
||||||
u8g2_DrawStr(u8g2, x_off+42, y_off+6, u16toa((current_ma+500)/1000));
|
|
||||||
u8g2_DrawStr(u8g2, x_off+60, y_off+6, "V:");
|
|
||||||
u8g2_DrawStr(u8g2, x_off+70, y_off+6, u16toa((vbus_mv+500)/1000));
|
|
||||||
uint8_t p = (power*100)/pd_profile.set_power;
|
|
||||||
uint8_t w = (uint16_t)(p*54)/100;
|
|
||||||
u8g2_DrawBox(u8g2, x_off+42, y_off+14, w, 5);
|
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
funDigitalWrite(PIN_12V, 1);
|
funDigitalWrite(PIN_12V, 1);
|
||||||
|
|
||||||
if (count > CYCLES_PER_MEASURE) {
|
|
||||||
pwm = false;
|
|
||||||
count = 0;
|
|
||||||
} else {
|
|
||||||
pwm = true;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safety logic
|
// Safety logic
|
||||||
if (current_ma > pd_profile.max_current + pd_profile.max_current/10) {
|
if (current_ma > pd_profile.max_current + pd_profile.max_current/10) {
|
||||||
pwm = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
if (temp_c > MAX_BOARD_TEMP) {
|
if (temp_c > MAX_BOARD_TEMP) {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
pwm = false;
|
|
||||||
}
|
}
|
||||||
if (tip_temp_c > MAX_TIP_TEMP) {
|
if (tip_temp_c > MAX_TIP_TEMP) {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
pwm = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwm) {
|
|
||||||
const uint16_t tim_max = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
const uint16_t tim_max = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
||||||
pwm_set(((u32)duty*tim_max)/100);
|
pwm_set(((u32)duty*tim_max)/100);
|
||||||
u8g2_DrawBox(u8g2, x_off+92, y_off+0, 4, 4);
|
u8g2_DrawBox(u8g2, x_off+92, y_off+0, 4, 4);
|
||||||
} else {
|
|
||||||
pwm_set(0);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
funDigitalWrite(PIN_12V, 0);
|
funDigitalWrite(PIN_12V, 0);
|
||||||
}
|
}
|
||||||
@ -635,7 +679,7 @@ __attribute__((noreturn)) int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check button to toggle enable
|
// Check button to toggle enable
|
||||||
if (btn == 0 && prev_btn == 1) {
|
if (button_falling(btn)) {
|
||||||
enabled = !enabled;
|
enabled = !enabled;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
pwm_on();
|
pwm_on();
|
||||||
@ -645,18 +689,6 @@ __attribute__((noreturn)) int main(void)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// No PD capability, just display a message
|
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "NO PD");
|
|
||||||
}
|
|
||||||
|
|
||||||
u8g2_SendBuffer(u8g2);
|
u8g2_SendBuffer(u8g2);
|
||||||
|
|
||||||
prev_btn = btn;
|
|
||||||
|
|
||||||
elapsed = funSysTick32() - start;
|
|
||||||
if (elapsed > 0 && elapsed < Ticks_from_Ms(FRAME_TIME_MS)) {
|
|
||||||
DelaySysTick(Ticks_from_Ms(FRAME_TIME_MS) - elapsed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user