Skip to content

Commit

Permalink
rayon_demo - coordinate transformation fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
RainerZ committed Jul 31, 2024
1 parent 71fafc4 commit c9e0254
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 64 deletions.
8 changes: 2 additions & 6 deletions examples/rayon_demo/mandelbrot.a2l
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
/end MEMORY_SEGMENT

/begin MEMORY_SEGMENT
mandelbrot "" DATA FLASH INTERN 0x80010000 32 -1 -1 -1 -1 -1
mandelbrot "" DATA FLASH INTERN 0x80010000 24 -1 -1 -1 -1 -1
/begin IF_DATA XCP
/begin SEGMENT /* index: */ 1 /* pages: */ 2 /* ext: */ 0 0 0
/begin CHECKSUM XCP_ADD_44 MAX_BLOCK_SIZE 0xFFFF EXTERNAL_FUNCTION "" /end CHECKSUM
Expand Down Expand Up @@ -130,21 +130,17 @@

/end DAQ

/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "192.168.0.83" /end XCP_ON_UDP_IP
/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "127.0.0.1" /end XCP_ON_UDP_IP

/end IF_DATA

/begin CHARACTERISTIC Mandelbrot.width "" VALUE 0x80010010 F64 0 NO_COMPU_METHOD -1000000000000 1000000000000 /end CHARACTERISTIC
/begin CHARACTERISTIC Mandelbrot.x "" VALUE 0x80010000 F64 0 NO_COMPU_METHOD -1000000000000 1000000000000 /end CHARACTERISTIC
/begin CHARACTERISTIC Mandelbrot.x_pixels "" VALUE 0x80010018 U32 0 NO_COMPU_METHOD 0 4294967295 /end CHARACTERISTIC
/begin CHARACTERISTIC Mandelbrot.y "" VALUE 0x80010008 F64 0 NO_COMPU_METHOD -1000000000000 1000000000000 /end CHARACTERISTIC
/begin CHARACTERISTIC Mandelbrot.y_pixels "" VALUE 0x8001001C U32 0 NO_COMPU_METHOD 0 4294967295 /end CHARACTERISTIC
/begin GROUP mandelbrot "" /begin REF_CHARACTERISTIC
Mandelbrot.width
Mandelbrot.x
Mandelbrot.x_pixels
Mandelbrot.y
Mandelbrot.y_pixels
/end REF_CHARACTERISTIC /end GROUP

/begin COMPU_METHOD elapsed_time.Conv "" LINEAR "%6.3" "s" COEFFS_LINEAR 1 0 /end COMPU_METHOD
Expand Down
Binary file modified examples/rayon_demo/mandelbrot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 55 additions & 57 deletions examples/rayon_demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,51 @@ use log::{debug, error, info, trace, warn};
use image::{ImageBuffer, Rgb};
use num::Complex;
use rayon::prelude::*;
//use std::usize;
use std::{thread, time::Duration};

use serde::{Deserialize, Serialize};
use xcp::*;
use xcp_type_description_derive::XcpTypeDescription;

