Changed AMS1117 with TPS63001(1.2A max buck/boost convertor)

main
noah metz 2026-06-25 01:31:10 -06:00
parent 21ecc5ab16
commit 5e45d07eb0
8 changed files with 6785 additions and 3820 deletions

@ -7,8 +7,8 @@
#define BTN_BACK_GPIO 13
// ── RGB LED ───────────────────────────────────────────────────────────────────
#define LED_R_GPIO 16
#define LED_G_GPIO 17
#define LED_R_GPIO 17
#define LED_G_GPIO 16
#define LED_B_GPIO 4
// ── I2C / OLED ────────────────────────────────────────────────────────────────
@ -104,8 +104,12 @@ extern const char *counter_names[NUM_COUNTERS];
#define FONT_MAX 0x5A
// ── Battery ADC (GPIO34, ADC1 Channel 6) ──────────────────────────────────────
#define BATT_LOW_PCT 10 // flash battery indicator below this
#define BATT_SAMPLE_TICKS 500 // sample every 500 × 10ms = 5s
#define BATT_LOW_PCT 10 // flash battery indicator below this
#define BATT_SAMPLE_TICKS 50 // sample every 50 × 10ms = 0.5s
#define BATT_CHARGE_GPIO 23 // low when charger is connected (active-low)
#define BATT_FULL_GPIO 19 // low when battery is full (active-low)
#define BATT_LOAD_COMP_BLE_MV 200 // voltage sag offset (mV) when BLE is active
#define BATT_LOAD_COMP_MV 50 // voltage sag offset (mV) when BLE is off
// ── Auto-sleep ────────────────────────────────────────────────────────────────
#define SLEEP_TIMEOUT_DEF 60 // default auto-sleep timeout (minutes)

