saltylab-firmware/src/esc_vesc.c
sl-firmware 844504e92e refactor: ESC abstraction layer with pluggable backends (Issue #388)
BREAKING CHANGE: Hoverboard implementation moved to pluggable vtable architecture.

## Implementation

### New Files
- include/esc_backend.h: Abstract interface (vtable) with:
  - esc_telemetry_t struct (voltage, current, temp, speed, steer, fault)
  - esc_backend_t vtable (init, send, estop, resume, get_telemetry)
  - Runtime registration (esc_backend_register/get)
  - Convenience wrappers (esc_init, esc_send, esc_estop, etc)

- src/esc_backend.c: Backend registry and wrapper implementations

- src/esc_hoverboard.c: Hoverboard backend implementing vtable
  - USART2 @ 115200 baud configuration
  - EFeru FOC packet encoding (0xABCD start, XOR checksum)
  - Backward-compatible hoverboard_init/send wrappers
  - Telemetry stub (future: add RX feedback parsing)

- src/esc_vesc.c: VESC backend stub (filled by Issue #383)
  - Placeholder functions for FSESC 4.20 Plus integration
  - Public vesc_backend_register_impl() for runtime registration
  - Ready for pyvesc protocol implementation

### Modified Files
- src/motor_driver.c: Changed from direct hoverboard_send() calls to esc_send()
  - No logic changes, ESC-agnostic via vtable

- include/config.h: Added ESC_BACKEND define
  - Compile-time selection (default: HOVERBOARD)
  - Comments document architecture for future VESC support

### Removed Files
- src/hoverboard.c: Original implementation merged into esc_hoverboard.c

## Architecture Benefits
1. **Backend Pluggability**: Support multiple ESC types without code duplication
2. **Zero Direct Dependencies**: motor_driver.c never calls hoverboard functions directly
3. **Clean Testing**: Each backend can be tested/stubbed independently
4. **Future-Ready**: VESC integration (Issue #383) just implements the vtable
5. **Backward Compatible**: Existing code calling hoverboard_init/send still works

## Testing
- pio run:  PASS (55.4KB Flash, 16.9KB RAM)
- Hoverboard backend tested via existing balance tests (unchanged logic)
- VESC backend stub compiles and links (no-op until #383 fills implementation)

## Blocks
- Issue #383 (VESC integration) — ready to implement vtable functions
- Issue #384 (pan/tilt servo) — may use independent PWM (not blocked)

## Dependencies
- None — this is pure refactoring, no API changes for callers

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 10:36:35 -05:00

71 lines
2.1 KiB
C

#include "esc_backend.h"
/*
* VESC ESC Backend Stub
*
* Placeholder implementation for FSESC 4.20 Plus (VESC-based dual ESC).
* UART: ttyTHS1 (Jetson Orin) → FC USART6 @ 921600 baud
* Protocol: pyvesc with CRC16-XModem checksum
*
* Issue #383: VESC integration (fills in this stub)
* Issue #388: ESC abstraction layer (provides this interface)
*
* TODO (Issue #383):
* - Implement vesc_init() with UART/GPIO config
* - Implement vesc_send() with pyvesc packet encoding (duty/RPM control)
* - Implement vesc_estop() to disable motor controller
* - Implement vesc_get_telemetry() to parse VESC state messages
* - Add balance mode configuration if using VESC balance app
*/
static const esc_backend_t vesc_backend;
/* Stub implementations — no-op until #383 fills them in */
static void vesc_backend_init(void) {
/* TODO (Issue #383): Initialize UART6, configure VESC balance mode */
}
static void vesc_backend_send(int16_t speed, int16_t steer) {
/* TODO (Issue #383): Encode speed/steer to pyvesc packet and send via UART6 */
(void)speed;
(void)steer;
}
static void vesc_backend_estop(void) {
/* TODO (Issue #383): Send VESC shutdown command to disable motors */
}
static void vesc_backend_resume(void) {
/* TODO (Issue #383): Resume from estop if needed */
}
static void vesc_backend_get_telemetry(esc_telemetry_t *out) {
/* TODO (Issue #383): Poll/parse VESC telemetry (voltage, current, RPM, temp, fault) */
if (out) {
out->speed = 0;
out->steer = 0;
out->voltage_mv = 0;
out->current_ma = 0;
out->temperature_c = 0;
out->fault = 0;
}
}
/* VESC backend vtable */
static const esc_backend_t vesc_backend = {
.init = vesc_backend_init,
.send = vesc_backend_send,
.estop = vesc_backend_estop,
.resume = vesc_backend_resume,
.get_telemetry = vesc_backend_get_telemetry,
};
/*
* Public function to register VESC backend.
* Called from main.c when configured with ESC_BACKEND=VESC.
*/
void vesc_backend_register_impl(void) {
esc_backend_register(&vesc_backend);
}