2022-07-06 20:33:43 +02:00
|
|
|
use anyhow;
|
|
|
|
|
2022-07-11 20:13:52 +02:00
|
|
|
use std::{
|
|
|
|
sync::mpsc::SyncSender,
|
|
|
|
thread,
|
2022-07-12 19:10:04 +02:00
|
|
|
time::{Duration, Instant},
|
|
|
|
io::{Read, Write},
|
2022-07-11 20:13:52 +02:00
|
|
|
};
|
2022-07-06 20:33:43 +02:00
|
|
|
|
2022-07-11 16:17:17 +02:00
|
|
|
use esp_idf_hal::prelude::*;
|
2022-07-20 12:33:11 +02:00
|
|
|
use esp_idf_hal::serial::{self, Rx, Tx};
|
2022-07-11 16:17:17 +02:00
|
|
|
|
|
|
|
use ublox::*;
|
|
|
|
|
2022-07-06 20:33:43 +02:00
|
|
|
use crate::modem::Msg;
|
2022-07-11 20:13:52 +02:00
|
|
|
use crate::serial::SerialIO;
|
2022-07-06 20:33:43 +02:00
|
|
|
|
2022-07-20 12:33:11 +02:00
|
|
|
struct GpsModule<UART: serial::Uart> {
|
2022-07-12 19:10:04 +02:00
|
|
|
port: SerialIO<UART>,
|
|
|
|
parser: Parser<Vec<u8>>,
|
|
|
|
}
|
|
|
|
|
2022-07-20 12:33:11 +02:00
|
|
|
impl<UART: serial::Uart> GpsModule<UART> {
|
|
|
|
pub fn new(tx: Tx<UART>, rx: Rx<UART>) -> Self {
|
2022-07-12 19:10:04 +02:00
|
|
|
let parser = Parser::default();
|
2022-07-20 12:33:11 +02:00
|
|
|
GpsModule { port: SerialIO::new(tx, rx), parser }
|
2022-07-12 19:10:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_all(&mut self, data: &[u8]) -> std::io::Result<()> {
|
|
|
|
println!("WRITE: {:?}", data);
|
|
|
|
self.port.write(data).map(|_| ())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update<T: FnMut(PacketRef)>(&mut self, mut cb: T) -> std::io::Result<()> {
|
|
|
|
println!("UPDATING ... ... ...");
|
|
|
|
loop {
|
|
|
|
let mut local_buf = [0; 1024];
|
|
|
|
let nbytes = self.read_port(&mut local_buf)?;
|
|
|
|
if nbytes == 0 {
|
2022-07-20 12:33:11 +02:00
|
|
|
println!("no bytes to read :(");
|
2022-07-12 19:10:04 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// parser.consume adds the buffer to its internal buffer, and
|
|
|
|
// returns an iterator-like object we can use to process the packets
|
|
|
|
let mut it = self.parser.consume(&local_buf[..nbytes]);
|
|
|
|
while let Some(Ok(packet)) = it.next() {
|
|
|
|
println!("READ: {:?}", packet);
|
|
|
|
cb(packet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-07-20 12:33:11 +02:00
|
|
|
pub fn wait_for_ack<T: UbxPacketMeta>(&mut self, timeout: Duration) -> std::io::Result<bool> {
|
2022-07-12 19:10:04 +02:00
|
|
|
let mut found_packet = false;
|
|
|
|
println!("LOOKING FOR ACK ...");
|
|
|
|
let start = Instant::now();
|
|
|
|
while !found_packet && start.elapsed() < timeout {
|
|
|
|
self.update(|packet| {
|
|
|
|
if let PacketRef::AckAck(ack) = packet {
|
|
|
|
if ack.class() == T::CLASS && ack.msg_id() == T::ID {
|
|
|
|
println!("FOUND PACKET: {} {}", ack.class(), ack.msg_id());
|
|
|
|
found_packet = true;
|
|
|
|
}
|
|
|
|
}
|
2022-07-20 12:33:11 +02:00
|
|
|
else if let PacketRef::AckNak(nak) = packet {
|
|
|
|
println!("NAK PACKET: {} {}", nak.class(), nak.msg_id());
|
|
|
|
}
|
2022-07-12 19:10:04 +02:00
|
|
|
})?;
|
|
|
|
}
|
2022-07-20 12:33:11 +02:00
|
|
|
println!("exiting wait_for_ack");
|
|
|
|
Ok(found_packet)
|
2022-07-12 19:10:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Reads the serial port, converting timeouts into "no data received"
|
|
|
|
fn read_port(&mut self, output: &mut [u8]) -> std::io::Result<usize> {
|
|
|
|
match self.port.read(output) {
|
|
|
|
Ok(b) => Ok(b),
|
|
|
|
Err(e) => {
|
|
|
|
if e.kind() == std::io::ErrorKind::TimedOut {
|
|
|
|
Ok(0)
|
|
|
|
} else {
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 16:17:17 +02:00
|
|
|
pub fn main<T: Sync + Send>(
|
2022-07-12 19:10:04 +02:00
|
|
|
tx: esp_idf_hal::gpio::Gpio12<T>,
|
|
|
|
rx: esp_idf_hal::gpio::Gpio13<T>,
|
2022-07-11 16:17:17 +02:00
|
|
|
uart: serial::UART2,
|
|
|
|
sender: SyncSender<Msg>,
|
|
|
|
) -> Result<(), anyhow::Error> {
|
|
|
|
let serial_pins = serial::Pins {
|
|
|
|
tx,
|
|
|
|
rx,
|
|
|
|
cts: None,
|
|
|
|
rts: None,
|
|
|
|
};
|
2022-07-12 19:10:04 +02:00
|
|
|
|
|
|
|
let serial_config = serial::config::Config::default()
|
|
|
|
.baudrate(Hertz(9600))
|
|
|
|
.data_bits(serial::config::DataBits::DataBits8)
|
|
|
|
.parity_none()
|
|
|
|
.flow_control(serial::config::FlowControl::None)
|
|
|
|
.stop_bits(serial::config::StopBits::STOP1);
|
|
|
|
|
2022-07-11 20:13:52 +02:00
|
|
|
let serial: serial::Serial<serial::UART2, _, _> = serial::Serial::new(
|
2022-07-11 16:17:17 +02:00
|
|
|
uart,
|
|
|
|
serial_pins,
|
2022-07-12 19:10:04 +02:00
|
|
|
serial_config,
|
2022-07-11 16:17:17 +02:00
|
|
|
)?;
|
|
|
|
|
2022-07-20 12:33:11 +02:00
|
|
|
let (tx, rx) = serial.split();
|
|
|
|
let mut device = GpsModule::new(tx, rx);
|
2022-07-11 16:17:17 +02:00
|
|
|
|
2022-07-12 19:10:04 +02:00
|
|
|
// Configure the device to talk UBX
|
|
|
|
device
|
|
|
|
.write_all(
|
|
|
|
&CfgPrtUartBuilder {
|
|
|
|
portid: UartPortId::Uart1,
|
|
|
|
reserved0: 0,
|
|
|
|
tx_ready: 0,
|
|
|
|
mode: UartMode::new(DataBits::Eight, Parity::None, StopBits::One),
|
|
|
|
baud_rate: 9600,
|
|
|
|
in_proto_mask: InProtoMask::all(),
|
|
|
|
out_proto_mask: OutProtoMask::UBLOX,
|
|
|
|
flags: 0,
|
|
|
|
reserved5: 0,
|
|
|
|
}
|
|
|
|
.into_packet_bytes(),
|
2022-07-20 12:33:11 +02:00
|
|
|
)?;
|
2022-07-12 19:10:04 +02:00
|
|
|
device.wait_for_ack::<CfgPrtUart>(Duration::from_millis(3000)).unwrap();
|
|
|
|
println!("CfgPrtUart acked!");
|
|
|
|
|
2022-07-20 12:33:11 +02:00
|
|
|
// Set interval for the NavPosVelTime packet
|
|
|
|
println!("Sending set_rate_for::<NavPosVelTime> ...");
|
|
|
|
for i in 1..5 {
|
|
|
|
device
|
|
|
|
.write_all(
|
|
|
|
&CfgMsgAllPortsBuilder::set_rate_for::<NavPosVelTime>([0, 1, 1, 0, 0, 0])
|
2022-07-12 19:10:04 +02:00
|
|
|
.into_packet_bytes(),
|
2022-07-20 12:33:11 +02:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
println!("SENT set_rate_for::<NavPosVelTime>({}) !!!", i);
|
|
|
|
if let Ok(true) = device.wait_for_ack::<CfgMsgSinglePort>(Duration::from_millis(3000)) {
|
|
|
|
println!("Setting rate for NavPosVelTime acked! Exiting loop ...");
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2022-07-12 19:10:04 +02:00
|
|
|
|
|
|
|
// Send a packet request for the MonVer packet
|
2022-07-20 12:33:11 +02:00
|
|
|
//device
|
|
|
|
// .write_all(&UbxPacketRequest::request_for::<MonVer>().into_packet_bytes())
|
|
|
|
// .unwrap();
|
2022-07-12 19:10:04 +02:00
|
|
|
|
|
|
|
// Start reading data
|
|
|
|
println!("Opened u-blox device, waiting for solutions...");
|
|
|
|
for _ in 0..20 {
|
|
|
|
device
|
|
|
|
.update(|packet| match packet {
|
|
|
|
PacketRef::MonVer(packet) => {
|
|
|
|
println!(
|
|
|
|
"SW version: {} HW version: {}",
|
|
|
|
packet.software_version(),
|
|
|
|
packet.hardware_version()
|
|
|
|
);
|
|
|
|
println!("{:?}", packet);
|
2022-07-11 20:13:52 +02:00
|
|
|
}
|
2022-07-12 19:10:04 +02:00
|
|
|
PacketRef::NavPosVelTime(sol) => {
|
|
|
|
let has_posvel = sol.fix_type() == GpsFix::Fix3D
|
|
|
|
|| sol.fix_type() == GpsFix::GPSPlusDeadReckoning;
|
|
|
|
|
|
|
|
if has_posvel {
|
|
|
|
let pos: Position = (&sol).into();
|
|
|
|
let vel: Velocity = (&sol).into();
|
|
|
|
println!(
|
|
|
|
"Latitude: {:.5} Longitude: {:.5} Altitude: {:.2}m",
|
|
|
|
pos.lat, pos.lon, pos.alt
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"Speed: {:.2} m/s Heading: {:.2} degrees",
|
|
|
|
vel.speed, vel.heading
|
|
|
|
);
|
|
|
|
println!("Sol: {:?}", sol);
|
|
|
|
}
|
2022-07-11 20:13:52 +02:00
|
|
|
}
|
2022-07-12 19:10:04 +02:00
|
|
|
_ => {
|
|
|
|
println!("{:?}", packet);
|
2022-07-11 20:13:52 +02:00
|
|
|
}
|
2022-07-20 12:33:11 +02:00
|
|
|
})?;
|
|
|
|
thread::sleep(Duration::from_millis(1000));
|
2022-07-06 20:33:43 +02:00
|
|
|
}
|
2022-07-12 19:10:04 +02:00
|
|
|
|
2022-07-11 20:13:52 +02:00
|
|
|
println!("exiting GPS sender loop :)");
|
2022-07-06 20:33:43 +02:00
|
|
|
Ok(())
|
|
|
|
}
|