|
| 1 | +#ifndef IPS_SEQ_ITEM_VGA_HPP |
| 2 | +#define IPS_SEQ_ITEM_VGA_HPP |
| 3 | + |
| 4 | +#define int64 systemc_int64 |
| 5 | +#define uint64 systemc_uint64 |
| 6 | +#include <systemc.h> |
| 7 | +#include <systemc-ams.h> |
| 8 | +#undef int64 |
| 9 | +#undef uint64 |
| 10 | +#define int64 opencv_int64 |
| 11 | +#define uint64 opencv_uint64 |
| 12 | +#include <opencv2/opencv.hpp> |
| 13 | +#undef int64 |
| 14 | +#undef uint64 |
| 15 | + |
| 16 | +#include "vunit.hpp" |
| 17 | + |
| 18 | +// Image path |
| 19 | +#define IPS_IMG_PATH_TB "../../tools/datagen/src/imgs/car_rgb_noisy_image.jpg" |
| 20 | + |
| 21 | +/** |
| 22 | + * @brief This class is used to generate the data for the AMS test |
| 23 | + * |
| 24 | + * @tparam BITS - the number of output bits of the digital pixel |
| 25 | + * @tparam H_ACTIVE - output horizontal active video pixels |
| 26 | + * @tparam H_FP - wait after the display period before the sync |
| 27 | + * horizontal pulse |
| 28 | + * @tparam H_SYNC_PULSE - assert HSYNC |
| 29 | + * @tparam H_BP - wait after the sync horizontal pulse before starting |
| 30 | + * the next display period |
| 31 | + * @tparam V_ACTIVE - output vertical active video pixels |
| 32 | + * @tparam V_FP - wait after the display period before the sync |
| 33 | + * vertical pulse |
| 34 | + * @tparam V_SYNC_PULSE - assert VSYNC |
| 35 | + * @tparam V_BP - wait after the sync vertical pulse before starting |
| 36 | + * the next display period |
| 37 | + */ |
| 38 | +template < |
| 39 | + unsigned int BITS = 8, |
| 40 | + unsigned int H_ACTIVE = 640, |
| 41 | + unsigned int H_FP = 16, |
| 42 | + unsigned int H_SYNC_PULSE = 96, |
| 43 | + unsigned int H_BP = 48, |
| 44 | + unsigned int V_ACTIVE = 480, |
| 45 | + unsigned int V_FP = 10, |
| 46 | + unsigned int V_SYNC_PULSE = 2, |
| 47 | + unsigned int V_BP = 33, |
| 48 | + int VMIN = 0, |
| 49 | + int VMAX = 5, |
| 50 | + VUnit VU = VUnit::v> |
| 51 | +SCA_TDF_MODULE(seq_item_vga) |
| 52 | +{ |
| 53 | +protected: |
| 54 | + cv::Mat tx_img; |
| 55 | + // Min voltage value based on the voltage units |
| 56 | + const double V_MIN = static_cast<double>(VMIN) / static_cast<double>(VU); |
| 57 | + // Max voltage value based on the voltage units |
| 58 | + const double V_MAX = static_cast<double>(VMAX) / static_cast<double>(VU); |
| 59 | + // Max digital output code |
| 60 | + const double MAX_DIG = static_cast<double>((1 << BITS) - 1); |
| 61 | + |
| 62 | +public: |
| 63 | + // Counters |
| 64 | + sca_tdf::sca_de::sca_in<unsigned int> hcount; |
| 65 | + sca_tdf::sca_de::sca_in<unsigned int> vcount; |
| 66 | + // Output pixel |
| 67 | + sca_tdf::sca_out<double> o_red; |
| 68 | + sca_tdf::sca_out<double> o_green; |
| 69 | + sca_tdf::sca_out<double> o_blue; |
| 70 | + |
| 71 | + SC_CTOR(seq_item_vga) |
| 72 | + { |
| 73 | + // Read image |
| 74 | + const std::string img_path = IPS_IMG_PATH_TB; |
| 75 | + |
| 76 | + cv::Mat read_img = cv::imread(img_path, cv::IMREAD_COLOR); |
| 77 | + |
| 78 | + // CV_8UC3 Type: 8-bit unsigned, 3 channels (e.g., for a color image) |
| 79 | + read_img.convertTo(this->tx_img, CV_8UC3); |
| 80 | + |
| 81 | + // Check if the image is loaded successfully |
| 82 | + if (this->tx_img.empty()) |
| 83 | + { |
| 84 | + std::cerr << "Error: Could not open or find the image!" << std::endl; |
| 85 | + exit(EXIT_FAILURE); |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + void set_attributes() |
| 90 | + { |
| 91 | + // Propagation time from input to output |
| 92 | + set_timestep(sca_core::sca_time(1, sc_core::SC_NS)); |
| 93 | + this->o_red.set_delay(17); |
| 94 | + this->o_green.set_delay(17); |
| 95 | + this->o_blue.set_delay(17); |
| 96 | + } |
| 97 | + |
| 98 | + void processing() |
| 99 | + { |
| 100 | + const int IMG_ROW = static_cast<int>(this->vcount.read()) - (V_SYNC_PULSE + V_BP); |
| 101 | + const int IMG_COL = static_cast<int>(this->hcount.read()) - (H_SYNC_PULSE + H_BP); |
| 102 | + |
| 103 | + if ((IMG_ROW < 0) || (IMG_COL < 0) || (IMG_ROW >= static_cast<int>(V_ACTIVE)) || (IMG_COL >= static_cast<int>(H_ACTIVE))) |
| 104 | + { |
| 105 | + this->o_red.write(0.0); |
| 106 | + this->o_green.write(0.0); |
| 107 | + this->o_blue.write(0.0); |
| 108 | + } |
| 109 | + else |
| 110 | + { |
| 111 | + if ((IMG_ROW >= this->tx_img.rows) || (IMG_COL >= this->tx_img.cols)) |
| 112 | + { |
| 113 | + this->o_red.write(0.0); |
| 114 | + this->o_green.write(0.0); |
| 115 | + this->o_blue.write(0.0); |
| 116 | + } |
| 117 | + else |
| 118 | + { |
| 119 | + cv::Vec3b pixel = tx_img.at<cv::Vec3b>(IMG_ROW, IMG_COL, 0); |
| 120 | + |
| 121 | + this->o_red.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[0]))); |
| 122 | + this->o_green.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[1]))); |
| 123 | + this->o_blue.write(sc_uint2double(static_cast<sc_uint<BITS>>(pixel[2]))); |
| 124 | + } |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * @brief Convert the digital signal into analog signal |
| 130 | + * The N-bit digital code is converted into an analog signal in a voltage |
| 131 | + * range from Vmin to Vmax |
| 132 | + */ |
| 133 | + double sc_uint2double(sc_uint<BITS> in) |
| 134 | + { |
| 135 | + double dig_in = static_cast<double>(in); |
| 136 | + return V_MIN + (dig_in / MAX_DIG) * (V_MAX - V_MIN); |
| 137 | + } |
| 138 | +}; |
| 139 | +#endif // IPS_SEQ_ITEM_VGA_HPP |
0 commit comments