Add pitch mode properly, add boot to bootloader, refactor rotary_event and friends
This commit is contained in:
168
src/main.c
168
src/main.c
@@ -7,6 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <bsp/board.h>
|
||||
#include <hardware/pio.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <tusb.h>
|
||||
#include "usb_config.h"
|
||||
@@ -16,19 +17,17 @@ PIO pio = pio0;
|
||||
static void hid_task(void);
|
||||
|
||||
// USB report structs
|
||||
__attribute__((packed)) struct light_data {
|
||||
uint8_t leds[16];
|
||||
};
|
||||
|
||||
__attribute__((packed)) struct button_report {
|
||||
uint32_t buttons;
|
||||
};
|
||||
|
||||
#define APP_MODE_MASK 0x0f
|
||||
#define APP_FLAG_MACH 0x10
|
||||
#define APP_FLAG_PITCH 0x20
|
||||
|
||||
#define APP_UPDATE 0
|
||||
#define APP_INIT 1
|
||||
#define APP_BOOTLOADER 2 // request to reboot to bootloader
|
||||
|
||||
__attribute__((packed)) struct app_report {
|
||||
uint8_t type;
|
||||
@@ -49,10 +48,9 @@ __attribute__((packed)) struct app_report {
|
||||
};
|
||||
};
|
||||
|
||||
static struct light_data the_light_data;
|
||||
|
||||
static bool show_vs = false, show_as = false;
|
||||
static bool show_vs = false, show_as = false, show_hdg = true, show_alt = true;
|
||||
static bool mach_mode = false;
|
||||
static bool pitch_mode = false;
|
||||
|
||||
static volatile unsigned hdg = 0;
|
||||
static volatile unsigned alt = 0;
|
||||
@@ -64,49 +62,66 @@ static int min_as = 0, max_as = 999, max_mach = 990;
|
||||
#define BUTTON_HDG_SYNC 1
|
||||
#define BUTTON_ALT_SYNC 7
|
||||
|
||||
static void render_uint(int start, int len, unsigned val, bool leading_zeros)
|
||||
{
|
||||
const int end = start + len - 1;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (val || i == 0 || leading_zeros)
|
||||
sevenseg_set_digit(end - i, val % 10);
|
||||
else
|
||||
sevenseg_set_digit(end - i, LED_BLANK);
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
static void render_blank(int start, int len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i) {
|
||||
sevenseg_set_digit(start + i, LED_BLANK);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_hdg_display(void)
|
||||
{
|
||||
sevenseg_set_digit(0, hdg / 100);
|
||||
sevenseg_set_digit(1, hdg / 10 % 10);
|
||||
sevenseg_set_digit(2, hdg % 10);
|
||||
if (show_hdg) {
|
||||
render_uint(0, 3, hdg, true);
|
||||
} else {
|
||||
render_blank(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_alt_display(void)
|
||||
{
|
||||
int val = alt;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (val || i == 0)
|
||||
sevenseg_set_digit(7 - i, val % 10);
|
||||
else
|
||||
sevenseg_set_digit(7 - i, LED_BLANK);
|
||||
val /= 10;
|
||||
if (show_alt) {
|
||||
render_uint(3, 5, alt, false);
|
||||
} else {
|
||||
render_blank(3, 5);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_vs_display(void)
|
||||
{
|
||||
if (show_vs) {
|
||||
if (pitch_mode) {
|
||||
int val = vs;
|
||||
unsigned val_abs = val < 0 ? -val : val;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (val_abs || i == 0) {
|
||||
sevenseg_set_digit(11 - i, val_abs % 10);
|
||||
} else {
|
||||
sevenseg_set_digit(11 - i, LED_BLANK);
|
||||
}
|
||||
val_abs /= 10;
|
||||
}
|
||||
if (val >= 1000 || val <= -1000) {
|
||||
sevenseg_set_digit(8, (val_abs % 10) | (val < 0 ? LED_DECIMAL : 0));
|
||||
} else if (val < 0) {
|
||||
unsigned int val_abs = val < 0 ? -val : val;
|
||||
if (val < 0) {
|
||||
sevenseg_set_digit(8, LED_MINUS);
|
||||
} else {
|
||||
sevenseg_set_digit(8, LED_BLANK);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
sevenseg_set_digit(11 - i, LED_BLANK);
|
||||
render_uint(9, 2, val_abs, false);
|
||||
sevenseg_set_digit(11, LED_DEGREE);
|
||||
} else if (show_vs) {
|
||||
int val = vs;
|
||||
unsigned val_abs = val < 0 ? -val : val;
|
||||
render_uint(8, 4, val_abs, false);
|
||||
if (val >= 1000 || val <= -1000) {
|
||||
sevenseg_mod_digit(8, val < 0 ? LED_DECIMAL : 0);
|
||||
} else if (val < 0) {
|
||||
sevenseg_set_digit(8, LED_MINUS);
|
||||
}
|
||||
} else {
|
||||
render_blank(8, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,74 +131,50 @@ static void update_as_display(void)
|
||||
int val = as;
|
||||
if (mach_mode) {
|
||||
sevenseg_set_digit(12, 0 | LED_DECIMAL);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
sevenseg_set_digit(15 - i, val % 10);
|
||||
val /= 10;
|
||||
}
|
||||
render_uint(13, 3, val, true);
|
||||
} else {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (val || i == 0)
|
||||
sevenseg_set_digit(15 - i, val % 10);
|
||||
else
|
||||
sevenseg_set_digit(15 - i, LED_BLANK);
|
||||
val /= 10;
|
||||
}
|
||||
render_uint(12, 4, val, false);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
sevenseg_set_digit(15 - i, LED_BLANK);
|
||||
}
|
||||
render_blank(12, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t clamp(int16_t cur, int16_t min, int16_t max)
|
||||
static int crement_val(bool inc, int val, int min, int max, int step, bool wrap)
|
||||
{
|
||||
return cur >= min ? (cur <= max ? cur : max) : min;
|
||||
// round to step in correct direction
|
||||
if (inc) {
|
||||
val = ((val - step + 1) / step) * step;
|
||||
} else {
|
||||
val = ((val + step - 1) / step) * step;
|
||||
}
|
||||
if (inc) {
|
||||
return val >= max - step + 1 ? (wrap ? min : max) : val + step;
|
||||
} else {
|
||||
return val <= min + step ? (wrap ? max : min) : val - step;
|
||||
}
|
||||
}
|
||||
|
||||
void rotary_event(int rot_ch, bool ccw)
|
||||
{
|
||||
/* if (ccw) */
|
||||
/* rotary_events = (rotary_events & ~(0x3<<(rot_ch*2))) | (0x1<<(rot_ch*2)); */
|
||||
/* else */
|
||||
/* rotary_events = (rotary_events & ~(0x3<<(rot_ch*2))) | (0x3<<(rot_ch*2)); */
|
||||
/* rotary_events |= 1<<(rot_ch*2 + ccw); */
|
||||
/* sevenseg_set_digit(0, rot_ch); */
|
||||
/* sevenseg_set_digit(1, ccw); */
|
||||
if (rot_ch == 3) {
|
||||
if (ccw) {
|
||||
hdg = hdg == 0 ? 359 : hdg - 1;
|
||||
} else {
|
||||
hdg = hdg == 359 ? 0 : hdg + 1;
|
||||
}
|
||||
hdg = crement_val(!ccw, hdg, 0, 359, 1, true);
|
||||
update_hdg_display();
|
||||
} else if (rot_ch == 2) {
|
||||
if (ccw) {
|
||||
alt = alt == 0 ? 0 : ((alt + 99) / 100) * 100 - 100;
|
||||
} else {
|
||||
alt = alt == 50000 ? 50000 : (alt / 100) * 100 + 100;
|
||||
}
|
||||
alt = crement_val(!ccw, alt, 0, 50000, 100, false);
|
||||
update_alt_display();
|
||||
} else if (rot_ch == 1) {
|
||||
if (ccw) {
|
||||
vs = vs == -5000 ? -5000 : ((vs < 0 ? vs : vs + 99) / 100) * 100 - 100;
|
||||
if (pitch_mode) {
|
||||
vs = crement_val(!ccw, vs, -20, 20, 1, false);
|
||||
} else {
|
||||
vs = vs == 5000 ? 5000 : ((vs > 0 ? vs : vs - 99) / 100) * 100 + 100;
|
||||
vs = crement_val(!ccw, vs, -5000, 5000, 100, false);
|
||||
}
|
||||
update_vs_display();
|
||||
} else {
|
||||
if (mach_mode) {
|
||||
if (ccw) {
|
||||
as = clamp(((as + 9) / 10) * 10 - 10, 0, max_mach);
|
||||
} else {
|
||||
as = clamp((as / 10) * 10 + 10, 0, max_mach);
|
||||
}
|
||||
as = crement_val(!ccw, as, 0, 990, 10, false);
|
||||
} else {
|
||||
if (ccw) {
|
||||
as = clamp(as - 1, min_as, max_as);
|
||||
} else {
|
||||
as = clamp(as + 1, min_as, max_as);
|
||||
}
|
||||
as = crement_val(!ccw, as, min_as, max_as, 1, false);
|
||||
}
|
||||
update_as_display();
|
||||
}
|
||||
@@ -205,6 +196,7 @@ int main()
|
||||
update_as_display();
|
||||
|
||||
irq_set_enabled(PIO0_IRQ_1, true);
|
||||
statusleds_set(0);
|
||||
|
||||
printf("Hello, world!\n");
|
||||
while (1) {
|
||||
@@ -266,15 +258,24 @@ static void hid_task(void)
|
||||
static void app_update_report(struct app_report const *report)
|
||||
{
|
||||
mach_mode = report->type & APP_FLAG_MACH;
|
||||
pitch_mode = report->type & APP_FLAG_PITCH;
|
||||
if (report->update.hdg >= 0) {
|
||||
hdg = report->update.hdg;
|
||||
update_hdg_display();
|
||||
send_heading_reports = true;
|
||||
show_hdg = true;
|
||||
} else if (report->update.hdg == -2) {
|
||||
show_hdg = false;
|
||||
}
|
||||
if (report->update.alt != 0xffff) {
|
||||
alt = report->update.alt;
|
||||
update_alt_display();
|
||||
send_alt_reports = true;
|
||||
if (report->update.alt == 0xfffe) {
|
||||
show_alt = false;
|
||||
} else {
|
||||
alt = report->update.alt;
|
||||
update_alt_display();
|
||||
send_alt_reports = true;
|
||||
show_alt = true;
|
||||
}
|
||||
}
|
||||
if (report->update.vs != -1) {
|
||||
if (report->update.vs == -2) {
|
||||
@@ -328,6 +329,9 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
||||
case APP_INIT:
|
||||
app_init_report(&report);
|
||||
break;
|
||||
case APP_BOOTLOADER:
|
||||
reset_usb_boot(0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,8 @@ static void txnfull_isr(void)
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t digit_row_map[NUM_DIGITS] = {
|
||||
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71, 0x00, 0x40,
|
||||
};
|
||||
static const uint8_t digit_row_map[NUM_DIGITS] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,
|
||||
0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71, 0x00, 0x40, 0x63 };
|
||||
|
||||
void sevenseg_set_digit(int index, enum sevenseg_digits digit)
|
||||
{
|
||||
@@ -50,6 +49,15 @@ void sevenseg_set_digit(int index, enum sevenseg_digits digit)
|
||||
}
|
||||
}
|
||||
|
||||
void sevenseg_mod_digit(int index, enum sevenseg_digits digit)
|
||||
{
|
||||
if (digit & LED_DECIMAL) {
|
||||
row_vals[7] |= (1 << index);
|
||||
} else {
|
||||
row_vals[7] &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
void sevenseg_init(void)
|
||||
{
|
||||
uint offset = pio_add_program(pio, &sevenseg_program);
|
||||
@@ -59,13 +67,15 @@ void sevenseg_init(void)
|
||||
sm_config_set_sideset_pins(&c, SEVENSEG_SCLK_PIN);
|
||||
sm_config_set_out_shift(&c, false, false, 24);
|
||||
sm_config_set_clkdiv(&c, 245.28f); // 20 kHz refresh cycle, 53 pio instrs/cycle
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN),
|
||||
(1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN));
|
||||
pio_sm_set_pindirs_with_mask(
|
||||
pio, sm,
|
||||
(1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN),
|
||||
(1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN));
|
||||
pio_gpio_init(pio, SEVENSEG_SDO_PIN);
|
||||
pio_gpio_init(pio, SEVENSEG_SCLK_PIN);
|
||||
pio_gpio_init(pio, SEVENSEG_FCLK_PIN);
|
||||
pio_gpio_init(pio, SEVENSEG_OE_PIN);
|
||||
pio_set_irq0_source_enabled(pio, PIO_INTR_SM0_TXNFULL_LSB+sm, true);
|
||||
pio_set_irq0_source_enabled(pio, PIO_INTR_SM0_TXNFULL_LSB + sm, true);
|
||||
irq_set_exclusive_handler(PIO0_IRQ_0, &txnfull_isr);
|
||||
irq_set_enabled(PIO0_IRQ_0, true);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
|
||||
@@ -19,10 +19,12 @@ enum sevenseg_digits {
|
||||
LED_F,
|
||||
LED_BLANK,
|
||||
LED_MINUS,
|
||||
LED_DEGREE,
|
||||
NUM_DIGITS,
|
||||
LED_DECIMAL = 0x100,
|
||||
};
|
||||
|
||||
void sevenseg_set_digit(int index, enum sevenseg_digits digit);
|
||||
void sevenseg_mod_digit(int index, enum sevenseg_digits digit);
|
||||
|
||||
void sevenseg_init(void);
|
||||
|
||||
Reference in New Issue
Block a user