/// Write the buffer `pixels`, whose dimensions are given by `bounds`, to the
/// file named `filename`.
fn write_image(
filename: &str,
pixels: &[u8],
mandelbrot: CalSeg<Mandelbrot>,
) -> Result<(), std::io::Error> {
const X_RES: usize = 3000;
const Y_RES: usize = 2000;

#[derive(Debug, Copy, Clone, Serialize, Deserialize, XcpTypeDescription)]
struct Mandelbrot {
x: f64,
y: f64,
width: f64,
}

// const MANDELBROT: Mandelbrot = Mandelbrot {
// x: -1.06,
// y: 0.271,
// width: 0.023,
// };

// Complete set
const MANDELBROT: Mandelbrot = Mandelbrot {
x: -0.5,
y: 0.0,
width: 3.0,
};

//---------------------------------------------------------------------------------------
// Image rendering

/// Write the buffer `pixels`, whose dimensions are given by `bounds`, to the file named `filename`.
fn write_image(filename: &str, pixels: &[u8]) -> Result<(), std::io::Error> {
// Black and white
// let output = File::create(filename)?;
// let encoder = PNGEncoder::new(output);
// encoder.encode(
// &pixels,
// mandelbrot.x_pixels as u32,
// mandelbrot.y_pixels as u32,
// X_RES as u32,
// Y_RES as u32,
// ColorType::Gray(8),
// )?;

// Rainbox color map (credits to CoPilot)
let mut color_map = Vec::with_capacity(256);
for i in 0..256 {
let (r, g, b) = match i {
Expand All @@ -49,10 +70,9 @@ fn write_image(
}

// Color
let mut imgbuf = ImageBuffer::new(mandelbrot.x_pixels as u32, mandelbrot.y_pixels as u32);
let mut imgbuf = ImageBuffer::new(X_RES as u32, Y_RES as u32);
for (x, y, rgb_pixel) in imgbuf.enumerate_pixels_mut() {
*rgb_pixel =
color_map[pixels[y as usize * mandelbrot.x_pixels as usize + x as usize] as usize];
*rgb_pixel = color_map[pixels[y as usize * X_RES as usize + x as usize] as usize];
}
imgbuf.save(filename).unwrap();

Expand All @@ -62,23 +82,6 @@ fn write_image(
//---------------------------------------------------------------------------------------
// Mandelbrot set

#[derive(Debug, Copy, Clone, Serialize, Deserialize, XcpTypeDescription)]
struct Mandelbrot {
x_pixels: u32,
y_pixels: u32,
x: f64,
y: f64,
width: f64,
}

const MANDELBROT: Mandelbrot = Mandelbrot {
x_pixels: 3000,
y_pixels: 2000,
x: -1.06,
y: 0.271,
width: 0.022,
};

/// Try to determine if `c` is in the Mandelbrot set, using at most `limit`
/// iterations to decide.
///
Expand Down Expand Up @@ -107,7 +110,6 @@ fn escape_time(c: Complex<f64>, limit: usize) -> Option<usize> {
/// The `upper_left` and `lower_right` parameters are points on the complex
/// plane designating the area our image covers.
fn pixel_to_point(
bounds: (usize, usize),
pixel: (usize, usize),
upper_left: Complex<f64>,
lower_right: Complex<f64>,
Expand All @@ -117,9 +119,8 @@ fn pixel_to_point(
upper_left.im - lower_right.im,
);
Complex {
re: upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,
im: upper_left.im - pixel.1 as f64 * height / bounds.1 as f64, // Why subtraction here? pixel.1 increases as we go down,
// but the imaginary component increases as we go up.
re: upper_left.re + pixel.0 as f64 * width / X_RES as f64,
im: upper_left.im - pixel.1 as f64 * height / Y_RES as f64,
}
}

Expand All @@ -140,7 +141,7 @@ fn render(

// Render line
for column in 0..length {
let point = pixel_to_point((length, 1), (column, row), upper_left, lower_right);
let point = pixel_to_point((column, row), upper_left, lower_right);
pixels[column] = match escape_time(point, 255) {
None => 0,
Some(count) => 255 - count as u8,
Expand All @@ -161,7 +162,7 @@ fn main() {
.filter_level(log::LevelFilter::Info)
.init();

const BIND_ADDR: [u8; 4] = [192, 168, 0, 83]; // [127, 0, 0, 1]
const BIND_ADDR: [u8; 4] = [127, 0, 0, 1]; // [192, 168, 0, 83]; // [127, 0, 0, 1];
XcpBuilder::new("mandelbrot")
.set_log_level(XcpLogLevel::Info)
.enable_a2l(true)
Expand All @@ -171,6 +172,10 @@ fn main() {

let mandelbrot = Xcp::create_calseg("mandelbrot", &MANDELBROT, true);

// The pixel array on stack would overflow the addr offset
// let mut pixels: [u8; X_RES * Y_RES] = [0; X_RES * Y_RES];
let mut pixels = vec![0; X_RES * Y_RES];

// Create event for this worker thread and register variable index, which is the upper left corner of the rectangle
let event = daq_create_event!("mainloop");
let mut elapsed_time: f64 = 0.0;
Expand All @@ -182,40 +187,33 @@ fn main() {
thread::sleep(Duration::from_micros(1000));
let start_time = std::time::Instant::now();

let x_pixels: usize = mandelbrot.x_pixels as usize;
let y_pixels: usize = mandelbrot.y_pixels as usize;
let lower_right = Complex {
re: mandelbrot.x - mandelbrot.width / 2.0,
im: mandelbrot.y - mandelbrot.width / 2.0 * y_pixels as f64 / x_pixels as f64,
re: mandelbrot.x + mandelbrot.width / 2.0,
im: mandelbrot.y - mandelbrot.width / 2.0 * Y_RES as f64 / X_RES as f64,
};
let upper_left = Complex {
re: mandelbrot.x + mandelbrot.width / 2.0,
im: mandelbrot.y + mandelbrot.width / 2.0 * y_pixels as f64 / x_pixels as f64,
re: mandelbrot.x - mandelbrot.width / 2.0,
im: mandelbrot.y + mandelbrot.width / 2.0 * Y_RES as f64 / X_RES as f64,
};

// Calculate image by lines in parallel
let mut pixels = vec![0; x_pixels * y_pixels];
let lines: Vec<(usize, &mut [u8])> = pixels.chunks_mut(x_pixels).enumerate().collect();
// Calculate image lines in parallel
let lines: Vec<(usize, &mut [u8])> = pixels.chunks_mut(X_RES).enumerate().collect();
lines.into_par_iter().for_each(|(y, band)| {
let band_upper_left =
pixel_to_point((x_pixels, y_pixels), (0, y), upper_left, lower_right);
let band_lower_right = pixel_to_point(
(x_pixels, y_pixels),
(x_pixels, y + 1),
upper_left,
lower_right,
);
render(band, y, x_pixels, band_upper_left, band_lower_right);
let band_upper_left = pixel_to_point((0, y), upper_left, lower_right);
let band_lower_right = pixel_to_point((X_RES, y + 1), upper_left, lower_right);
render(band, y, X_RES, band_upper_left, band_lower_right);
});

// Measure runtime
// Measure run time
elapsed_time = start_time.elapsed().as_secs_f64();
event.trigger();
println!("Image rendered, duration = {:.3} s", elapsed_time);

// Measure the pixel array from heap, with an individual event
//daq_event!(pixels, "pixels");

// Render image to png
let m = mandelbrot.clone();
write_image("mandelbrot.png", &pixels, m).expect("error writing PNG file");
write_image("mandelbrot.png", &pixels).expect("error writing PNG file");
println!("Image written to mandelbrot.png");

// Write A2L file
Expand Down
4 changes: 3 additions & 1 deletion xcp_client/src/xcp_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,9 @@ impl XcpClient {
}
}
None => {
panic!("xcp_command: bug in receive_task, no data in channel")
// @@@@ Empty response, channel has been closed, return with XcpError Timeout
error!("xcp_command: receive_task channel closed");
Err(Box::new(XcpError::new(ERROR_CMD_TIMEOUT)) as Box<dyn Error>)
}
}
}
Expand Down

0 comments on commit c9e0254

Please sign in to comment.