From 144854e4b1a7ac38c5ddd2b0d45c495f491aa5dc Mon Sep 17 00:00:00 2001 From: Andy Wortman Date: Sat, 27 Jul 2019 20:07:05 -0700 Subject: significant rewrite for threaded qhy operation --- src/main.rs | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 5 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 7275c96..dc70da6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,20 +7,181 @@ mod asicam; mod qhyccd; +#[macro_use] +extern crate crossbeam_channel; + +use crossbeam_channel::{Sender, Receiver}; +use crossbeam_channel::unbounded; + +use std::time::Duration; + use crate::asicam::ASICamera2::{ControlType, ImageType}; use crate::asicam::Camera; +use crate::qhyccd::QHYResponse; +use crate::qhyccd::QHYMessage; + +use std::path::Path; +use std::fs::File; +use std::io::BufWriter; + +use png::HasParameters; + +fn record_image(data: &[u8], dimensions: Dimensions, target: &'static str, image_id: u32) { + let path_string = format!("{}_{}.png", target, image_id); + println!("writing {}..", path_string); + let dest = Path::new(&path_string); + let file = File::create(dest).unwrap(); + let ref mut w = BufWriter::new(file); + let mut encoder = png::Encoder::new(w, dimensions.width, dimensions.height); + let color_type = if dimensions.channels == 3 { + png::ColorType::RGB + } else if dimensions.channels == 1 { + png::ColorType::Grayscale + } else { panic!("Unsupported channel count: {}", dimensions.channels); }; + + let bitness = if dimensions.bpp == 8 { + png::BitDepth::Eight + } else if dimensions.bpp == 16 { + png::BitDepth::Sixteen + } else { + panic!("Unknwon bitness: {}", dimensions.bpp); + }; + encoder.set(color_type).set(bitness); + let mut writer = encoder.write_header().unwrap(); + writer.write_image_data(data).unwrap(); + println!("image written!"); +} + fn main() { let test = true; -// println!("Doing qhy..."); -// operate_qhy(test); - println!("Doing asi..."); - operate_asi(test); + println!("Doing qhy..."); + let (image_writer, image_reader) = unbounded(); + let (frame_sender, free_frames) = unbounded(); + + std::thread::spawn(move || { + loop { + select! { + recv(image_reader) -> msg => { + match msg { + Ok(ImageInfo { mut data, dimensions, target, image_id }) => { + qhyccd::fix_channels_and_endianness(data.as_mut_slice()); + record_image(data.as_slice(), dimensions, target, image_id); + println!("pretend i wrote image {}_{}", target, image_id); + frame_sender.send(data).unwrap(); + } + Err(RecvError) => { + // something in the application has crashed. time 2 die + return; + } + } + } + } + } + }); + + operate_qhy("dark_gain_4000", None, free_frames, image_writer); +// println!("Doing asi..."); +// operate_asi(test); +} + +#[derive(Debug, Copy, Clone)] +struct Dimensions { + width: u32, + height: u32, + bpp: u8, + channels: u8, } -fn operate_qhy(test: bool) { +impl Dimensions { + pub fn new(width: u32, height: u32, bpp: u8, channels: u8) -> Self { + Dimensions { width, height, bpp, channels } + } +} + +struct ImageInfo { + data: Vec, + dimensions: Dimensions, + target: &'static str, + image_id: u32 +} + +enum ImageWriter { + FrameReady(Vec, Dimensions, &'static str, u32) +} + +fn operate_qhy(target: &'static str, count: Option, mut free_frames: Receiver>, mut image_writer: Sender) { use crate::qhyccd::Control; println!("Operating on qhy camera ... or i'll die trying"); + let (mut camera_rx, mut camera_tx) = qhyccd::connect(0).unwrap(); + + let mut image_id = 0u32; + let mut settings_copy = qhyccd::Settings::default(); + + camera_tx.send(QHYMessage::SetControl(Control::Exposure, 20000000.0)).unwrap(); + camera_tx.send(QHYMessage::SetControl(Control::Gain, 4000.0)).unwrap(); + camera_tx.send(QHYMessage::SetControl(Control::Offset, 00.0)).unwrap(); + camera_tx.send(QHYMessage::SetControl(Control::Cooler, 27.0)).unwrap(); + camera_tx.send(QHYMessage::SetControl(Control::USBTraffic, 60.0)).unwrap(); + camera_tx.send(QHYMessage::SetControl(Control::Color, 0.0)).unwrap(); // disable color +// camera.set_roi(0, 0, 1920 * 2, 1080 * 2).unwrap(); +// println!("Gain: {:?}", camera.get_param_limits(Control::ManulPwm)); +// println!("cur pwm ???: {}", camera.get_param(Control::CurPWM)); + camera_tx.send(QHYMessage::BeginCapture).unwrap(); + + loop { + select! { + recv(free_frames) -> msg => { + match msg { + Ok(buffer) => { + camera_tx.send(QHYMessage::FrameAvailable(buffer)).unwrap(); + }, + Err(RecvError) => { + // disconnected. nothing we can do but to.. + return; + } + } + }, + recv(camera_rx) -> msg => { + match msg { + Ok(QHYResponse::CurrentControlValue(control, value)) => { + println!("Control {:?} value: {}", control, value); + } + Ok(QHYResponse::InitializationError) => { + println!("Failed to initialize camera, exiting..."); + return; + } + Ok(QHYResponse::Shutdown) => { + return; + } + Ok(QHYResponse::UpdatedSettings(settings)) => { + settings_copy = settings; + } + Ok(QHYResponse::Data(data, dimensions)) => { + image_writer.send(ImageInfo { data, dimensions, target, image_id: image_id }).unwrap(); + // images.log(target, image_id, settings_copy); + image_id += 1; + if Some(image_id) == count { + camera_tx.send(QHYMessage::Shutdown); + } + } + Ok(QHYResponse::DroppedFrame) => { + println!("Dropped frame..."); + } + Err(RecvError) => { + // camera is closed. hopefully it just shut down? but maybe crashed!! + return; + } + } + } + default(Duration::from_millis(2000)) => { + camera_tx.send( + QHYMessage::QueryControl(Control::CurTemp) + ); + } + } + } + /* let t = std::thread::spawn(move || { let mut camera = qhyccd::acquire(0).unwrap(); camera.set_defaults().unwrap(); @@ -52,6 +213,7 @@ fn operate_qhy(test: bool) { camera.release().unwrap(); }); t.join(); + */ } fn operate_asi(test: bool) { -- cgit v1.1