FluxSand 1.0
FluxSand - Interactive Digital Hourglass
Loading...
Searching...
No Matches
bsp_pwm.hpp
1#pragma once
2
3#include <unistd.h>
4
5#include <cmath>
6#include <cstdint>
7#include <cstdio>
8#include <semaphore>
9#include <string>
10#include <thread>
11
21class PWM {
22 public:
26 // NOLINTNEXTLINE
27 enum class NoteName { C = 0, Cs, D, Ds, E, F, Fs, G, Gs, A, As, B };
28
37 PWM(int channel, int frequency_hz = 1000, float duty_percent = 0.0f,
38 int chip = 2)
39 : channel_(channel), period_ns_(static_cast<int>(1e9 / frequency_hz)) {
40 chip_path_ = "/sys/class/pwm/pwmchip" + std::to_string(chip);
41 pwm_path_ = chip_path_ + "/pwm" + std::to_string(channel);
42
43 // Export the PWM channel if it has not been exported yet.
44 if (access(pwm_path_.c_str(), F_OK) != 0) {
45 FILE* fp = fopen((chip_path_ + "/export").c_str(), "w");
46 if (fp) {
47 (void)(fprintf(fp, "%d", channel));
48 (void)(fclose(fp));
49 usleep(100000); // Allow sysfs to initialize.
50 }
51 }
52
53 WriteSysfs(pwm_path_ + "/period", period_ns_);
54 SetDutyCycle(duty_percent);
55 Enable();
56
57 // Launch background thread to play notes asynchronously.
58 note_thread_ = std::thread([this]() {
59 while (true) {
60 note_sem_.acquire();
61 float midi = static_cast<float>(note_) +
62 (static_cast<float>(octave_) + 1.0f) * 12.0f;
63 float freq = 440.0f * std::pow(2.0f, (midi - 69.0f) / 12.0f);
64 Beep(static_cast<uint32_t>(freq), duration_ms_);
65 }
66 });
67 }
68
72 ~PWM() { Disable(); }
73
78 void SetFrequency(uint32_t hz) {
79 period_ns_ = static_cast<int>(1e9 / hz);
80 WriteSysfs(pwm_path_ + "/period", period_ns_);
81 }
82
87 void SetDutyCycle(float percent) {
88 int duty_ns = static_cast<int>(percent * static_cast<float>(period_ns_));
89 WriteSysfs(pwm_path_ + "/duty_cycle", duty_ns);
90 }
91
95 void Enable() { WriteSysfs(pwm_path_ + "/enable", 1); }
96
100 void Disable() { WriteSysfs(pwm_path_ + "/enable", 0); }
101
107 void Beep(uint32_t freq, uint32_t duration_ms) {
108 SetFrequency(freq);
109 SetDutyCycle(0.5f);
110 Enable();
111 usleep(duration_ms * 1000);
112 Disable();
113 }
114
121 void PlayNote(NoteName note, uint32_t octave, uint32_t duration_ms) {
122 note_ = note;
123 octave_ = octave;
124 duration_ms_ = duration_ms;
125 note_sem_.release();
126 }
127
134 void SetAlarmConfig(uint32_t freq, uint32_t duration_ms, uint32_t delay_ms) {
135 alarm_freq_ = freq;
136 alarm_duration_ = duration_ms;
137 alarm_delay_ = delay_ms;
138 }
139
145 usleep(alarm_delay_ * 1000);
146 }
147
148 private:
149 std::string chip_path_;
150 std::string pwm_path_;
153
154 uint32_t alarm_freq_ = 1500;
155 uint32_t alarm_duration_ = 300;
156 uint32_t alarm_delay_ = 300;
157
158 std::thread note_thread_;
160 uint32_t octave_;
161 uint32_t duration_ms_;
162 std::binary_semaphore note_sem_{0};
163
170 int WriteSysfs(const std::string& path, int value) const {
171 FILE* fp = fopen(path.c_str(), "w");
172 if (!fp) {
173 return -1;
174 }
175 int result = fprintf(fp, "%d", value);
176 (void)(fclose(fp));
177 return result;
178 }
179};
PWM driver with Beep and PlayNote functionality.
Definition bsp_pwm.hpp:21
int channel_
PWM channel number.
Definition bsp_pwm.hpp:152
NoteName
Musical note names used for MIDI note calculation.
Definition bsp_pwm.hpp:27
void SetDutyCycle(float percent)
Set the duty cycle of PWM output.
Definition bsp_pwm.hpp:87
void SetFrequency(uint32_t hz)
Set the output frequency of PWM.
Definition bsp_pwm.hpp:78
void Enable()
Enable the PWM output signal.
Definition bsp_pwm.hpp:95
NoteName note_
Current note name.
Definition bsp_pwm.hpp:159
uint32_t octave_
Current octave.
Definition bsp_pwm.hpp:160
std::binary_semaphore note_sem_
Semaphore to trigger note play.
Definition bsp_pwm.hpp:162
uint32_t alarm_freq_
Default alarm frequency in Hz.
Definition bsp_pwm.hpp:154
std::thread note_thread_
Background thread for playing notes.
Definition bsp_pwm.hpp:158
void Beep(uint32_t freq, uint32_t duration_ms)
Output a beep with specific frequency and duration.
Definition bsp_pwm.hpp:107
void SetAlarmConfig(uint32_t freq, uint32_t duration_ms, uint32_t delay_ms)
Set configuration parameters for alarm beep.
Definition bsp_pwm.hpp:134
int WriteSysfs(const std::string &path, int value) const
Write an integer value to a sysfs file.
Definition bsp_pwm.hpp:170
PWM(int channel, int frequency_hz=1000, float duty_percent=0.0f, int chip=2)
Constructor: initializes PWM channel, sets initial frequency and duty cycle.
Definition bsp_pwm.hpp:37
std::string chip_path_
Sysfs path to the PWM chip.
Definition bsp_pwm.hpp:149
uint32_t alarm_delay_
Default alarm delay in ms.
Definition bsp_pwm.hpp:156
uint32_t alarm_duration_
Default alarm duration in ms.
Definition bsp_pwm.hpp:155
~PWM()
Destructor: disables PWM output.
Definition bsp_pwm.hpp:72
std::string pwm_path_
Sysfs path to the PWM channel.
Definition bsp_pwm.hpp:150
void PlayNote(NoteName note, uint32_t octave, uint32_t duration_ms)
Play a musical note based on note name and octave.
Definition bsp_pwm.hpp:121
void Disable()
Disable the PWM output signal.
Definition bsp_pwm.hpp:100
uint32_t duration_ms_
Duration of note in ms.
Definition bsp_pwm.hpp:161
int period_ns_
PWM period in nanoseconds.
Definition bsp_pwm.hpp:151
void TriggerAlarm()
Trigger an alarm sound followed by a delay.
Definition bsp_pwm.hpp:143