차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
| linuxpc:buzzer:index [2026/06/09 14:50] – created admin | linuxpc:buzzer:index [2026/06/09 23:03] (현재) – admin | ||
|---|---|---|---|
| 줄 26: | 줄 26: | ||
| [[https:// | [[https:// | ||
| + | ++++[소스 코드]| | ||
| <code C#> | <code C#> | ||
| - | (원본 코드 그대로) </ | + | using System; |
| + | using System.IO; | ||
| + | using System.Runtime.InteropServices; | ||
| + | using System.Threading; | ||
| + | |||
| + | class Siren | ||
| + | { | ||
| + | static void Main(string[] args) | ||
| + | { | ||
| + | Console.CancelKeyPress += (sender, e) => | ||
| + | { | ||
| + | e.Cancel = true; | ||
| + | exiting = true; | ||
| + | Console.WriteLine(" | ||
| + | }; | ||
| + | |||
| + | const string eventPath = "/ | ||
| + | |||
| + | Console.WriteLine(" | ||
| + | |||
| + | double time = 0; | ||
| + | double step = 0.02; // 50 Hz update rate (20ms) | ||
| + | |||
| + | FileStream? fs = null; | ||
| + | |||
| + | try | ||
| + | { | ||
| + | fs = new FileStream(eventPath, | ||
| + | |||
| + | while (!exiting) | ||
| + | { | ||
| + | // Siren: 500 Hz to 1500 Hz and back in 2 seconds | ||
| + | double cycleTime = time % 2.0; | ||
| + | double frequency; | ||
| + | |||
| + | if (cycleTime < 1.0) | ||
| + | frequency = 500 + (cycleTime * 1000); | ||
| + | else | ||
| + | frequency = 1500 - ((cycleTime - 1.0) * 1000); // Fall | ||
| + | |||
| + | int hz = (int)Math.Round(frequency); | ||
| + | |||
| + | SendTone(fs, | ||
| + | |||
| + | Thread.Sleep((int)(step * 1000)); | ||
| + | time += step; | ||
| + | } | ||
| + | } | ||
| + | catch (Exception ex) | ||
| + | { | ||
| + | Console.Error.WriteLine(ex.Message); | ||
| + | } | ||
| + | finally | ||
| + | { | ||
| + | // Ensure buzzer is silenced | ||
| + | try | ||
| + | { | ||
| + | if (fs != null) | ||
| + | { | ||
| + | SendTone(fs, | ||
| + | fs.Dispose(); | ||
| + | } | ||
| + | } | ||
| + | catch (Exception ex) | ||
| + | { | ||
| + | Console.Error.WriteLine(ex.Message); | ||
| + | } | ||
| + | |||
| + | Console.WriteLine(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Linux input event constants | ||
| + | const ushort EV_SYN = 0x00; | ||
| + | const ushort EV_SND = 0x12; | ||
| + | const ushort SYN_REPORT = 0x00; | ||
| + | const ushort SND_BELL = 0x01; | ||
| + | const ushort SND_TONE = 0x02; | ||
| + | |||
| + | static bool exiting = false; | ||
| + | |||
| + | // input_event struct from < | ||
| + | // struct timeval { long tv_sec; long tv_usec; }; | ||
| + | // struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; }; | ||
| + | [StructLayout(LayoutKind.Sequential)] | ||
| + | struct TimeVal | ||
| + | { | ||
| + | public long tv_sec; | ||
| + | public long tv_usec; | ||
| + | } | ||
| + | |||
| + | [StructLayout(LayoutKind.Sequential)] | ||
| + | struct InputEvent | ||
| + | { | ||
| + | public TimeVal time; | ||
| + | public ushort type; | ||
| + | public ushort code; | ||
| + | public int value; | ||
| + | } | ||
| + | |||
| + | // Compute once to avoid repeated reflection-ish cost | ||
| + | static readonly int InputEventSize = Marshal.SizeOf< | ||
| + | |||
| + | static void SendTone(FileStream fs, int hz) | ||
| + | { | ||
| + | // hz > 0 => play tone at hz | ||
| + | // hz == 0 => stop tone | ||
| + | WriteEvent(fs, | ||
| + | WriteEvent(fs, | ||
| + | fs.Flush(); | ||
| + | } | ||
| + | |||
| + | static void WriteEvent(FileStream fs, ushort type, ushort code, int value) | ||
| + | { | ||
| + | // Local struct lives on the stack (no heap allocation) | ||
| + | InputEvent ev = new InputEvent | ||
| + | { | ||
| + | time = default, // kernel will timestamp; zeroed is fine | ||
| + | type = type, | ||
| + | code = code, | ||
| + | value = value | ||
| + | }; | ||
| + | |||
| + | // Stack-allocated byte buffer | ||
| + | Span< | ||
| + | |||
| + | // Copy struct bytes into the stack buffer | ||
| + | MemoryMarshal.Write(buffer, | ||
| + | |||
| + | // Write without allocating | ||
| + | fs.Write(buffer); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | ++++ | ||
| [[..: | [[..: | ||
