using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using Echo.Core.Common.Packed; using Echo.UserInterface.Backend; using ImGuiNET; using SDL2; using testdrid.SdlWrapper; namespace SDL2Demo.Forms { internal class IqWindow : IRenderable { private readonly Renderer _renderer; private readonly Texture _texture; private readonly bool imgui; private readonly Vector2 _imguiVector; private bool noDraw; public void ResetIqGraphic() { noDraw = true; iqData = new byte[256][]; for (int i = 0; i < iqData.Length; i++) { iqData[i] = new byte[256]; } noDraw = false; } public IqWindow(Renderer renderer) { ResetIqGraphic(); _renderer = renderer; _texture = Texture.Create(_renderer, SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 256); _texture.SetDrawBlendMode(SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); imgui = false; } public IqWindow(ImGuiDevice imGuiDevice) { ResetIqGraphic(); IntPtr textureIntPtr = imGuiDevice.CreateTexture(new Int2(256, 256), true, !BitConverter.IsLittleEndian); _texture = Texture.FromIntPointer(textureIntPtr); _renderer = null; _imguiVector = new Vector2(256, 256); imgui = true; } private byte[][] iqData; private ulong iqErrors; public Point RenderOffset { get; set; } public void PushIqSample(byte i, byte q) { if (iqData[i][q] == byte.MaxValue) return; iqData[i][q]++; } private void RenderInternal() { if (noDraw) return; byte b = 0; try { for (int y = 0; y < iqData.Length; y++) { if (noDraw) return; for (int x = 0; x < iqData[y].Length; x++) { if (noDraw) return; b = iqData[y][x]; if (b != 0) _texture.SetPixel(x, y, 255, (byte)(255 - b), 0, 0); else _texture.SetPixel(x, y, 0, 0, 0, 0); } } } catch (NullReferenceException e) { iqErrors++; } } public void Render() { _texture.Lock(); RenderInternal(); _texture.Unlock(); if (imgui) { ImGui.PushStyleVar(ImGuiStyleVar.WindowMinSize, 256); ImGui.Begin("IQ", ImGuiWindowFlags.NoResize); ImGui.Image(_texture.Pointer, _imguiVector); ImGui.End(); } else { _renderer.Copy(_texture, RenderOffset); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void PushIqSamples(sbyte[] iqBuffer) { byte i, q; for (int idx = 0; idx < iqBuffer.Length; idx += 2) { i = (byte)(int)(iqBuffer[idx + 0] + sbyte.MaxValue); q = (byte)(int)(iqBuffer[idx + 1] + sbyte.MaxValue); PushIqSample(i, q); } } } }