@ -153,47 +153,83 @@ void oled_draw_header(void)
}
// Slot 5 (cols 80-95): percentage text, page 0
// Slot 6 (cols 96-111): vertical battery icon, nub at top, fill from bottom
// or lightning bolt when charging
if (g_battery_pct >= 0) {
int show = (g_battery_pct >= BATT_LOW_PCT || (g_tick / 50) % 2 == 0);
if (show) {
// ── Percentage text, vertically centered (rows 4-11) ─────────────
char pct_str[5];
int plen = snprintf(pct_str, sizeof(pct_str), "%d", g_battery_pct);
int tx = 5 * SEG_W + (SEG_W - plen * 5) / 2;
for (int ci = 0; ci < plen; ci++) {
uint8_t c = (uint8_t)pct_str[ci];
if (c < FONT_BASE || c > FONT_MAX) continue;
const uint8_t *glyph = font5x8[c - FONT_BASE];
for (int sc = 0; sc < 5; sc++, tx++) {
if (tx < 0 || tx >= OLED_WIDTH) continue;
pages[0][tx] &= ~(uint8_t)(glyph[sc] << 4); // font bits 0-3 → rows 4-7
pages[1][tx] &= ~(uint8_t)(glyph[sc] >> 4); // font bits 4-7 → rows 8-11
if (!g_charging && !g_batt_full) {
// ── Percentage text, vertically centered (rows 4-11) ─────────
char pct_str[5];
int plen = snprintf(pct_str, sizeof(pct_str), "%d", g_battery_pct);
int tx = 5 * SEG_W + (SEG_W - plen * 5) / 2;
for (int ci = 0; ci < plen; ci++) {
uint8_t c = (uint8_t)pct_str[ci];
if (c < FONT_BASE || c > FONT_MAX) continue;
const uint8_t *glyph = font5x8[c - FONT_BASE];
for (int sc = 0; sc < 5; sc++, tx++) {
if (tx < 0 || tx >= OLED_WIDTH) continue;
pages[0][tx] &= ~(uint8_t)(glyph[sc] << 4);
pages[1][tx] &= ~(uint8_t)(glyph[sc] >> 4);
}
}
}
// ── Vertical battery icon ─────────────────────────────────────────
// 1px inset from slot edges: body cols 2-13, rows 3-14.
// Nub: cols 5-10, rows 1-2.
// Inner: cols 3-12, rows 4-13 (10 rows). Fill rises from bottom.
int fill_rows = g_battery_pct * 10 / 100;
int fill_start = 14 - fill_rows; // first filled inner row
uint8_t p0_fill = 0, p1_fill = 0;
for (int r = 4; r <= 7; r++) if (r >= fill_start) p0_fill |= (1 << r);
for (int r = 8; r <= 13; r++) if (r >= fill_start) p1_fill |= (1 << (r-8));
// Body: cols 2-13, rows 3-14. Nub: cols 5-10, rows 1-2.
// Inner: cols 3-12, rows 4-13 (10 rows).
int bbase = 6 * SEG_W;
for (int x = 0; x < 16; x++) {
uint8_t p0 = 0, p1 = 0;
if (x == 2 || x == 13) {
p0 = 0xF8; p1 = 0x7F; // side borders rows 3-14
} else if (x >= 3 && x <= 12) {
p0 = 0x08 | p0_fill; // top border (row 3) + fill
p1 = 0x40 | p1_fill; // bottom border (row 14) + fill
if (g_batt_full) {
// Fully filled battery body; no percentage text.
for (int x = 0; x < 16; x++) {
uint8_t p0 = 0, p1 = 0;
if (x == 2 || x == 13) {
p0 = 0xF8; p1 = 0x7F;
} else if (x >= 3 && x <= 12) {
p0 = 0xF8; p1 = 0x7F;
}
if (x >= 5 && x <= 10) p0 |= 0x06;
pages[0][bbase + x] &= ~p0;
pages[1][bbase + x] &= ~p1;
}
} else if (g_charging) {
// Lightning bolt inside body; no fill level or percentage.
// Per-column page masks for rows 4-13 within the 16-wide slot:
// p0 bits 4-7 → rows 4-7; p1 bits 0-5 → rows 8-13
static const uint8_t bp0[16] = {0,0,0,0,0,0x80,0x80,0xC0,0xF0,0x90,0x10,0,0,0,0,0};
static const uint8_t bp1[16] = {0,0,0,0,0,0x19,0x0D,0x03,0x01,0x01,0x00,0,0,0,0,0};
for (int x = 0; x < 16; x++) {
uint8_t p0 = bp0[x], p1 = bp1[x];
if (x == 2 || x == 13) {
p0 |= 0xF8; p1 |= 0x7F;
} else if (x >= 3 && x <= 12) {
p0 |= 0x08; // top border row 3
p1 |= 0x40; // bottom border row 14
}
if (x >= 5 && x <= 10) p0 |= 0x06; // nub rows 1-2
pages[0][bbase + x] &= ~p0;
pages[1][bbase + x] &= ~p1;
}
} else {
// Fill level rising from bottom.
int fill_rows = g_battery_pct * 10 / 100;
int fill_start = 14 - fill_rows;
uint8_t p0_fill = 0, p1_fill = 0;
for (int r = 4; r <= 7; r++) if (r >= fill_start) p0_fill |= (1 << r);
for (int r = 8; r <= 13; r++) if (r >= fill_start) p1_fill |= (1 << (r-8));
for (int x = 0; x < 16; x++) {
uint8_t p0 = 0, p1 = 0;
if (x == 2 || x == 13) {
p0 = 0xF8; p1 = 0x7F;
} else if (x >= 3 && x <= 12) {
p0 = 0x08 | p0_fill;
p1 = 0x40 | p1_fill;
}
if (x >= 5 && x <= 10) p0 |= 0x06;
pages[0][bbase + x] &= ~p0;
pages[1][bbase + x] &= ~p1;
}
if (x >= 5 && x <= 10) p0 |= 0x06; // nub rows 1-2
pages[0][bbase + x] &= ~p0;
pages[1][bbase + x] &= ~p1;
}
}
}

@ -24,6 +24,8 @@
// ── Global state ──────────────────────────────────────────────────────────────
int g_sleep_mode = 0;
int g_battery_pct = -1;
int g_charging = 0;
int g_batt_full = 0;
int g_sleep_timeout_min = SLEEP_TIMEOUT_DEF;
static adc_oneshot_unit_handle_t s_adc;
@ -78,6 +80,7 @@ int g_dice_rolled = 0;
int g_dice_sum = 0;
// ── Serial command task ───────────────────────────────────────────────────────
#ifdef DEBUG
static void serial_print_state(void)
{
printf("DBG STATE life=%d poison=%u cmdr=[%d,%d,%d,%d] counters=[%d,%d,%d] menu=%d ble=%d eliminated=%d\n",
@ -150,6 +153,7 @@ static void serial_cmd_task(void *arg)
}
}
}
#endif // DEBUG
// ── app_main ──────────────────────────────────────────────────────────────────
void app_main(void)
@ -200,12 +204,21 @@ void app_main(void)
};
gpio_config(&gpio_cfg);
gpio_config_t charge_cfg = {
.pin_bit_mask = (1ULL<<BATT_CHARGE_GPIO) | (1ULL<<BATT_FULL_GPIO),
.mode=GPIO_MODE_INPUT, .pull_up_en=GPIO_PULLUP_ENABLE,
.pull_down_en=GPIO_PULLDOWN_DISABLE, .intr_type=GPIO_INTR_DISABLE,
};
gpio_config(&charge_cfg);
ble_init();
#ifdef DEBUG
uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
esp_vfs_dev_uart_use_driver(0);
setvbuf(stdin, NULL, _IONBF, 0);
xTaskCreate(serial_cmd_task, "serial_cmd", 4096, NULL, 3, NULL);
#endif
oled_draw_header();
oled_draw_life();
@ -717,15 +730,37 @@ void app_main(void)
if (g_battery_pct >= 0 && g_battery_pct < BATT_LOW_PCT && g_tick % 50 == 0)
oled_draw_header();
// Update charging/full state every 50 ticks (0.5s); redraw header on change
if (g_tick % 50 == 0) {
int charging = !gpio_get_level(BATT_CHARGE_GPIO);
int batt_full = !gpio_get_level(BATT_FULL_GPIO);
if (charging != g_charging || batt_full != g_batt_full) {
g_charging = charging;
g_batt_full = batt_full;
oled_draw_header();
}
}
if (++batt_tick >= BATT_SAMPLE_TICKS) {
batt_tick = 0;
int raw, voltage_mv;
static int batt_raw_buf[100];
static int batt_raw_idx = 0;
static int batt_raw_count = 0;
int raw;
adc_oneshot_read(s_adc, ADC_CHANNEL_6, &raw);
batt_raw_buf[batt_raw_idx] = raw;
batt_raw_idx = (batt_raw_idx + 1) % 100;
if (batt_raw_count < 100) batt_raw_count++;
int sum = 0;
for (int i = 0; i < batt_raw_count; i++) sum += batt_raw_buf[i];
int avg_raw = sum / batt_raw_count;
int voltage_mv;
if (s_adc_cali_ok)
adc_cali_raw_to_voltage(s_adc_cali, raw, &voltage_mv);
adc_cali_raw_to_voltage(s_adc_cali, avg_raw, &voltage_mv);
else
voltage_mv = raw * 3100 / 4095;
int cell_mv = voltage_mv * 2; // 100k/100k voltage divider
voltage_mv = avg_raw * 3100 / 4095;
int comp_mv = g_ble_enabled ? BATT_LOAD_COMP_BLE_MV : BATT_LOAD_COMP_MV;
int cell_mv = voltage_mv * 2 + comp_mv; // 100k/100k divider + load compensation
// LiPo discharge curve: piecewise linear interpolation.
// Voltage stays flat ~3.7-4.2V through most of charge; linear
// mapping reads too high. Table derived from typical LiPo OCV curve.

@ -35,6 +35,8 @@ extern ble_peer_t g_peers[MAX_BLE_PEERS];
// Battery / power
extern int g_battery_pct; // -1 = not yet sampled
extern int g_charging; // 1 when charger is connected (BATT_CHARGE_GPIO low)
extern int g_batt_full; // 1 when battery is full (BATT_FULL_GPIO low)
extern int g_sleep_timeout_min; // 0 = disabled
// Timing

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"active_layer": 2,
"active_layer_preset": "Back Layers",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
@ -53,7 +53,7 @@
"board_outline_area",
"ly_points"
],
"visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff",
"visible_layers": "00000000_00000000_00000002_2200888c",
"zone_display_mode": 0
},
"git": {

@ -691,7 +691,7 @@
"uuid": "4f1ddaab-5ed8-4280-ae9f-5da3efc5b3b5"
}
],
"used_designators": "#PWR16-17,#PWR44-45,R23-26,D3",
"used_designators": "",
"variants": []
},
"sheets": [

File diff suppressed because it is too large Load Diff