From a148876e36bc3f84f11fdac57a9f69171e30c058 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Jan 2024 21:14:06 -0800 Subject: [PATCH 01/16] altos/telelco-v3: Minor UI tweaks MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit "Box"→"Bank" to match docs. Auto-center text instead of pre-computing. Way easier. Scroll found banks during startup. Signed-off-by: Keith Packard --- src/drivers/ao_lco_bits.c | 22 +++++++- src/telelco-v3.0/ao_lco_v3.c | 103 ++++++++++++++++++++++------------- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index 80140ec9..ebe3d0cb 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -381,6 +381,26 @@ ao_lco_set_firing(uint8_t firing) ao_wakeup(&ao_lco_armed); } +#if 0 +static int16_t fake_boxes[] = { + 1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97 +}; +#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) +#define NFAKE ARRAYSIZE(fake_boxes) + +static bool +is_fake(int16_t box) +{ + unsigned i; + for (i = 0; i < NFAKE; i++) + if (fake_boxes[i] == box) + return true; + return false; +} +#else +#define is_fake(b) false +#endif + void ao_lco_search(void) { @@ -407,7 +427,7 @@ ao_lco_search(void) ao_lco_tick_offset[box] = 0; r = ao_lco_query((uint16_t) box, &ao_pad_query, &ao_lco_tick_offset[box]); PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); - if (r == AO_RADIO_CMAC_OK) { + if (r == AO_RADIO_CMAC_OK || is_fake(box)) { ++boxes; ao_lco_box_set_present(box); #ifdef AO_LCO_SEARCH_API diff --git a/src/telelco-v3.0/ao_lco_v3.c b/src/telelco-v3.0/ao_lco_v3.c index 12363843..dc6b030e 100644 --- a/src/telelco-v3.0/ao_lco_v3.c +++ b/src/telelco-v3.0/ao_lco_v3.c @@ -56,19 +56,22 @@ static const struct ao_transform show_transform = { #define LOGO_FONT BenguiatGothicStd_Bold_26_font #define LABEL_Y (int16_t) (SMALL_FONT.ascent) -#define VALUE_Y (int16_t) (LABEL_Y + BIG_FONT.ascent + 5) -#define BOX_X 2 -#define PAD_X 90 -#define BOX_LABEL_X 26 +#define VALUE_Y (int16_t) (LABEL_Y + 5 + BIG_FONT.ascent) + +#define SEP_X 82 +#define SEP_WIDTH 2 + +#define BOX_X (SEP_X / 2) +#define PAD_X ((WIDTH + SEP_X + SEP_WIDTH) / 2) + #define VALUE_LABEL_X 64 #define RSSI_LABEL_X 15 -#define PAD_LABEL_X 95 -#define SEP_X (PAD_X - 8) + #define SCAN_X (WIDTH - 100) / 2 #define SCAN_Y 50 #define SCAN_HEIGHT 3 #define FOUND_Y 63 -#define FOUND_X 6 +#define FOUND_X 3 #define FOUND_WIDTH (WIDTH - 6) #define CONTRAST_LABEL_X 37 #define CONTRAST_WIDTH 100 @@ -95,19 +98,26 @@ static uint8_t ao_lco_select_mode; static uint8_t ao_lco_event_debug; #define PRINTE(...) do { if (!ao_lco_debug && !ao_lco_event_debug) break; printf ("\r%5lu %s: ", (unsigned long) ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) -#define AO_LCO_SELECT_PAD 0 -#define AO_LCO_SELECT_BOX 1 +#define AO_LCO_SELECT_BOX 0 +#define AO_LCO_SELECT_PAD 1 static uint8_t ao_lco_display_mutex; +static void +_ao_center_text(int16_t x, int16_t y, const struct ao_font *font, const char *str) +{ + int16_t width = ao_text_width(font, str); + ao_text(&fb, font, x - width/2, y, str, AO_BLACK, AO_COPY); +} + static void _ao_lco_show_pad(int8_t pad) { char str[5]; + _ao_center_text(PAD_X, LABEL_Y, &SMALL_FONT, "Pad"); snprintf(str, sizeof(str), "%d", pad); - ao_text(&fb, &BIG_FONT, PAD_X, VALUE_Y, str, AO_BLACK, AO_COPY); - ao_text(&fb, &SMALL_FONT, PAD_LABEL_X, LABEL_Y, "Pad", AO_BLACK, AO_COPY); + _ao_center_text(PAD_X, VALUE_Y, &BIG_FONT, str); } static void @@ -115,22 +125,20 @@ _ao_lco_show_box(int16_t box) { char str[7]; - snprintf(str, sizeof(str), "%2d", box); - ao_text(&fb, &BIG_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY); - ao_text(&fb, &SMALL_FONT, BOX_LABEL_X, LABEL_Y, "Box", AO_BLACK, AO_COPY); + _ao_center_text(BOX_X, LABEL_Y, &SMALL_FONT, "Bank"); + snprintf(str, sizeof(str), "%d", box); + _ao_center_text(BOX_X, VALUE_Y, &BIG_FONT, str); } static void _ao_lco_show_voltage(uint16_t decivolts, const char *label) { char str[7]; - int16_t width; PRINTD("voltage %d\n", decivolts); - snprintf(str, sizeof(str), "%2d.%d", decivolts / 10, decivolts % 10); - ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY); - width = ao_text_width(&SMALL_FONT, label); - ao_text(&fb, &SMALL_FONT, VALUE_LABEL_X - width/2, LABEL_Y, label, AO_BLACK, AO_COPY); + _ao_center_text(WIDTH/2, LABEL_Y, &SMALL_FONT, label); + snprintf(str, sizeof(str), "%d.%d", decivolts / 10, decivolts % 10); + _ao_center_text(WIDTH/2, VALUE_Y, &BIG_FONT, str); } static void @@ -151,14 +159,11 @@ _ao_lco_show_contrast(void) char buf[8]; uint8_t brightness = ao_st7565_get_brightness(); int16_t contrast = (int16_t) (brightness * CONTRAST_WIDTH / AO_LCO_MAX_CONTRAST); - int16_t width; - ao_text(&fb, &SMALL_FONT, CONTRAST_LABEL_X, LABEL_Y, "Contrast", AO_BLACK, AO_COPY); + _ao_center_text(WIDTH/2, LABEL_Y, &SMALL_FONT, "Contrast"); ao_rect(&fb, CONTRAST_X, CONTRAST_Y, contrast, CONTRAST_HEIGHT, AO_BLACK, AO_COPY); - /* this "knows" that CONTRAST_WIDTH == 100 */ - snprintf(buf, sizeof(buf), "%d %%", contrast); - width = ao_text_width(&SMALL_FONT, buf); - ao_text(&fb, &SMALL_FONT, BACKLIGHT_VALUE_X - width / 2, BACKLIGHT_VALUE_Y, buf, AO_BLACK, AO_COPY); + snprintf(buf, sizeof(buf), "%d %%", brightness * 100 / AO_LCO_MAX_CONTRAST); + _ao_center_text(WIDTH/2, CONTRAST_VALUE_Y, &SMALL_FONT, buf); } static void @@ -167,14 +172,11 @@ _ao_lco_show_backlight(void) char buf[8]; int32_t backlight = ao_lco_get_backlight(); int16_t value = (int16_t) (backlight * BACKLIGHT_WIDTH / AO_LCO_MAX_BACKLIGHT); - int16_t width; - ao_text(&fb, &SMALL_FONT, BACKLIGHT_LABEL_X, LABEL_Y, "Backlight", AO_BLACK, AO_COPY); + _ao_center_text(WIDTH/2, LABEL_Y, &SMALL_FONT, "Backlight"); ao_rect(&fb, BACKLIGHT_X, BACKLIGHT_Y, value, BACKLIGHT_HEIGHT, AO_BLACK, AO_COPY); - /* this "knows" that BACKLIGHT_WIDTH == 100 */ - snprintf(buf, sizeof(buf), "%d %%", value); - width = ao_text_width(&SMALL_FONT, buf); - ao_text(&fb, &SMALL_FONT, BACKLIGHT_VALUE_X - width / 2, BACKLIGHT_VALUE_Y, buf, AO_BLACK, AO_COPY); + snprintf(buf, sizeof(buf), "%ld %%", backlight * 100 / AO_LCO_MAX_BACKLIGHT); + _ao_center_text(WIDTH/2, BACKLIGHT_VALUE_Y, &SMALL_FONT, buf); } static int16_t info_y; @@ -210,7 +212,7 @@ _ao_lco_show_rssi(void) { char label[20]; int16_t width; - snprintf(label, sizeof(label), "Box %d RSSI", ao_lco_box); + snprintf(label, sizeof(label), "Bank %d RSSI", ao_lco_box); width = ao_text_width(&SMALL_FONT, label); ao_text(&fb, &SMALL_FONT, VALUE_LABEL_X - width / 2, LABEL_Y, label, AO_BLACK, AO_COPY); if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) @@ -225,7 +227,7 @@ static void _ao_lco_show_pad_battery(void) { char label[20]; - snprintf(label, sizeof(label), "Box %d Battery", ao_lco_box); + snprintf(label, sizeof(label), "Bank %d Battery", ao_lco_box); _ao_lco_show_voltage(ao_pad_query.battery, label); } @@ -258,7 +260,7 @@ ao_lco_show(void) default: _ao_lco_show_pad(ao_lco_pad); _ao_lco_show_box(ao_lco_box); - ao_rect(&fb, SEP_X, 0, 2, HEIGHT, AO_BLACK, AO_COPY); + ao_rect(&fb, SEP_X, 0, SEP_WIDTH, HEIGHT, AO_BLACK, AO_COPY); } break; } @@ -420,14 +422,18 @@ static struct ao_task ao_lco_monitor_task; static struct ao_task ao_lco_arm_warn_task; static struct ao_task ao_lco_igniter_status_task; -static int16_t found_x; +static int16_t found_width; +#define MAX_FOUND 32 +static int16_t found_boxes[MAX_FOUND]; +static uint8_t nfound; void ao_lco_search_start(void) { ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY); ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY); - found_x = FOUND_X; + found_width = 0; + nfound = 0; } void @@ -442,11 +448,30 @@ void ao_lco_search_box_present(int16_t box) { char str[8]; - if (found_x < FOUND_WIDTH) + int16_t width; + int16_t box_top = FOUND_Y - TINY_FONT.ascent; + int16_t x; + uint8_t n; + + snprintf(str, sizeof(str), "%s%u", nfound ? ", " : "", box); + width = ao_text_width(&TINY_FONT, str); + while (found_width + width > FOUND_WIDTH || nfound == MAX_FOUND) { - snprintf(str, sizeof(str), "%s%02u", found_x ? ", " : "", box); - found_x = ao_text(&fb, &TINY_FONT, found_x, FOUND_Y, str, AO_BLACK, AO_COPY); + snprintf(str, sizeof(str), "%u, ", found_boxes[0]); + found_width -= ao_text_width(&TINY_FONT, str); + memmove(&found_boxes[0], &found_boxes[1], (nfound - 1) * sizeof (int16_t)); + nfound--; + } + found_boxes[nfound++] = box; + + ao_rect(&fb, FOUND_X, FOUND_Y - TINY_FONT.ascent, FOUND_WIDTH, HEIGHT - box_top, AO_WHITE, AO_COPY); + x = FOUND_X; + for (n = 0; n < nfound; n++) { + snprintf(str, sizeof(str), "%s%u", n ? ", " : "", found_boxes[n]); + int16_t next_x = ao_text(&fb, &TINY_FONT, x, FOUND_Y, str, AO_BLACK, AO_COPY); + x = next_x; } + found_width = x - FOUND_X; } void -- 2.30.2 From a724a6b223229f8640740874523aee394350e9c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Jan 2024 17:58:02 -0800 Subject: [PATCH 02/16] altos/easytimer-v2: Fix up ao_pins.h Fix M25 CS pin (PA10). Fix BMI088 axes Fix MMC5983 axes. Signed-off-by: Keith Packard --- src/easytimer-v2/ao_pins.h | 45 ++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/easytimer-v2/ao_pins.h b/src/easytimer-v2/ao_pins.h index a9bdb34c..3acafb61 100644 --- a/src/easytimer-v2/ao_pins.h +++ b/src/easytimer-v2/ao_pins.h @@ -149,18 +149,35 @@ struct ao_adc { */ #define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT (&samd21_port_a) -#define AO_M25_SPI_CS_MASK (1 << 27) +#define AO_M25_SPI_CS_PORT (&samd21_port_b) +#define AO_M25_SPI_CS_MASK (1 << 10) #define AO_M25_SPI_BUS AO_SPI_0_PA04_PA05_PA06 /* - * On EasyTimer v2, bmi088 pin 1 (NE corner of chip) is placed towards the - * USB and antenna edges of the board. Relative to bmi088 specs, to - * get the above values, we need to flip the Y axis, assigning values - * as follows: * - * +along +X +roll +X - * +across -Y +pitch -Y + * Here are the required sensor signs: + * + * +along nose up + * +across switch screws down + * +through TH down + * + * With the board aligned to have positive accel for the relevant + * axis, looking down from above we have: + * + * +roll counter clockwise (nose up) + * +pitch counter clockwise (switch screws down) + * +yaw counter clockwise (TH down) + */ + + +/* + * On EasyTimer v2, bmi088 pin 1 (NE corner of chip) is placed away + * from the USB edge of the board. Relative to bmi088 specs, to get + * the above values, we need to flip the X and Y axes, assigning + * values as follows: + * + * +along -Y +roll -Y + * +across -X +pitch -X * +through +Z +yaw +Z */ @@ -172,12 +189,12 @@ struct ao_adc { #define AO_BMI088_GYR_CS_PIN 11 #define HAS_IMU 1 -#define ao_bmi088_along(m) ((m)->acc.x) -#define ao_bmi088_across(m) (-(m)->acc.y) +#define ao_bmi088_along(m) (-(m)->acc.y) +#define ao_bmi088_across(m) (-(m)->acc.x) #define ao_bmi088_through(m) ((m)->acc.z) -#define ao_bmi088_roll(m) ((m)->gyr.x) -#define ao_bmi088_pitch(m) (-(m)->gyr.y) +#define ao_bmi088_roll(m) (-(m)->gyr.y) +#define ao_bmi088_pitch(m) (-(m)->gyr.x) #define ao_bmi088_yaw(m) ((m)->gyr.z) #define ao_data_along(packet) ao_bmi088_along(&(packet)->bmi088) @@ -193,7 +210,7 @@ struct ao_adc { * * pin 1 NE corner of chip * - * +along -Y + * +along +Y * +across +X * +through -Z */ @@ -211,7 +228,7 @@ struct ao_adc { #define AO_MMC5983_SPI_CS_PORT (&samd21_port_a) #define AO_MMC5983_SPI_CS_PIN 8 -#define ao_mmc5983_along(m) (-(m)->y) +#define ao_mmc5983_along(m) ((m)->y) #define ao_mmc5983_across(m) ((m)->x) #define ao_mmc5983_through(m) (-(m)->z) -- 2.30.2 From 52d0c638343b2424cae08059f788a02efddee19a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Jan 2024 18:39:27 -0800 Subject: [PATCH 03/16] altoslib: Add EasyTimer-v2 support Log parsing and idle monitor. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 3 + altoslib/AltosEepromRecordSet.java | 3 + altoslib/AltosEepromRecordTimer.java | 171 +++++++++++++++++++++++++++ altoslib/AltosIMU.java | 7 +- altoslib/AltosIdleFetch.java | 8 ++ altoslib/AltosLib.java | 1 + altoslib/AltosMag.java | 2 + altoslib/AltosSensorEasyTimer2.java | 77 ++++++++++++ altoslib/Makefile.am | 2 + 9 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 altoslib/AltosEepromRecordTimer.java create mode 100644 altoslib/AltosSensorEasyTimer2.java diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index ce34db7f..17a81329 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -223,6 +223,9 @@ public class AltosConfigData { case AltosLib.AO_LOG_FORMAT_EASYMOTOR: /* ADXL375 */ return -value; + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + /* BMI088 */ + return -value; default: if (product.startsWith("EasyTimer-")) return -value; diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 2c2089d7..c42f78af 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -111,6 +111,9 @@ public class AltosEepromRecordSet implements AltosRecordSet { case AltosLib.AO_LOG_FORMAT_EASYMOTOR: record = new AltosEepromRecordMotor(eeprom); break; + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + record = new AltosEepromRecordTimer(eeprom); + break; } ordered = new TreeSet(); diff --git a/altoslib/AltosEepromRecordTimer.java b/altoslib/AltosEepromRecordTimer.java new file mode 100644 index 00000000..91dcb6a3 --- /dev/null +++ b/altoslib/AltosEepromRecordTimer.java @@ -0,0 +1,171 @@ +/* + * Copyright © 2024 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_14; + +public class AltosEepromRecordTimer extends AltosEepromRecord { + public static final int record_length = 32; + + private int log_format; + + private int imu_type() { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + return AltosIMU.imu_type_easytimer_v2; + default: + return AltosLib.MISSING; + } + } + + private int imu_model() { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + return AltosLib.model_bmi088; + } + return AltosLib.MISSING; + } + + private boolean sensor_normalized() { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + return true; + } + return false; + } + + private int mag_model() { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_EASYTIMER_2: + return AltosLib.model_mmc5983; + } + return AltosLib.MISSING; + } + + /* AO_LOG_FLIGHT elements */ + private int flight() { return data16(0); } + private int ground_accel() { return data16(2); } + private int ground_pres() { return AltosLib.MISSING; } + private int ground_accel_along() { return data16(4); } + private int ground_accel_across() { return data16(6); } + private int ground_accel_through() { return data16(8); } + private int ground_roll() { return data32(12); } + private int ground_pitch() { return data32(16); } + private int ground_yaw() { return data32(20); } + + /* AO_LOG_STATE elements */ + private int state() { return data16(0); } + private int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + + private int accel_along() { return data16(0); } + private int accel_across() { return data16(2); } + private int accel_through() { return data16(4); } + private int gyro_roll() { return data16(6); } + private int gyro_pitch() { return data16(8); } + private int gyro_yaw() { return data16(10); } + private int mag_along() { return data16(12); } + private int mag_across() { return data16(14); } + private int mag_through() { return data16(16); } + + private int accel() { return -accel_along(); } + + private int v_batt() { return data16(18); } + private int v_pbatt() { return data16(20); } + private int nsense() { return 2; } + private int sense(int i) { return data16(22 + i * 2); } + private int pyro() { return data16(26); } + + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + + cal_data.set_imu_type(imu_type()); + cal_data.set_imu_model(imu_model()); + cal_data.set_mag_model(mag_model()); + + switch (cmd()) { + case AltosLib.AO_LOG_FLIGHT: + cal_data.set_flight(flight()); + cal_data.set_ground_accel(ground_accel()); + listener.set_accel_ground(cal_data.accel_along(ground_accel_along()), + cal_data.accel_across(ground_accel_across()), + cal_data.accel_through(ground_accel_through())); + cal_data.set_gyro_zero(ground_roll() / 512.0, + ground_pitch() / 512.0, + ground_yaw() / 512.0); + break; + case AltosLib.AO_LOG_STATE: + listener.set_state(state()); + break; + case AltosLib.AO_LOG_SENSOR: + AltosConfigData config_data = eeprom.config_data(); + + int accel_along = accel_along(); + int accel_across = accel_across(); + int accel_through = accel_through(); + int gyro_roll = gyro_roll(); + int gyro_pitch = gyro_pitch(); + int gyro_yaw = gyro_yaw(); + + int mag_along = mag_along(); + int mag_across = mag_across(); + int mag_through = mag_through(); + + listener.set_accel(cal_data.accel_along(accel_along), + cal_data.accel_across(accel_across), + cal_data.accel_through(accel_through)); + listener.set_gyro(cal_data.gyro_roll(gyro_roll), + cal_data.gyro_pitch(gyro_pitch), + cal_data.gyro_yaw(gyro_yaw)); + + listener.set_mag(cal_data.mag_along(mag_along), + cal_data.mag_across(mag_across), + cal_data.mag_through(mag_through)); + + listener.set_acceleration(cal_data.acceleration(accel())); + + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); + + int nsense = nsense(); + + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); + + double voltages[] = new double[nsense-2]; + for (int i = 0; i < nsense-2; i++) + voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); + + listener.set_igniter_voltage(voltages); + listener.set_pyro_fired(pyro()); + break; + } + } + + public AltosEepromRecord next() { + int s = next_start(); + if (s < 0) + return null; + return new AltosEepromRecordTimer(eeprom, s); + } + + public AltosEepromRecordTimer(AltosEeprom eeprom, int start) { + super(eeprom, start, record_length); + log_format = eeprom.config_data().log_format; + } + + public AltosEepromRecordTimer(AltosEeprom eeprom) { + this(eeprom, 0); + } +} diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index b4ba5a56..436d54cc 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -73,11 +73,13 @@ public class AltosIMU implements Cloneable { case imu_type_easymega_v1: case imu_type_easymega_v2: return counts_per_g_mpu; - case imu_type_telemega_v4: + case imu_type_telemega_v4: case imu_type_easytimer_v1: return counts_per_g_bmx; case imu_type_easymotor_v2: return counts_per_g_adxl; + case imu_type_easytimer_v2: + return counts_per_g_bmi088; } return AltosLib.MISSING; @@ -251,6 +253,8 @@ public class AltosIMU implements Cloneable { public static final int imu_type_easymotor_v2 = 6; /* ADXL375 (accel only) */ + public static final int imu_type_easytimer_v2 = 7; /* BMI088 */ + private int accel_across(int imu_type) { if (accel_across != AltosLib.MISSING) @@ -391,6 +395,7 @@ public class AltosIMU implements Cloneable { private static boolean is_primary_accel(int imu_type) { switch (imu_type) { case imu_type_easytimer_v1: + case imu_type_easytimer_v2: return true; default: return false; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 90f4f53e..2b92d729 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -40,6 +40,7 @@ class AltosIdler { static final int idle_adxl375 = 10; static final int idle_adxl375_easymotor_v2 = 11; static final int idle_imu = 12; + static final int idle_imu_et_v2 = 13; static final int idle_sensor_tm = 100; static final int idle_sensor_metrum = 101; @@ -54,6 +55,7 @@ class AltosIdler { static final int idle_sensor_easytimer1 = 110; static final int idle_sensor_easymotor2 = 111; static final int idle_sensor_emini3 = 112; + static final int idle_sensor_etimer2 = 113; public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct { for (int idler : idlers) { @@ -79,6 +81,9 @@ class AltosIdler { case idle_imu_et_v1: AltosIMU.provide_data(listener, link, AltosIMU.imu_type_easytimer_v1); break; + case idle_imu_et_v2: + AltosIMU.provide_data(listener, link, AltosIMU.imu_type_easytimer_v2); + break; case idle_imu: AltosIMU.provide_data(listener, link, AltosLib.MISSING); break; @@ -267,6 +272,9 @@ public class AltosIdleFetch implements AltosDataProvider { new AltosIdler("EasyMotor-v2", AltosIdler.idle_adxl375_easymotor_v2, AltosIdler.idle_sensor_easymotor2), + new AltosIdler("EasyTimer-v2", + AltosIdler.idle_imu_et_v2, + AltosIdler.idle_sensor_easymotor2), }; AltosLink link; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 5293badc..7cd0e15c 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -387,6 +387,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_EASYMOTOR = 20; public static final int AO_LOG_FORMAT_TELEMEGA_5 = 21; public static final int AO_LOG_FORMAT_TELEMEGA_6 = 22; + public static final int AO_LOG_FORMAT_EASYTIMER_2 = 23; public static final int AO_LOG_FORMAT_NONE = 127; public static final int model_mpu6000 = 0; diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index c7f1ac1d..6e11f3fd 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -45,6 +45,8 @@ public class AltosMag implements Cloneable { case AltosIMU.imu_type_telemega_v1_v2: case AltosIMU.imu_type_easymega_v1: return counts_per_gauss_hmc5883; + case AltosIMU.imu_type_easytimer_v2: + return counts_per_gauss_mmc5983; } return AltosIMU.counts_per_gauss(imu_type, mag_model); diff --git a/altoslib/AltosSensorEasyTimer2.java b/altoslib/AltosSensorEasyTimer2.java new file mode 100644 index 00000000..4d8102cc --- /dev/null +++ b/altoslib/AltosSensorEasyTimer2.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_14; + +import java.util.concurrent.TimeoutException; + +class AltosSensorEasyTimer2 { + int tick; + int[] sense; + int v_batt; + int v_pbatt; + int temp; + + public AltosSensorEasyTimer2() { + sense = new int[2]; + } + + public AltosSensorEasyTimer2(AltosLink link) throws InterruptedException, TimeoutException { + this(); + String[] items = link.adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("A:")) { + sense[0] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("B:")) { + sense[1] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + v_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + } + + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { + try { + AltosSensorEasyTimer2 sensor_easytimer2 = new AltosSensorEasyTimer2(link); + + listener.set_battery_voltage(AltosConvert.easy_timer_voltage(sensor_easytimer2.v_batt)); + + double[] igniter_voltage = new double[2]; + for (int i = 0; i < 2; i++) + igniter_voltage[i] = AltosConvert.easy_timer_voltage(sensor_easytimer2.sense[i]); + listener.set_igniter_voltage(igniter_voltage); + + } catch (TimeoutException te) { + } + } +} + diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index a030e2cb..7cb2ef6f 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -51,6 +51,7 @@ altoslib_JAVA = \ AltosEepromRecordMicroPeak2.java \ AltosEepromRecordMotor.java \ AltosEepromRecordSet.java \ + AltosEepromRecordTimer.java \ AltosEepromChunk.java \ AltosEepromDownload.java \ AltosEepromMonitor.java \ @@ -108,6 +109,7 @@ altoslib_JAVA = \ AltosSensorMM.java \ AltosSensorEMini.java \ AltosSensorEasyTimer1.java \ + AltosSensorEasyTimer2.java \ AltosSensorTM.java \ AltosSensorTMini2.java \ AltosSensorTMini3.java \ -- 2.30.2 From 9419cf4f22e5cd337da54d7907fc0a5e848bd464 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Jan 2024 18:40:06 -0800 Subject: [PATCH 04/16] altos/easytimer-v2: Set default log size to 192kB This leaves space for 4 flights. Signed-off-by: Keith Packard --- src/easytimer-v2/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easytimer-v2/ao_pins.h b/src/easytimer-v2/ao_pins.h index 3acafb61..4e935613 100644 --- a/src/easytimer-v2/ao_pins.h +++ b/src/easytimer-v2/ao_pins.h @@ -250,7 +250,7 @@ struct ao_adc { * Logging */ -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024) +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (192 * 1024) #define AO_CONFIG_MAX_SIZE 1024 #define LOG_ERASE_MARK 0x55 #define LOG_MAX_ERASE 128 -- 2.30.2 From 13befe46b107a88d05710991beab3b7b8478fa09 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Jan 2024 18:40:30 -0800 Subject: [PATCH 05/16] altos/easytimer-v2: Fix product name Signed-off-by: Keith Packard --- src/easytimer-v2/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easytimer-v2/Makefile b/src/easytimer-v2/Makefile index 66c31e0b..2298ab48 100644 --- a/src/easytimer-v2/Makefile +++ b/src/easytimer-v2/Makefile @@ -62,7 +62,7 @@ ALTOS_SRC = \ $(SAMPLE_PROFILE) \ $(STACK_GUARD) -PRODUCT=EasyTimer-2 +PRODUCT=EasyTimer-v2 PRODUCT_DEF=-DEASYTIMER_V_2 IDPRODUCT=0x000d -- 2.30.2 From bcf9db74705dcd77eccd8f36f73c2eb99a5f1c70 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 31 Jan 2024 22:05:13 -0800 Subject: [PATCH 06/16] altosui: Make accel cal dialog say 'beeper' instead of 'antenna' Quite the plumbing required, but it'll do. Signed-off-by: Keith Packard --- altoslib/AltosConfigValues.java | 2 ++ altosui/AltosConfigFCUI.java | 2 +- altosuilib/AltosUIAccelCal.java | 12 ++++++++---- telegps/TeleGPSConfigUI.java | 2 ++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index 8fb30277..6823e0f9 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -124,6 +124,8 @@ public interface AltosConfigValues { public abstract void set_radio_10mw(int radio_10mw); + public abstract boolean has_radio(); + public abstract int report_feet() throws AltosConfigDataException; public abstract void set_report_feet(int radio_10mw); diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index 88f8b080..bc082a4e 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -240,7 +240,7 @@ public class AltosConfigFCUI return product != null && product.startsWith("EasyTimer"); } - boolean has_radio() { + public boolean has_radio() { return is_telemega() || is_telemetrum() || is_telemini(); } diff --git a/altosuilib/AltosUIAccelCal.java b/altosuilib/AltosUIAccelCal.java index 94d80193..ae8d6246 100644 --- a/altosuilib/AltosUIAccelCal.java +++ b/altosuilib/AltosUIAccelCal.java @@ -81,14 +81,14 @@ public class AltosUIAccelCal public void run() { switch (phase) { case AltosAccelCal.phase_antenna_up: - message.setText("Orient antenna upwards and click on Antenna Up"); + message.setText(String.format ("Orient antenna upwards and click on %s", up_msg())); antenna_up.setEnabled(true); setDefaultButton(antenna_up); antenna_down.setEnabled(false); ok.setEnabled(false); break; case AltosAccelCal.phase_antenna_down: - message.setText("Orient antenna downwards and click on Antenna Down"); + message.setText(String.format("Orient antenna downwards and click on %s", down_msg())); antenna_up.setEnabled(false); antenna_down.setEnabled(true); setDefaultButton(antenna_down); @@ -157,6 +157,10 @@ public class AltosUIAccelCal } } } + + public String up_msg() { return config_values.has_radio() ? "Antenna Up" : "Beeper Up"; } + public String down_msg() { return config_values.has_radio() ? "Antenna Down" : "Beeper Down"; } + public AltosUIAccelCal(Frame owner, AltosLink link, AltosConfigValues config_values) { super(owner, "Calibrate Accelerometer", true); @@ -193,7 +197,7 @@ public class AltosUIAccelCal c.gridheight = 1; c.weightx = 0; c.weighty = 0; - antenna_up = new JButton("Antenna Up"); + antenna_up = new JButton(up_msg()); antenna_up.setActionCommand("up"); antenna_up.setEnabled(false); antenna_up.addActionListener(this); @@ -208,7 +212,7 @@ public class AltosUIAccelCal c.gridheight = 1; c.weightx = 0; c.weighty = 0; - antenna_down = new JButton("Antenna Down"); + antenna_down = new JButton(down_msg()); antenna_down.setActionCommand("down"); antenna_down.setEnabled(false); antenna_down.addActionListener(this); diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index b5d267b7..b348f702 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -248,6 +248,8 @@ public class TeleGPSConfigUI flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory"); } + public boolean has_radio() { return true; } + /* Build the UI using a grid bag */ public TeleGPSConfigUI(JFrame in_owner) { super (in_owner, "Configure Device", false); -- 2.30.2 From 94445131d0be72f099985709dda4203259b1d947 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Feb 2024 16:31:03 -0800 Subject: [PATCH 07/16] stm32f1: Clean up some ADC definitions The CR2 bit is called TSVREFE in the docs, use that consistently Signed-off-by: Keith Packard --- src/stm32f1/ao_adc_single_stm.c | 2 +- src/stm32f1/ao_adc_stm.c | 54 ++++++++++++++++----------------- src/stm32f1/stm32f1.h | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/stm32f1/ao_adc_single_stm.c b/src/stm32f1/ao_adc_single_stm.c index 01a3fa6a..feaba42d 100644 --- a/src/stm32f1/ao_adc_single_stm.c +++ b/src/stm32f1/ao_adc_single_stm.c @@ -22,7 +22,7 @@ static uint8_t ao_adc_ready; -#define AO_ADC_CR2_VAL(start) ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREF) | \ +#define AO_ADC_CR2_VAL(start) ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREFE) |\ ((start) << STM_ADC_CR2_SWSTART) | \ (0 << STM_ADC_CR2_JWSTART) | \ (0 << STM_ADC_CR2_EXTTRIG) | \ diff --git a/src/stm32f1/ao_adc_stm.c b/src/stm32f1/ao_adc_stm.c index d7fac0d7..9523bd65 100644 --- a/src/stm32f1/ao_adc_stm.c +++ b/src/stm32f1/ao_adc_stm.c @@ -21,7 +21,7 @@ static uint8_t ao_adc_ready; -#define AO_ADC_CR2_VAL ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREF) | \ +#define AO_ADC_CR2_VAL ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREFE) |\ (0 << STM_ADC_CR2_SWSTART) | \ (0 << STM_ADC_CR2_JWSTART) | \ (0 << STM_ADC_CR2_EXTTRIG) | \ @@ -56,9 +56,9 @@ ao_adc_poll(void) if (!ao_adc_ready) return; ao_adc_ready = 0; - stm_adc.sr = 0; + stm_adc1.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), - &stm_adc.dr, + &stm_adc1.dr, (void *) (&ao_data_ring[ao_data_head].adc), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | @@ -72,7 +72,7 @@ ao_adc_poll(void) ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done); ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); - stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); + stm_adc1.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); } #ifdef AO_ADC_SQ1_NAME @@ -264,9 +264,9 @@ ao_adc_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); /* Turn off ADC during configuration */ - stm_adc.cr2 = 0; + stm_adc1.cr2 = 0; - stm_adc.cr1 = ((0 << STM_ADC_CR1_AWDEN ) | + stm_adc1.cr1 = ((0 << STM_ADC_CR1_AWDEN ) | (0 << STM_ADC_CR1_JAWDEN ) | (STM_ADC_CR1_DUALMOD_INDEPENDENT << STM_ADC_CR1_DUALMOD ) | (0 << STM_ADC_CR1_DISCNUM ) | @@ -281,57 +281,57 @@ ao_adc_init(void) (0 << STM_ADC_CR1_AWDCH )); /* 384 cycle sample time for everyone */ - stm_adc.smpr1 = 0x3ffff; - stm_adc.smpr2 = 0x3fffffff; + stm_adc1.smpr1 = 0x3ffff; + stm_adc1.smpr2 = 0x3fffffff; - stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); + stm_adc1.sqr1 = ((AO_NUM_ADC - 1) << 20); #if AO_NUM_ADC > 0 - stm_adc.sqr3 |= (AO_ADC_SQ1 << 0); + stm_adc1.sqr3 |= (AO_ADC_SQ1 << 0); #endif #if AO_NUM_ADC > 1 - stm_adc.sqr3 |= (AO_ADC_SQ2 << 5); + stm_adc1.sqr3 |= (AO_ADC_SQ2 << 5); #endif #if AO_NUM_ADC > 2 - stm_adc.sqr3 |= (AO_ADC_SQ3 << 10); + stm_adc1.sqr3 |= (AO_ADC_SQ3 << 10); #endif #if AO_NUM_ADC > 3 - stm_adc.sqr3 |= (AO_ADC_SQ4 << 15); + stm_adc1.sqr3 |= (AO_ADC_SQ4 << 15); #endif #if AO_NUM_ADC > 4 - stm_adc.sqr3 |= (AO_ADC_SQ5 << 20); + stm_adc1.sqr3 |= (AO_ADC_SQ5 << 20); #endif #if AO_NUM_ADC > 5 - stm_adc.sqr3 |= (AO_ADC_SQ6 << 25); + stm_adc1.sqr3 |= (AO_ADC_SQ6 << 25); #endif #if AO_NUM_ADC > 6 - stm_adc.sqr2 |= (AO_ADC_SQ7 << 0); + stm_adc1.sqr2 |= (AO_ADC_SQ7 << 0); #endif #if AO_NUM_ADC > 7 - stm_adc.sqr2 |= (AO_ADC_SQ8 << 5); + stm_adc1.sqr2 |= (AO_ADC_SQ8 << 5); #endif #if AO_NUM_ADC > 8 - stm_adc.sqr2 |= (AO_ADC_SQ9 << 10); + stm_adc1.sqr2 |= (AO_ADC_SQ9 << 10); #endif #if AO_NUM_ADC > 9 - stm_adc.sqr2 |= (AO_ADC_SQ10 << 15); + stm_adc1.sqr2 |= (AO_ADC_SQ10 << 15); #endif #if AO_NUM_ADC > 10 - stm_adc.sqr2 |= (AO_ADC_SQ11 << 20); + stm_adc1.sqr2 |= (AO_ADC_SQ11 << 20); #endif #if AO_NUM_ADC > 11 - stm_adc.sqr2 |= (AO_ADC_SQ12 << 25); + stm_adc1.sqr2 |= (AO_ADC_SQ12 << 25); #endif #if AO_NUM_ADC > 12 - stm_adc.sqr1 |= (AO_ADC_SQ13 << 0); + stm_adc1.sqr1 |= (AO_ADC_SQ13 << 0); #endif #if AO_NUM_ADC > 13 - stm_adc.sqr1 |= (AO_ADC_SQ14 << 5); + stm_adc1.sqr1 |= (AO_ADC_SQ14 << 5); #endif #if AO_NUM_ADC > 14 - stm_adc.sqr1 |= (AO_ADC_SQ15 << 10); + stm_adc1.sqr1 |= (AO_ADC_SQ15 << 10); #endif #if AO_NUM_ADC > 15 - stm_adc.sqr1 |= (AO_ADC_SQ16 << 15); + stm_adc1.sqr1 |= (AO_ADC_SQ16 << 15); #endif #if AO_NUM_ADC > 15 #error "too many ADC channels" @@ -341,11 +341,11 @@ ao_adc_init(void) #error Please define HAS_ADC_TEMP #endif #if HAS_ADC_TEMP - stm_adc.cr2 |= ((1 << STM_ADC_CR2_TSVREFE)); + stm_adc1.cr2 |= ((1 << STM_ADC_CR2_TSVREFE)); #endif /* Clear any stale status bits */ - stm_adc.sr = 0; + stm_adc1.sr = 0; ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); diff --git a/src/stm32f1/stm32f1.h b/src/stm32f1/stm32f1.h index b77a0aef..664e7652 100644 --- a/src/stm32f1/stm32f1.h +++ b/src/stm32f1/stm32f1.h @@ -1132,7 +1132,7 @@ extern struct stm_adc stm_adc1; #define STM_ADC_CR1_AWDCH 0 #define STM_ADC_CR1_AWDCH_MASK 0x1fUL -#define STM_ADC_CR2_TSVREF 23 +#define STM_ADC_CR2_TSVREFE 23 #define STM_ADC_CR2_SWSTART 22 #define STM_ADC_CR2_JWSTART 21 #define STM_ADC_CR2_EXTTRIG 20 -- 2.30.2 From 4da8e047c4df06a0fec2c0cd47d26d5f1bef0e31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 12 Feb 2024 22:58:45 -0800 Subject: [PATCH 08/16] src/easymini-2.0: Add combined .dfu file for Seeed testing Provide a combined .dfu for testing EasyMini at Seeed. This checks the baro sensor (via POST) and SoC. Signed-off-by: Keith Packard --- src/easymini-v2.0/Makefile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/easymini-v2.0/Makefile b/src/easymini-v2.0/Makefile index a47fc9bd..a045e126 100644 --- a/src/easymini-v2.0/Makefile +++ b/src/easymini-v2.0/Makefile @@ -58,15 +58,25 @@ CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) PROGNAME=easymini-v2.0 PROG=$(PROGNAME)-$(VERSION).elf HEX=$(PROGNAME)-$(VERSION).ihx +FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf +BOTH_DFU=$(PROGNAME)-combined-$(VERSION).dfu + +MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin SRC=$(ALTOS_SRC) ao_easymini.c OBJ=$(SRC:.c=.o) -all: $(PROG) $(HEX) +all: $(PROG) $(HEX) $(BOTH_DFU) $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) +$(BOTH_DFU): $(PROG) $(FLASH_PROG) + $(MAKEBIN) --dfu --output=$@ --base=$(FLASH_ADDR) $(FLASH_PROG) $(PROG) + +$(FLASH_PROG): FRC + +cd flash-loader && make + $(OBJ): $(INC) distclean: clean @@ -78,3 +88,5 @@ clean: install: uninstall: + +FRC: -- 2.30.2 From 6a9721f344d1837c913fee142c875de4d7357820 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Feb 2024 12:44:00 -0800 Subject: [PATCH 09/16] altoslib: Add EasyMega v3.0 support Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 1 + altoslib/AltosEepromRecordSet.java | 1 + altoslib/AltosIMU.java | 5 ++++- altoslib/AltosIdleFetch.java | 8 ++++++++ altoslib/AltosLib.java | 3 +++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 17a81329..005ef571 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -220,6 +220,7 @@ public class AltosConfigData { case AltosLib.AO_LOG_FORMAT_TELEMEGA_5: case AltosLib.AO_LOG_FORMAT_TELEMEGA_6: case AltosLib.AO_LOG_FORMAT_EASYMEGA_2: + case AltosLib.AO_LOG_FORMAT_EASYMEGA_3: case AltosLib.AO_LOG_FORMAT_EASYMOTOR: /* ADXL375 */ return -value; diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index c42f78af..8f3fa459 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -88,6 +88,7 @@ public class AltosEepromRecordSet implements AltosRecordSet { case AltosLib.AO_LOG_FORMAT_TELEMEGA_4: case AltosLib.AO_LOG_FORMAT_TELEMEGA_5: case AltosLib.AO_LOG_FORMAT_TELEMEGA_6: + case AltosLib.AO_LOG_FORMAT_EASYMEGA_3: record = new AltosEepromRecordMega(eeprom); break; case AltosLib.AO_LOG_FORMAT_TELEMETRUM: diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index 436d54cc..01ecc161 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -278,8 +278,10 @@ public class AltosIMU implements Cloneable { } private int accel_along(int imu_type) { - if (accel_along != AltosLib.MISSING) + if (accel_along != AltosLib.MISSING) { + System.out.printf("accel along %d\n", accel_along); return accel_along; + } switch (imu_type) { case imu_type_telemega_v1_v2: @@ -407,6 +409,7 @@ public class AltosIMU implements Cloneable { AltosIMU imu = new AltosIMU(link); AltosCalData cal_data = listener.cal_data(); + System.out.printf("imu_model %d mag_model %d\n", imu.imu_model, imu.mag_model); if (imu_type != AltosLib.MISSING) cal_data.set_imu_type(imu_type); if (imu != null) { diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 2b92d729..b64ba0a4 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -41,6 +41,7 @@ class AltosIdler { static final int idle_adxl375_easymotor_v2 = 11; static final int idle_imu = 12; static final int idle_imu_et_v2 = 13; + static final int idle_imu_em_v3 = 14; static final int idle_sensor_tm = 100; static final int idle_sensor_metrum = 101; @@ -56,6 +57,7 @@ class AltosIdler { static final int idle_sensor_easymotor2 = 111; static final int idle_sensor_emini3 = 112; static final int idle_sensor_etimer2 = 113; + static final int idle_sensor_emega3 = 114; public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct { for (int idler : idlers) { @@ -257,6 +259,12 @@ public class AltosIdleFetch implements AltosDataProvider { AltosIdler.idle_ms5607, AltosIdler.idle_imu_em_v2, AltosIdler.idle_sensor_mega), + new AltosIdler("EasyMega-v3", + AltosIdler.idle_adxl375, + AltosIdler.idle_ms5607, + AltosIdler.idle_imu, + AltosIdler.idle_mag, + AltosIdler.idle_sensor_mega), new AltosIdler("TeleGPS-v1", AltosIdler.idle_gps, AltosIdler.idle_sensor_tgps1), diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 7cd0e15c..82b5881a 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -388,6 +388,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TELEMEGA_5 = 21; public static final int AO_LOG_FORMAT_TELEMEGA_6 = 22; public static final int AO_LOG_FORMAT_EASYTIMER_2 = 23; + public static final int AO_LOG_FORMAT_EASYMEGA_3 = 24; public static final int AO_LOG_FORMAT_NONE = 127; public static final int model_mpu6000 = 0; @@ -615,6 +616,7 @@ public class AltosLib { case product_telegps: return "TeleGPS"; case product_easymini: return "EasyMini"; case product_telemini: return "TeleMini"; + case product_easymega: return "EasyMega"; case product_easymotor: return "EasyMotor"; default: return "unknown"; } @@ -655,6 +657,7 @@ public class AltosLib { case AO_LOG_FORMAT_TELEMEGA_3: return product_telemega; case AO_LOG_FORMAT_EASYMEGA_2: + case AO_LOG_FORMAT_EASYMEGA_3: return product_easymega; case AO_LOG_FORMAT_TELESTATIC: return product_altusmetrum; -- 2.30.2 From 22b5d1a98a86ac4d2d0ef12565a01e3591f9afb9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Feb 2024 12:45:09 -0800 Subject: [PATCH 10/16] altos/stm32f103: Fix continuous ADC code This needs the same hacks as the manual ADC code. Signed-off-by: Keith Packard --- src/stm32f1/ao_adc_stm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/stm32f1/ao_adc_stm.c b/src/stm32f1/ao_adc_stm.c index 9523bd65..36021443 100644 --- a/src/stm32f1/ao_adc_stm.c +++ b/src/stm32f1/ao_adc_stm.c @@ -21,12 +21,12 @@ static uint8_t ao_adc_ready; -#define AO_ADC_CR2_VAL ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREFE) |\ - (0 << STM_ADC_CR2_SWSTART) | \ +#define AO_ADC_CR2_VAL(start) ((HAS_ADC_TEMP << STM_ADC_CR2_TSVREFE) |\ + ((start) << STM_ADC_CR2_SWSTART) | \ (0 << STM_ADC_CR2_JWSTART) | \ (0 << STM_ADC_CR2_EXTTRIG) | \ - (0 << STM_ADC_CR2_EXTSEL) | \ - (0 << STM_ADC_CR2_JEXTTRIG) | \ + (STM_ADC_CR2_EXTSEL_SWSTART << STM_ADC_CR2_EXTSEL) | \ + (0 << STM_ADC_CR2_JEXTTRIG) | \ (0 << STM_ADC_CR2_JEXTSEL) | \ (0 << STM_ADC_CR2_ALIGN) | \ (1 << STM_ADC_CR2_DMA) | \ @@ -72,7 +72,9 @@ ao_adc_poll(void) ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done); ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); - stm_adc1.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); + stm_adc1.cr2 = AO_ADC_CR2_VAL(0); + stm_adc1.cr2 = AO_ADC_CR2_VAL(0); + stm_adc1.cr2 = AO_ADC_CR2_VAL(1); } #ifdef AO_ADC_SQ1_NAME -- 2.30.2 From bb3bfea5462d3f3e1a0a5f4645f67996054a78a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Feb 2024 12:45:54 -0800 Subject: [PATCH 11/16] altos: Build EasyMega v3.0 by defaul Signed-off-by: Keith Packard --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index 180d62d2..c89ac0e0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -57,6 +57,7 @@ ARMM0DIRS=\ easymini-v2.0 easymini-v2.0/flash-loader \ easymini-v3.0 easymini-v3.0/flash-loader \ telelco-v3.0 telelco-v3.0/flash-loader \ + easymega-v3.0 easymega-v3.0/flash-loader \ micropeak-v2.0 AVRDIRS=\ -- 2.30.2 From d9140ea0d6bf6755a2701115273f02a4c3944e17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Feb 2024 12:46:17 -0800 Subject: [PATCH 12/16] altos/easymega-v3.0: Update i2c pin usage Found an errata which means we had to swap which i2c to use with the mag sensor. Swap the mag sensor and fire_c/fire_d. Signed-off-by: Keith Packard --- src/easymega-v3.0/ao_pins.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/easymega-v3.0/ao_pins.h b/src/easymega-v3.0/ao_pins.h index 1aea7b21..8f0706eb 100644 --- a/src/easymega-v3.0/ao_pins.h +++ b/src/easymega-v3.0/ao_pins.h @@ -85,11 +85,11 @@ #define SPI_2_PB13_PB14_PB15 1 /* Flash, IMU, Companion */ #define SPI_2_MODE_OUTPUT STM_GPIO_CR_MODE_OUTPUT_50MHZ -#define HAS_I2C_1 1 -#define I2C_1_PB8_PB9 1 +#define HAS_I2C_1 0 +#define I2C_1_PB8_PB9 0 -#define HAS_I2C_2 0 -#define I2C_2_PB10_PB11 0 +#define HAS_I2C_2 1 +#define I2C_2_PB10_PB11 1 #define PACKET_HAS_SLAVE 0 #define PACKET_HAS_MASTER 0 @@ -134,11 +134,11 @@ /* Pyro C */ #define AO_PYRO_PORT_2 (&stm_gpiob) -#define AO_PYRO_PIN_2 11 +#define AO_PYRO_PIN_2 9 /* Pyro D */ #define AO_PYRO_PORT_3 (&stm_gpiob) -#define AO_PYRO_PIN_3 10 +#define AO_PYRO_PIN_3 8 /* Drogue */ #define AO_IGNITER_DROGUE_PORT (&stm_gpioa) @@ -321,7 +321,7 @@ struct ao_adc { #define HAS_MMC5983 1 #define MMC5983_I2C 1 -#define AO_MMC5983_I2C_INDEX STM_I2C_INDEX(1) +#define AO_MMC5983_I2C_INDEX STM_I2C_INDEX(2) #define ao_mmc5983_along(m) (-(m)->y) #define ao_mmc5983_across(m) ((m)->x) @@ -338,12 +338,6 @@ struct ao_adc { #define AO_ADXL375_CS_PORT (&stm_gpioc) #define AO_ADXL375_CS_PIN 12 -#define AO_ADXL375_INT1_PORT (&stm_gpiob) -#define AO_ADXL375_INT1_PIN 8 - -#define AO_ADXL375_INT2_PORT (&stm_gpiob) -#define AO_ADXL375_INT2_PIN 9 - #define AO_ADXL375_AXIS x #define AO_ADXL375_INVERT 1 -- 2.30.2 From a017cfce31429ef25a53a724e99b53c8267ec4ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Mar 2024 16:23:57 -0700 Subject: [PATCH 13/16] altos/stm32f1: Grab both TX/RX DMA mutexes while doing I2C The I2C engine appears to trigger an extra RX DMA transaction which scrambles anything sharing the same DMA units. Signed-off-by: Keith Packard --- src/stm32f1/ao_arch_funcs.h | 6 ++++++ src/stm32f1/ao_dma_stm.c | 21 +++++++++++++++++++++ src/stm32f1/ao_i2c_stm.c | 12 +++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/stm32f1/ao_arch_funcs.h b/src/stm32f1/ao_arch_funcs.h index 3a83f382..7004eb46 100644 --- a/src/stm32f1/ao_arch_funcs.h +++ b/src/stm32f1/ao_arch_funcs.h @@ -350,6 +350,12 @@ ao_dma_set_transfer(uint8_t index, uint16_t count, uint32_t ccr); +void +ao_dma_mutex_get(uint8_t index); + +void +ao_dma_mutex_put(uint8_t index); + void ao_dma_set_isr(uint8_t index, void (*isr)(int index)); diff --git a/src/stm32f1/ao_dma_stm.c b/src/stm32f1/ao_dma_stm.c index d3162d5b..45bb88f3 100644 --- a/src/stm32f1/ao_dma_stm.c +++ b/src/stm32f1/ao_dma_stm.c @@ -66,6 +66,27 @@ void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } static uint8_t ao_dma_active; #endif +void +ao_dma_mutex_get(uint8_t index) +{ + if (ao_dma_allocated[index]) { + if (ao_dma_mutex[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_mutex[index] = 0xff; + } else + ao_mutex_get(&ao_dma_mutex[index]); +} + +void +ao_dma_mutex_put(uint8_t index) +{ + if (ao_dma_allocated[index]) + ao_dma_mutex[index] = 0; + else + ao_mutex_put(&ao_dma_mutex[index]); +} + + void ao_dma_set_transfer(uint8_t index, volatile void *peripheral, diff --git a/src/stm32f1/ao_i2c_stm.c b/src/stm32f1/ao_i2c_stm.c index e84f594b..a61d3eb5 100644 --- a/src/stm32f1/ao_i2c_stm.c +++ b/src/stm32f1/ao_i2c_stm.c @@ -224,11 +224,11 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; /* Clear any pending ADDR bit */ (void) stm_i2c->sr2; ao_i2c_wait_addr(index); - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -241,13 +241,14 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + ao_dma_mutex_get(rx_dma_index); + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_start(tx_dma_index); ao_arch_block_interrupts(); while (!ao_dma_done[tx_dma_index]) if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len)) break; - ao_dma_done_transfer(tx_dma_index); stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0) if (ao_sleep_for(&ao_i2c_state[index], 1 + len)) @@ -258,6 +259,8 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); } + ao_dma_mutex_put(rx_dma_index); + ao_dma_done_transfer(tx_dma_index); return true; } @@ -311,7 +314,9 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_arch_release_interrupts(); ret = ao_i2c_recv_len[index] == 0; } else { + uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + ao_dma_mutex_get(tx_dma_index); ao_dma_set_transfer(rx_dma_index, &stm_i2c->dr, block, @@ -349,8 +354,9 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) break; ao_arch_release_interrupts(); ret = ao_dma_done[rx_dma_index]; - ao_dma_done_transfer(rx_dma_index); stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); + ao_dma_done_transfer(rx_dma_index); + ao_dma_mutex_put(tx_dma_index); } if (stop) ao_i2c_wait_stop(index); -- 2.30.2 From d7a91278051ff75e3edc3e999a6d8096fa4deec4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 3 Mar 2024 16:37:09 -0800 Subject: [PATCH 14/16] altos/easytimer-v2: Generate combined .ihx file for seeed testing The test plan for seeed requires a combined loader and firmware image for a single flashing step. Signed-off-by: Keith Packard --- src/easytimer-v2/Makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/easytimer-v2/Makefile b/src/easytimer-v2/Makefile index 2298ab48..32b9117a 100644 --- a/src/easytimer-v2/Makefile +++ b/src/easytimer-v2/Makefile @@ -71,17 +71,30 @@ CFLAGS = $(PRODUCT_DEF) $(SAMD21_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $( PROGNAME=easytimer-v2 PROG=$(PROGNAME)-$(VERSION).elf HEX=$(PROGNAME)-$(VERSION).ihx +FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf +BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx + +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex SRC=$(ALTOS_SRC) ao_easytimer.c OBJ=$(SRC:.c=.o) -all: $(PROG) $(HEX) +all: $(PROG) $(HEX) $(BOTH_HEX) $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) +$(BOTH_HEX): $(PROG) $(FLASH_PROG) + $(ELFTOHEX) --nosym --output=$@ $(FLASH_PROG) $(PROG) + $(OBJ): $(INC) + +$(FLASH_PROG): FRC + +cd flash-loader && make + +FRC: + distclean: clean clean: -- 2.30.2 From abfa580ad700415f5ea240450a1621f9de35de82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Mar 2024 21:38:48 -0700 Subject: [PATCH 15/16] altos: ao_fec_prepare using wrong value for input len The FEC code always sends a multiple of four bytes, padding by two bytes for even inputs and one byte for odd. But the preparation step was using the wrong value for the length, so the output was getting mangled. Signed-off-by: Keith Packard --- src/kernel/ao_fec_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/ao_fec_tx.c b/src/kernel/ao_fec_tx.c index 8c0e7db4..209581b8 100644 --- a/src/kernel/ao_fec_tx.c +++ b/src/kernel/ao_fec_tx.c @@ -74,7 +74,7 @@ ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra) extra[i++] = (uint8_t) crc; /* Append FEC -- 1 byte if odd, two bytes if even */ - num_fec = 2 - (i & 1); + num_fec = 2 - (len & 1); while (num_fec--) extra[i++] = AO_FEC_TRELLIS_TERMINATOR; return i; -- 2.30.2 From 19c42c4d97151f2dc38e59cff4d0638694fcd27d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Mar 2024 09:45:38 -0700 Subject: [PATCH 16/16] altos/test: Adjust CRC error rate after FEC fix The number of CRC failures during FEC testing is lower now that the packet length bug has been fixed in the FEC encode bits. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index cbced6ae..5f234285 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -304,7 +304,7 @@ ao_real_packet(void) } #define EXPECT_DECODE_FAIL 0 -#define EXPECT_CRC_MISMATCH 6386 +#define EXPECT_CRC_MISMATCH 6304 #define EXPECT_DATA_MISMATCH 0 #define NOISE_AMOUNT 0x50 -- 2.30.2