state machine encoder logic and first simple menu
This commit is contained in:
parent
65ac37fd62
commit
5e12e9a4a0
125
fw/main.c
125
fw/main.c
@ -69,20 +69,64 @@ void handle_usbfs_input(int numbytes, uint8_t *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// triggered on the falling edge of the rotary encoder PIN_A
|
/*
|
||||||
|
* __ ____ ____
|
||||||
|
* A: |____| |____| |____
|
||||||
|
* ____ ____ __
|
||||||
|
* B: ____| |____| |____|
|
||||||
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||||
|
* f r r f f r r f f r
|
||||||
|
*/
|
||||||
|
void update_encoder(void)
|
||||||
|
{
|
||||||
|
// 0 = 00, 1 = 01, 2 = 10, 3 = 11
|
||||||
|
static uint8_t last_state = 0;
|
||||||
|
// Lookup table: state_table[last_state][current_state]
|
||||||
|
// 0 = invalid move or bounce (ignore)
|
||||||
|
// 1 = valid forward step
|
||||||
|
// -1 = valid backward step
|
||||||
|
static const int8_t state_table[4][4] = {
|
||||||
|
{ 0, 1, -1, 0}, // from 00
|
||||||
|
{-1, 0, 0, 1}, // from 01
|
||||||
|
{ 1, 0, 0, -1}, // from 10
|
||||||
|
{ 0, -1, 1, 0} // from 11
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: even with interrupts disabled and debounce, a single detent triggers
|
||||||
|
// multiple interrupts, leading to multiple encoder updates in a short time.
|
||||||
|
bool a = funDigitalRead(PIN_ENC_A);
|
||||||
|
bool b = funDigitalRead(PIN_ENC_B);
|
||||||
|
Delay_Us(100);
|
||||||
|
if (a != funDigitalRead(PIN_ENC_A) || b != funDigitalRead(PIN_ENC_B))
|
||||||
|
return; // debounce
|
||||||
|
|
||||||
|
uint8_t current_state = (a << 1) | b;
|
||||||
|
|
||||||
|
// Find the movement direction based on transition
|
||||||
|
encoder += state_table[last_state][current_state];
|
||||||
|
|
||||||
|
// Save current state for the next interrupt
|
||||||
|
last_state = current_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attached to PIN_ENC_A rising and falling edges
|
||||||
|
void EXTI7_0_IRQHandler(void) __attribute__((interrupt));
|
||||||
|
void EXTI7_0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
__disable_irq();
|
||||||
|
update_encoder();
|
||||||
|
EXTI->INTFR = EXTI_Line3;
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attached to PIN_ENC_B rising and falling edges
|
||||||
void EXTI15_8_IRQHandler(void) __attribute__((interrupt));
|
void EXTI15_8_IRQHandler(void) __attribute__((interrupt));
|
||||||
void EXTI15_8_IRQHandler(void)
|
void EXTI15_8_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t now = funSysTick32();
|
__disable_irq();
|
||||||
if (now - last_interrupt > ENCODER_DEBOUNCE) {
|
update_encoder();
|
||||||
last_interrupt = now;
|
|
||||||
if (funDigitalRead(PIN_ENC_A)) {
|
|
||||||
encoder++;
|
|
||||||
} else {
|
|
||||||
encoder--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXTI->INTFR = EXTI_Line11;
|
EXTI->INTFR = EXTI_Line11;
|
||||||
|
__enable_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,12 +398,21 @@ __attribute__((noreturn)) int main(void)
|
|||||||
|
|
||||||
// Configure the IO as an interrupt.
|
// Configure the IO as an interrupt.
|
||||||
// PIN_ENC_B is on port B, channel 11
|
// PIN_ENC_B is on port B, channel 11
|
||||||
AFIO->EXTICR1 = AFIO_EXTICR1_EXTI11_PB; // Port B channel (pin) 11
|
AFIO->EXTICR1 |= AFIO_EXTICR1_EXTI11_PB; // Port B channel (pin) 11
|
||||||
EXTI->INTENR = EXTI_INTENR_MR11; // Enable EXT11
|
EXTI->INTENR |= EXTI_INTENR_MR11; // Enable EXT11
|
||||||
EXTI->FTENR = EXTI_FTENR_TR11; // Falling edge trigger
|
EXTI->FTENR |= EXTI_FTENR_TR11; // Falling edge trigger
|
||||||
|
EXTI->RTENR |= EXTI_RTENR_TR11; // Rising edge trigger
|
||||||
// enable interrupt
|
// enable interrupt
|
||||||
NVIC_EnableIRQ(EXTI15_8_IRQn);
|
NVIC_EnableIRQ(EXTI15_8_IRQn);
|
||||||
|
|
||||||
|
// PIN_ENC_A is on port B, channel 3
|
||||||
|
AFIO->EXTICR1 |= AFIO_EXTICR1_EXTI3_PB; // Port B channel (pin) 3
|
||||||
|
EXTI->INTENR |= EXTI_INTENR_MR3; // Enable EXT3
|
||||||
|
EXTI->FTENR |= EXTI_FTENR_TR3; // Falling edge trigger
|
||||||
|
EXTI->RTENR |= EXTI_RTENR_TR3; // Rising edge trigger
|
||||||
|
// enable interrupt
|
||||||
|
NVIC_EnableIRQ(EXTI7_0_IRQn);
|
||||||
|
|
||||||
Delay_Ms(500);
|
Delay_Ms(500);
|
||||||
|
|
||||||
u8g2 = display_init();
|
u8g2 = display_init();
|
||||||
@ -388,7 +441,7 @@ __attribute__((noreturn)) int main(void)
|
|||||||
|
|
||||||
// TODO: let the user decide the power profile
|
// TODO: let the user decide the power profile
|
||||||
pd_profile.set_temp = 200;
|
pd_profile.set_temp = 200;
|
||||||
pd_profile.set_power = 95; // Slightly below max power to avoid overloading
|
pd_profile.set_power = 60; // Slightly below max power to avoid overloading
|
||||||
pd_profile.tip_r = 2500; // TODO: tip check and resistance calculator
|
pd_profile.tip_r = 2500; // TODO: tip check and resistance calculator
|
||||||
pd_profile.max_duty = MIN(
|
pd_profile.max_duty = MIN(
|
||||||
(100*(u32)isqrt((
|
(100*(u32)isqrt((
|
||||||
@ -416,6 +469,10 @@ __attribute__((noreturn)) int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STATE_MENU,
|
||||||
|
STATE_HEATING,
|
||||||
|
} state = STATE_MENU;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
u32 start = funSysTick32();
|
u32 start = funSysTick32();
|
||||||
poll_input(); // usb
|
poll_input(); // usb
|
||||||
@ -428,6 +485,9 @@ __attribute__((noreturn)) int main(void)
|
|||||||
static bool pwm = false; // PWM status
|
static bool pwm = false; // PWM status
|
||||||
static bool enabled = false; // Power electronics enabled
|
static bool enabled = false; // Power electronics enabled
|
||||||
static uint8_t count = 0; // Loop cycles with PWM on
|
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) {
|
if (has_pd) {
|
||||||
static uint16_t vbus_mv, current_ma;
|
static uint16_t vbus_mv, current_ma;
|
||||||
@ -446,6 +506,26 @@ __attribute__((noreturn)) int main(void)
|
|||||||
tip_temp_c = I16_FP_EMA_K2(tip_temp_c, (tip_mv*TC_CONV_NOM)/TC_CONV_DEN) + temp_c;
|
tip_temp_c = I16_FP_EMA_K2(tip_temp_c, (tip_mv*TC_CONV_NOM)/TC_CONV_DEN) + temp_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case STATE_MENU:
|
||||||
|
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));
|
||||||
|
|
||||||
|
if (encoder != 0) {
|
||||||
|
pd_profile.set_temp += encoder;
|
||||||
|
encoder = 0;
|
||||||
|
#define MIN_TEMP 100
|
||||||
|
#define MAX_TEMP 360
|
||||||
|
if (pd_profile.set_temp < MIN_TEMP) pd_profile.set_temp = MIN_TEMP;
|
||||||
|
if (pd_profile.set_temp > MAX_TEMP) pd_profile.set_temp = MAX_TEMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btn == 0 && prev_btn == 1) {
|
||||||
|
state = STATE_HEATING;
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_HEATING:
|
||||||
// Display tip temperature
|
// Display tip temperature
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TIP:");
|
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TIP:");
|
||||||
u8g2_DrawStr(u8g2, x_off+20, y_off+7, u8g2_u16toa(tip_temp_c, 4));
|
u8g2_DrawStr(u8g2, x_off+20, y_off+7, u8g2_u16toa(tip_temp_c, 4));
|
||||||
@ -497,9 +577,14 @@ __attribute__((noreturn)) int main(void)
|
|||||||
funDigitalWrite(PIN_12V, 0);
|
funDigitalWrite(PIN_12V, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move to menu mode when encoder is turned
|
||||||
|
if (encoder != 0) {
|
||||||
|
state = STATE_MENU;
|
||||||
|
funDigitalWrite(PIN_12V, 0);
|
||||||
|
pwm_set(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Check button to toggle enable
|
// Check button to toggle enable
|
||||||
static bool prev_btn = true;
|
|
||||||
bool btn = funDigitalRead(PIN_BTN);
|
|
||||||
if (btn == 0 && prev_btn == 1) {
|
if (btn == 0 && prev_btn == 1) {
|
||||||
enabled = !enabled;
|
enabled = !enabled;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
@ -508,8 +593,8 @@ __attribute__((noreturn)) int main(void)
|
|||||||
pwm_off();
|
pwm_off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev_btn = btn;
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No PD capability, just display a message
|
// No PD capability, just display a message
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "NO PD");
|
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "NO PD");
|
||||||
@ -517,7 +602,9 @@ __attribute__((noreturn)) int main(void)
|
|||||||
|
|
||||||
u8g2_SendBuffer(u8g2);
|
u8g2_SendBuffer(u8g2);
|
||||||
|
|
||||||
s32 elapsed = funSysTick32() - start;
|
prev_btn = btn;
|
||||||
|
|
||||||
|
elapsed = funSysTick32() - start;
|
||||||
if (elapsed > 0 && elapsed < Ticks_from_Ms(FRAME_TIME_MS)) {
|
if (elapsed > 0 && elapsed < Ticks_from_Ms(FRAME_TIME_MS)) {
|
||||||
DelaySysTick(Ticks_from_Ms(FRAME_TIME_MS) - elapsed);
|
DelaySysTick(Ticks_from_Ms(FRAME_TIME_MS) - elapsed);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user