====== 부저 ====== jPC에는 SoC의 PWM 출력에 연결된 전자식 부저(Electro-Mechanical Buzzer)가 내장되어 있습니다. ===== 터미널에서 부저 울리기 ===== [[https://manpages.debian.org/trixie/beep/beep.1.en.html|beep]] 프로그램을 사용하여 원하는 주파수와 시간으로 부저음을 발생시킬 수 있습니다. 예를 들어 2kHz 주파수의 소리를 100ms 동안 출력하려면 다음과 같이 실행합니다. beep -f 2000 -l 100 * ''-f'' : 주파수(Hz) * ''-l'' : 지속 시간(ms) ===== 프로그램에서 부저 제어하기 ===== 프로그램에서는 ''/dev/input/by-path/platform-buzzer-event'' 장치에 ''EV_SND'' 이벤트를 전송하여 부저를 제어할 수 있습니다. 아래 예제는 부저의 주파수를 지속적으로 변경하여 사이렌 효과를 발생시키는 프로그램입니다. 자세한 내용은 Linux Input Subsystem 문서를 참고하십시오. [[https://www.kernel.org/doc/html/latest/input/input_uapi.html|Linux Input Subsystem]] ++++[소스 코드]| 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("\nCtrl+C received. Stopping siren..."); }; const string eventPath = "/dev/input/by-path/platform-buzzer-event"; Console.WriteLine("Siren generator running. Press Ctrl+C to stop."); double time = 0; double step = 0.02; // 50 Hz update rate (20ms) FileStream? fs = null; try { fs = new FileStream(eventPath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite); 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); // Rise else frequency = 1500 - ((cycleTime - 1.0) * 1000); // Fall int hz = (int)Math.Round(frequency); SendTone(fs, hz); 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, 0); fs.Dispose(); } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); } Console.WriteLine("Siren stopped."); } } // 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, EV_SND, SND_TONE, hz); WriteEvent(fs, EV_SYN, SYN_REPORT, 0); 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 buffer = stackalloc byte[InputEventSize]; // Copy struct bytes into the stack buffer MemoryMarshal.Write(buffer, in ev); // Write without allocating fs.Write(buffer); } } ++++ [[..:index|JPC (임베디드 리눅스 Panel PC)]]