Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f42a0d5370 |
9 changed files with 11 additions and 169 deletions
|
|
@ -98,8 +98,7 @@ Additional features are available through feature flags:
|
||||||
|
|
||||||
Officially supported feature combinations are:
|
Officially supported feature combinations are:
|
||||||
- `esp,spat,gnss_ubx,screen` (default features, "standalone")
|
- `esp,spat,gnss_ubx,screen` (default features, "standalone")
|
||||||
- `esp,spat,gnss_ubx,screen,ble` ("standalone with BLE")
|
- `esp,spat,gnss_ubx,screen,cam_tx` ("standalone with CAM")
|
||||||
- `esp,spat,gnss_ubx,screen,cam_tx,ble` ("standalone with CAM")
|
|
||||||
- `esp,spat,gnss_ubx,screen,cam_tx,cam,denm`
|
- `esp,spat,gnss_ubx,screen,cam_tx,cam,denm`
|
||||||
- `esp,uart,cam,denm` ("smartphone companion with UART")
|
- `esp,uart,cam,denm` ("smartphone companion with UART")
|
||||||
- `esp,ble,cam,denm,cam_tx` ("smartphone companion with BLE")
|
- `esp,ble,cam,denm,cam_tx` ("smartphone companion with BLE")
|
||||||
|
|
|
||||||
22
build.rs
22
build.rs
|
|
@ -9,7 +9,6 @@ fn main() -> std::io::Result<()> {
|
||||||
println!("cargo:rustc-link-arg=-Tlinkall.x");
|
println!("cargo:rustc-link-arg=-Tlinkall.x");
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile protobuf definition to rust code
|
|
||||||
let descriptor_path =
|
let descriptor_path =
|
||||||
std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join("proto_descriptor.bin");
|
std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join("proto_descriptor.bin");
|
||||||
|
|
||||||
|
|
@ -18,27 +17,6 @@ fn main() -> std::io::Result<()> {
|
||||||
.compile_well_known_types()
|
.compile_well_known_types()
|
||||||
.compile_protos(&["docs/c_its-messages.proto"], &["docs/"])?;
|
.compile_protos(&["docs/c_its-messages.proto"], &["docs/"])?;
|
||||||
|
|
||||||
// get git revision
|
|
||||||
println!("cargo:rustc-rerun-if-changed=.git/HEAD");
|
|
||||||
|
|
||||||
// length:
|
|
||||||
// - tag name: 6-8 chars (v0.1.0 to v1.23.42)
|
|
||||||
// - offset+hash: 0-12 chars (up to 99 commits from tag + 8 char hash)
|
|
||||||
// - SUM: 6-20
|
|
||||||
let git_output = std::process::Command::new("git")
|
|
||||||
.args(["describe", "--tags", "--match", "v*", "--always"])
|
|
||||||
.output()
|
|
||||||
.unwrap();
|
|
||||||
assert!(
|
|
||||||
git_output.stderr.is_empty(),
|
|
||||||
"{}",
|
|
||||||
String::from_utf8(git_output.stderr).unwrap()
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"cargo:rustc-env=GIT_REVISION={}",
|
|
||||||
String::from_utf8(git_output.stdout).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,15 @@ extended=${2:-false}
|
||||||
|
|
||||||
|
|
||||||
features_base=(
|
features_base=(
|
||||||
spat,gnss_ubx,screen # "standalone" simple
|
uart,cam,denm
|
||||||
spat,gnss_ubx,screen,ble # "standalone" with BLE
|
ble,cam,denm,cam_tx
|
||||||
spat,gnss_ubx,screen,ble,cam_tx # "standalone" with CAM
|
uart,ble,cam,denm
|
||||||
spat,gnss_ubx,screen,cam_tx,cam,denm
|
spat,gnss_ubx,screen
|
||||||
uart,cam,denm # "smartphone companion with UART"
|
spat,gnss_ubx,screen,cam_tx
|
||||||
ble,cam,denm,cam_tx # "smartphone companion with BLE"
|
|
||||||
)
|
)
|
||||||
features_more=(
|
features_more=(
|
||||||
uart,ble,cam,denm
|
spat,gnss_ubx,screen,ble
|
||||||
spat,gnss_ubx,screen,cam_tx
|
spat,gnss_ubx,screen,ble,cam_tx
|
||||||
spat,gnss_ubx,screen,cam,denm
|
spat,gnss_ubx,screen,cam,denm
|
||||||
spat,gnss_ubx,screen,cam_tx,cam,denm
|
spat,gnss_ubx,screen,cam_tx,cam,denm
|
||||||
gnss_ubx,screen,cam_tx,cam,denm
|
gnss_ubx,screen,cam_tx,cam,denm
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
## Builds common config for standalone device
|
|
||||||
## -> enable SPAT/ GLOSA with GNSS and a screen + BLE
|
|
||||||
|
|
||||||
cargo run --release -F ble
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
## Builds common config for standalone device with automatic CAM transmission
|
## Builds common config for standalone device with automatic CAM transmission
|
||||||
## -> enable SPAT/ GLOSA with GNSS and a screen + CAM transmission
|
## -> enable SPAT/ GLOSA with GNSS and a screen + CAM transmission
|
||||||
|
|
||||||
cargo run --release -F cam_tx,ble
|
cargo run --release -F cam_tx
|
||||||
|
|
|
||||||
80
src/ble.rs
80
src/ble.rs
|
|
@ -41,76 +41,12 @@ pub enum BleSendable {
|
||||||
SpatemRaw(io::msg::RawMsgRx),
|
SpatemRaw(io::msg::RawMsgRx),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DIS_SERIAL_MAX_LEN: usize = 17;
|
|
||||||
pub const DIS_FW_REVISION_MAX_LEN: usize = 20; // git-describe
|
|
||||||
pub const DIS_SW_REVISION_MAX_LEN: usize = 66; // max length of get_feature_list, joined with comma
|
|
||||||
|
|
||||||
pub struct DeviceInfo {
|
|
||||||
/// WiFi MAC
|
|
||||||
pub serial_number: [u8; DIS_SERIAL_MAX_LEN],
|
|
||||||
/// git tag/ revision
|
|
||||||
pub fw_revision: [u8; DIS_FW_REVISION_MAX_LEN],
|
|
||||||
/// used for feature flags
|
|
||||||
pub sw_revision: [u8; DIS_SW_REVISION_MAX_LEN],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DeviceInfo {
|
|
||||||
pub fn new(serial_number: &str, fw_revision: &str, sw_revision: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
serial_number: string_as_padded_buf(serial_number, DIS_SERIAL_MAX_LEN)
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
fw_revision: string_as_padded_buf(fw_revision, DIS_FW_REVISION_MAX_LEN)
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
sw_revision: string_as_padded_buf(sw_revision, DIS_SW_REVISION_MAX_LEN)
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string_as_padded_buf(value: &str, length: usize) -> alloc::vec::Vec<u8> {
|
|
||||||
let buf = value.as_bytes();
|
|
||||||
let buf_len = buf.len();
|
|
||||||
|
|
||||||
// cut buffer at maximum length or pad with whitespace
|
|
||||||
if buf_len > length {
|
|
||||||
buf[..length].to_vec()
|
|
||||||
} else {
|
|
||||||
let padding_len = length - buf_len;
|
|
||||||
let padding = alloc::vec![b' '; padding_len];
|
|
||||||
|
|
||||||
[buf, &padding].concat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[gatt_server]
|
#[gatt_server]
|
||||||
struct Server {
|
struct Server {
|
||||||
c_its_events: CITSEvents,
|
c_its_events: CITSEvents,
|
||||||
device_info_service: DeviceInfoService,
|
|
||||||
battery_service: BatteryService,
|
battery_service: BatteryService,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gatt_service(uuid = service::DEVICE_INFORMATION)]
|
|
||||||
struct DeviceInfoService {
|
|
||||||
/// Manufacturer name
|
|
||||||
#[characteristic(uuid = characteristic::MANUFACTURER_NAME_STRING, read, value = "jtbx")]
|
|
||||||
mfg_name: &'static str,
|
|
||||||
/// Model number
|
|
||||||
#[characteristic(uuid = characteristic::MODEL_NUMBER_STRING, read, value = "ESP32-C5 C-ITS Companion")]
|
|
||||||
model_number: &'static str,
|
|
||||||
// Serial Number String
|
|
||||||
#[characteristic(uuid = characteristic::SERIAL_NUMBER_STRING, read, value = [0u8; DIS_SERIAL_MAX_LEN])]
|
|
||||||
serial_number: [u8; DIS_SERIAL_MAX_LEN],
|
|
||||||
// Firmware Revision String
|
|
||||||
#[characteristic(uuid = characteristic::FIRMWARE_REVISION_STRING, read, value = [0u8; DIS_FW_REVISION_MAX_LEN])]
|
|
||||||
fw_revision: [u8; DIS_FW_REVISION_MAX_LEN],
|
|
||||||
// Software Revision String
|
|
||||||
#[characteristic(uuid = characteristic::SOFTWARE_REVISION_STRING, read, value = [0u8; DIS_SW_REVISION_MAX_LEN])]
|
|
||||||
sw_revision: [u8; DIS_SW_REVISION_MAX_LEN],
|
|
||||||
}
|
|
||||||
|
|
||||||
#[gatt_service(uuid = service::BATTERY)]
|
#[gatt_service(uuid = service::BATTERY)]
|
||||||
struct BatteryService {
|
struct BatteryService {
|
||||||
/// Battery Level
|
/// Battery Level
|
||||||
|
|
@ -187,7 +123,6 @@ pub async fn run(
|
||||||
>,
|
>,
|
||||||
name: alloc::string::String,
|
name: alloc::string::String,
|
||||||
short_name: alloc::string::String,
|
short_name: alloc::string::String,
|
||||||
device_info: DeviceInfo,
|
|
||||||
) {
|
) {
|
||||||
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
||||||
HostResources::new();
|
HostResources::new();
|
||||||
|
|
@ -209,21 +144,6 @@ pub async fn run(
|
||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// set "dynamic" device info data
|
|
||||||
let _ = server
|
|
||||||
.device_info_service
|
|
||||||
.serial_number
|
|
||||||
.set(&server, &device_info.serial_number);
|
|
||||||
let _ = server
|
|
||||||
.device_info_service
|
|
||||||
.fw_revision
|
|
||||||
.set(&server, &device_info.fw_revision);
|
|
||||||
let _ = server
|
|
||||||
.device_info_service
|
|
||||||
.sw_revision
|
|
||||||
.set(&server, &device_info.sw_revision);
|
|
||||||
|
|
||||||
// advertise and run update logic
|
|
||||||
let _ = embassy_futures::join::join(ble_task(runner), async {
|
let _ = embassy_futures::join::join(ble_task(runner), async {
|
||||||
loop {
|
loop {
|
||||||
// run advertisement and set data until a client connects
|
// run advertisement and set data until a client connects
|
||||||
|
|
|
||||||
14
src/main.rs
14
src/main.rs
|
|
@ -148,6 +148,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
|
|
||||||
// Setup battery voltage readout (GPIO6 as input and GPIO26 as enable)
|
// Setup battery voltage readout (GPIO6 as input and GPIO26 as enable)
|
||||||
let mut battery = xiao::Battery::new(peripherals.ADC1, peripherals.GPIO6, peripherals.GPIO26);
|
let mut battery = xiao::Battery::new(peripherals.ADC1, peripherals.GPIO6, peripherals.GPIO26);
|
||||||
|
// TODO: expose via BLE as battery service!
|
||||||
|
|
||||||
// Setup ST7789 screen
|
// Setup ST7789 screen
|
||||||
// SCL: D8/ GPIO8 (SPI_SCK)
|
// SCL: D8/ GPIO8 (SPI_SCK)
|
||||||
|
|
@ -233,18 +234,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
serial[2]
|
serial[2]
|
||||||
);
|
);
|
||||||
let short_name = alloc::format!("V2X {:02x}{:02x}", serial[1], serial[2]); // max 8 chars!
|
let short_name = alloc::format!("V2X {:02x}{:02x}", serial[1], serial[2]); // max 8 chars!
|
||||||
|
spawner.spawn(ble::run(controller, name, short_name).expect("Failed to spawn BLE task"));
|
||||||
let fw_revision = core::env!("GIT_REVISION");
|
|
||||||
let sw_revision = util::get_feature_list().join(",");
|
|
||||||
spawner.spawn(
|
|
||||||
ble::run(
|
|
||||||
controller,
|
|
||||||
name,
|
|
||||||
short_name,
|
|
||||||
ble::DeviceInfo::new(&mac.to_string(), fw_revision, &sw_revision),
|
|
||||||
)
|
|
||||||
.expect("Failed to spawn BLE task"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup GNSS:
|
// Setup GNSS:
|
||||||
|
|
|
||||||
38
src/util.rs
38
src/util.rs
|
|
@ -31,41 +31,3 @@ pub(crate) fn get_tx_feature_list() -> Vec<&'static str> {
|
||||||
|
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn get_feature_list() -> Vec<&'static str> {
|
|
||||||
let mut features = alloc::vec![];
|
|
||||||
|
|
||||||
if cfg!(feature = "gnss_ubx") {
|
|
||||||
features.push("gnss_ubx");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "gnss_l67k") {
|
|
||||||
features.push("gnss_l67k");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "cam_tx") {
|
|
||||||
features.push("cam_tx");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "cam") {
|
|
||||||
features.push("cam");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "denm") {
|
|
||||||
features.push("denm");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "spat") {
|
|
||||||
features.push("spat");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "spat_debug") {
|
|
||||||
features.push("spat_debug");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "screen") {
|
|
||||||
features.push("screen");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "uart") {
|
|
||||||
features.push("uart");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "ble") {
|
|
||||||
features.push("ble");
|
|
||||||
}
|
|
||||||
|
|
||||||
features
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue