summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/hid/irs.cpp2
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.cpp16
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.h9
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.cpp2
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.cpp123
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.h34
6 files changed, 169 insertions, 17 deletions
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index 221c33b86..d383a266d 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -138,7 +138,7 @@ void IRS::RunMomentProcessor(HLERequestContext& ctx) {
138 138
139 if (result.IsSuccess()) { 139 if (result.IsSuccess()) {
140 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); 140 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
141 MakeProcessor<MomentProcessor>(parameters.camera_handle, device); 141 MakeProcessorWithCoreContext<MomentProcessor>(parameters.camera_handle, device);
142 auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle); 142 auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
143 image_transfer_processor.SetConfig(parameters.processor_config); 143 image_transfer_processor.SetConfig(parameters.processor_config);
144 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 144 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp
index e2f4ae876..c559eb0d5 100644
--- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp
@@ -3,16 +3,18 @@
3 3
4#include <queue> 4#include <queue>
5 5
6#include "core/core.h"
7#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h" 8#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h" 9#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/irsensor/clustering_processor.h" 10#include "core/hle/service/hid/irsensor/clustering_processor.h"
9 11
10namespace Service::IRS { 12namespace Service::IRS {
11ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_, 13ClusteringProcessor::ClusteringProcessor(Core::System& system_,
12 Core::IrSensor::DeviceFormat& device_format, 14 Core::IrSensor::DeviceFormat& device_format,
13 std::size_t npad_index) 15 std::size_t npad_index)
14 : device{device_format} { 16 : device{device_format}, system{system_} {
15 npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); 17 npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
16 18
17 device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; 19 device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
18 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; 20 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
@@ -48,7 +50,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
48 } 50 }
49 51
50 next_state = {}; 52 next_state = {};
51 const auto camera_data = npad_device->GetCamera(); 53 const auto& camera_data = npad_device->GetCamera();
52 auto filtered_image = camera_data.data; 54 auto filtered_image = camera_data.data;
53 55
54 RemoveLowIntensityData(filtered_image); 56 RemoveLowIntensityData(filtered_image);
@@ -83,7 +85,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
83 } 85 }
84 86
85 next_state.sampling_number = camera_data.sample; 87 next_state.sampling_number = camera_data.sample;
86 next_state.timestamp = next_state.timestamp + 131; 88 next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
87 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; 89 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
88 shared_memory->clustering_lifo.WriteNextEntry(next_state); 90 shared_memory->clustering_lifo.WriteNextEntry(next_state);
89 91
@@ -202,14 +204,14 @@ ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster(
202} 204}
203 205
204u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { 206u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
205 if ((y * width) + x > data.size()) { 207 if ((y * width) + x >= data.size()) {
206 return 0; 208 return 0;
207 } 209 }
208 return data[(y * width) + x]; 210 return data[(y * width) + x];
209} 211}
210 212
211void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { 213void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) {
212 if ((y * width) + x > data.size()) { 214 if ((y * width) + x >= data.size()) {
213 return; 215 return;
214 } 216 }
215 data[(y * width) + x] = value; 217 data[(y * width) + x] = value;
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h
index dc01a8ea7..83f34734a 100644
--- a/src/core/hle/service/hid/irsensor/clustering_processor.h
+++ b/src/core/hle/service/hid/irsensor/clustering_processor.h
@@ -8,6 +8,10 @@
8#include "core/hle/service/hid/irs_ring_lifo.h" 8#include "core/hle/service/hid/irs_ring_lifo.h"
9#include "core/hle/service/hid/irsensor/processor_base.h" 9#include "core/hle/service/hid/irsensor/processor_base.h"
10 10
11namespace Core {
12class System;
13}
14
11namespace Core::HID { 15namespace Core::HID {
12class EmulatedController; 16class EmulatedController;
13} // namespace Core::HID 17} // namespace Core::HID
@@ -15,8 +19,7 @@ class EmulatedController;
15namespace Service::IRS { 19namespace Service::IRS {
16class ClusteringProcessor final : public ProcessorBase { 20class ClusteringProcessor final : public ProcessorBase {
17public: 21public:
18 explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_, 22 explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
19 Core::IrSensor::DeviceFormat& device_format,
20 std::size_t npad_index); 23 std::size_t npad_index);
21 ~ClusteringProcessor() override; 24 ~ClusteringProcessor() override;
22 25
@@ -106,5 +109,7 @@ private:
106 Core::IrSensor::DeviceFormat& device; 109 Core::IrSensor::DeviceFormat& device;
107 Core::HID::EmulatedController* npad_device; 110 Core::HID::EmulatedController* npad_device;
108 int callback_key{}; 111 int callback_key{};
112
113 Core::System& system;
109}; 114};
110} // namespace Service::IRS 115} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
index 803a6277c..22067a591 100644
--- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
@@ -49,7 +49,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
49 return; 49 return;
50 } 50 }
51 51
52 const auto camera_data = npad_device->GetCamera(); 52 const auto& camera_data = npad_device->GetCamera();
53 53
54 // This indicates how much ambient light is present 54 // This indicates how much ambient light is present
55 processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; 55 processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp
index dbaca420a..cf045bda7 100644
--- a/src/core/hle/service/hid/irsensor/moment_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/moment_processor.cpp
@@ -1,24 +1,137 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "core/core.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h"
4#include "core/hle/service/hid/irsensor/moment_processor.h" 8#include "core/hle/service/hid/irsensor/moment_processor.h"
5 9
6namespace Service::IRS { 10namespace Service::IRS {
7MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format) 11static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30;
8 : device(device_format) { 12static constexpr std::size_t ImageWidth = 40;
13static constexpr std::size_t ImageHeight = 30;
14
15MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
16 std::size_t npad_index)
17 : device(device_format), system{system_} {
18 npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
19
9 device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; 20 device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
10 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; 21 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
11 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; 22 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped;
23
24 shared_memory = std::construct_at(
25 reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data));
26
27 Core::HID::ControllerUpdateCallback engine_callback{
28 .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
29 .is_npad_service = true,
30 };
31 callback_key = npad_device->SetCallback(engine_callback);
12} 32}
13 33
14MomentProcessor::~MomentProcessor() = default; 34MomentProcessor::~MomentProcessor() {
35 npad_device->DeleteCallback(callback_key);
36};
15 37
16void MomentProcessor::StartProcessor() {} 38void MomentProcessor::StartProcessor() {
39 device.camera_status = Core::IrSensor::IrCameraStatus::Available;
40 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready;
41}
17 42
18void MomentProcessor::SuspendProcessor() {} 43void MomentProcessor::SuspendProcessor() {}
19 44
20void MomentProcessor::StopProcessor() {} 45void MomentProcessor::StopProcessor() {}
21 46
47void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) {
48 if (type != Core::HID::ControllerTriggerType::IrSensor) {
49 return;
50 }
51
52 next_state = {};
53 const auto& camera_data = npad_device->GetCamera();
54
55 const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width);
56 const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height);
57 const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x);
58 const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y);
59
60 const std::size_t block_width = window_width / Columns;
61 const std::size_t block_height = window_height / Rows;
62
63 for (std::size_t row = 0; row < Rows; row++) {
64 for (std::size_t column = 0; column < Columns; column++) {
65 const size_t x_pos = (column * block_width) + window_start_x;
66 const size_t y_pos = (row * block_height) + window_start_y;
67 auto& statistic = next_state.statistic[column + (row * Columns)];
68 statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height);
69 }
70 }
71
72 next_state.sampling_number = camera_data.sample;
73 next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
74 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
75 shared_memory->moment_lifo.WriteNextEntry(next_state);
76
77 if (!IsProcessorActive()) {
78 StartProcessor();
79 }
80}
81
82u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
83 if ((y * ImageWidth) + x >= data.size()) {
84 return 0;
85 }
86 return data[(y * ImageWidth) + x];
87}
88
89MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data,
90 std::size_t start_x,
91 std::size_t start_y,
92 std::size_t width,
93 std::size_t height) const {
94 // The actual implementation is always 320x240
95 static constexpr std::size_t RealWidth = 320;
96 static constexpr std::size_t RealHeight = 240;
97 static constexpr std::size_t Threshold = 30;
98 MomentStatistic statistic{};
99 std::size_t active_points{};
100
101 // Sum all data points on the block that meet with the threshold
102 for (std::size_t y = 0; y < width; y++) {
103 for (std::size_t x = 0; x < height; x++) {
104 const size_t x_pos = x + start_x;
105 const size_t y_pos = y + start_y;
106 const auto pixel =
107 GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight);
108
109 if (pixel < Threshold) {
110 continue;
111 }
112
113 statistic.average_intensity += pixel;
114
115 statistic.centroid.x += static_cast<float>(x_pos);
116 statistic.centroid.y += static_cast<float>(y_pos);
117
118 active_points++;
119 }
120 }
121
122 // Return an empty field if no points were available
123 if (active_points == 0) {
124 return {};
125 }
126
127 // Finally calculate the actual centroid and average intensity
128 statistic.centroid.x /= static_cast<float>(active_points);
129 statistic.centroid.y /= static_cast<float>(active_points);
130 statistic.average_intensity /= static_cast<f32>(width * height);
131
132 return statistic;
133}
134
22void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { 135void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
23 current_config.camera_config.exposure_time = config.camera_config.exposure_time; 136 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
24 current_config.camera_config.gain = config.camera_config.gain; 137 current_config.camera_config.gain = config.camera_config.gain;
@@ -29,6 +142,8 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
29 current_config.preprocess = 142 current_config.preprocess =
30 static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); 143 static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
31 current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; 144 current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
145
146 npad_device->SetCameraFormat(format);
32} 147}
33 148
34} // namespace Service::IRS 149} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h
index d4bd22e0f..398cfbdc1 100644
--- a/src/core/hle/service/hid/irsensor/moment_processor.h
+++ b/src/core/hle/service/hid/irsensor/moment_processor.h
@@ -6,12 +6,22 @@
6#include "common/bit_field.h" 6#include "common/bit_field.h"
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hid/irs_types.h" 8#include "core/hid/irs_types.h"
9#include "core/hle/service/hid/irs_ring_lifo.h"
9#include "core/hle/service/hid/irsensor/processor_base.h" 10#include "core/hle/service/hid/irsensor/processor_base.h"
10 11
12namespace Core {
13class System;
14}
15
16namespace Core::HID {
17class EmulatedController;
18} // namespace Core::HID
19
11namespace Service::IRS { 20namespace Service::IRS {
12class MomentProcessor final : public ProcessorBase { 21class MomentProcessor final : public ProcessorBase {
13public: 22public:
14 explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format); 23 explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
24 std::size_t npad_index);
15 ~MomentProcessor() override; 25 ~MomentProcessor() override;
16 26
17 // Called when the processor is initialized 27 // Called when the processor is initialized
@@ -27,6 +37,9 @@ public:
27 void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); 37 void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config);
28 38
29private: 39private:
40 static constexpr std::size_t Columns = 8;
41 static constexpr std::size_t Rows = 6;
42
30 // This is nn::irsensor::MomentProcessorConfig 43 // This is nn::irsensor::MomentProcessorConfig
31 struct MomentProcessorConfig { 44 struct MomentProcessorConfig {
32 Core::IrSensor::CameraConfig camera_config; 45 Core::IrSensor::CameraConfig camera_config;
@@ -50,12 +63,29 @@ private:
50 u64 timestamp; 63 u64 timestamp;
51 Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; 64 Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
52 INSERT_PADDING_BYTES(4); 65 INSERT_PADDING_BYTES(4);
53 std::array<MomentStatistic, 0x30> stadistic; 66 std::array<MomentStatistic, Columns * Rows> statistic;
54 }; 67 };
55 static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); 68 static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size");
56 69
70 struct MomentSharedMemory {
71 Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo;
72 };
73 static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size");
74
75 void OnControllerUpdate(Core::HID::ControllerTriggerType type);
76 u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const;
77 MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x,
78 std::size_t start_y, std::size_t width, std::size_t height) const;
79
80 MomentSharedMemory* shared_memory = nullptr;
81 MomentProcessorState next_state{};
82
57 MomentProcessorConfig current_config{}; 83 MomentProcessorConfig current_config{};
58 Core::IrSensor::DeviceFormat& device; 84 Core::IrSensor::DeviceFormat& device;
85 Core::HID::EmulatedController* npad_device;
86 int callback_key{};
87
88 Core::System& system;
59}; 89};
60 90
61} // namespace Service::IRS 91} // namespace Service::IRS