Class: LGPIO::HardwarePWM
- Inherits:
-
Object
- Object
- LGPIO::HardwarePWM
- Defined in:
- lib/lgpio/hardware_pwm.rb,
ext/lgpio/lgpio.c
Direct Known Subclasses
Constant Summary collapse
- NS_PER_S =
1_000_000_000
- NS_PER_US =
1_000
- SYS_FS_PWM_PATH =
"/sys/class/pwm/"
Instance Attribute Summary collapse
-
#duty ⇒ Object
Returns the value of attribute duty.
-
#enabled ⇒ Object
readonly
Returns the value of attribute enabled.
-
#period ⇒ Object
Returns the value of attribute period.
-
#polarity ⇒ Object
Returns the value of attribute polarity.
Instance Method Summary collapse
- #disable ⇒ Object
- #duty_path ⇒ Object
- #duty_percent ⇒ Object
- #duty_percent=(d) ⇒ Object
- #duty_us=(d_us) ⇒ Object
- #enable ⇒ Object
- #enable_path ⇒ Object
- #frequency ⇒ Object
- #frequency=(freq) ⇒ Object
-
#initialize(chip, channel, frequency: nil, period: nil) ⇒ HardwarePWM
constructor
A new instance of HardwarePWM.
- #path ⇒ Object
- #period_path ⇒ Object
- #polarity_path ⇒ Object
-
#tx_wave_ook(dutyPath, dutyString, pulses) ⇒ Object
**************************************************************************.
Constructor Details
#initialize(chip, channel, frequency: nil, period: nil) ⇒ HardwarePWM
Returns a new instance of HardwarePWM.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/lgpio/hardware_pwm.rb', line 9 def initialize(chip, channel, frequency: nil, period: nil) @chip = chip @channel = channel # Accept either frequency (in Hz) or period in nanoseconds. if (frequency && period) || (!frequency && !period) raise "either period: or frequency: is required, but not both" end period ? self.period = period : self.frequency = frequency # Default to with 0 duty cycle and normal polarity. self.duty = 0 self.polarity = :normal enable end |
Instance Attribute Details
#duty ⇒ Object
Returns the value of attribute duty.
7 8 9 |
# File 'lib/lgpio/hardware_pwm.rb', line 7 def duty @duty end |
#enabled ⇒ Object (readonly)
Returns the value of attribute enabled.
7 8 9 |
# File 'lib/lgpio/hardware_pwm.rb', line 7 def enabled @enabled end |
#period ⇒ Object
Returns the value of attribute period.
7 8 9 |
# File 'lib/lgpio/hardware_pwm.rb', line 7 def period @period end |
#polarity ⇒ Object
Returns the value of attribute polarity.
7 8 9 |
# File 'lib/lgpio/hardware_pwm.rb', line 7 def polarity @polarity end |
Instance Method Details
#disable ⇒ Object
99 100 101 102 |
# File 'lib/lgpio/hardware_pwm.rb', line 99 def disable File.open(enable_path, 'w') { |f| f.write("0") } @enabled = false end |
#duty_path ⇒ Object
39 40 41 |
# File 'lib/lgpio/hardware_pwm.rb', line 39 def duty_path @duty_path ||= "#{path}duty_cycle" end |
#duty_percent ⇒ Object
77 78 79 80 |
# File 'lib/lgpio/hardware_pwm.rb', line 77 def duty_percent return 0.0 if (!duty || !period) || (duty == 0) (duty / period.to_f) * 100.0 end |
#duty_percent=(d) ⇒ Object
82 83 84 85 86 |
# File 'lib/lgpio/hardware_pwm.rb', line 82 def duty_percent=(d) raise "duty_cycle: #{d} % cannot be more than 100%" if d > 100 d_ns = ((d / 100.0) * @period.to_i).round self.duty = d_ns end |
#duty_us=(d_us) ⇒ Object
88 89 90 91 |
# File 'lib/lgpio/hardware_pwm.rb', line 88 def duty_us=(d_us) d_ns = (d_us * NS_PER_US).round self.duty = d_ns end |
#enable ⇒ Object
104 105 106 107 |
# File 'lib/lgpio/hardware_pwm.rb', line 104 def enable File.open(enable_path, 'w') { |f| f.write("1") } @enabled = true end |
#enable_path ⇒ Object
43 44 45 |
# File 'lib/lgpio/hardware_pwm.rb', line 43 def enable_path @enable_path ||= "#{path}enable" end |
#frequency ⇒ Object
62 63 64 65 |
# File 'lib/lgpio/hardware_pwm.rb', line 62 def frequency # If not set explicitly, calculate from period, rounded to nearest Hz. @frequency ||= (1_000_000_000.0 / period).round end |
#frequency=(freq) ⇒ Object
57 58 59 60 |
# File 'lib/lgpio/hardware_pwm.rb', line 57 def frequency=(freq) self.period = (NS_PER_S / freq.to_f).round @frequency = freq end |
#path ⇒ Object
27 28 29 |
# File 'lib/lgpio/hardware_pwm.rb', line 27 def path @path ||= "#{SYS_FS_PWM_PATH}pwmchip#{@chip}/pwm#{@channel}/" end |
#period_path ⇒ Object
35 36 37 |
# File 'lib/lgpio/hardware_pwm.rb', line 35 def period_path @period_path ||= "#{path}period" end |
#polarity_path ⇒ Object
31 32 33 |
# File 'lib/lgpio/hardware_pwm.rb', line 31 def polarity_path @polarity_path ||= "#{path}polarity" end |
#tx_wave_ook(dutyPath, dutyString, pulses) ⇒ Object
**************************************************************************
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'ext/lgpio/lgpio.c', line 231
static VALUE tx_wave_ook(VALUE self, VALUE dutyPath, VALUE dutyString, VALUE pulses) {
// NOTE: This uses hardware PWM, NOT the lgpio software PWM/wave interface.
// The Ruby class LGPIO::HardwarePWM should have already set the PWM carrier frequency.
//
// Convert pulses from microseconds to nanoseconds.
Check_Type(pulses, T_ARRAY);
uint32_t pulseCount = rb_array_len(pulses);
uint64_t nanoPulses[pulseCount];
for (uint32_t i=0; i<pulseCount; i++) {
nanoPulses[i] = NUM2UINT(rb_ary_entry(pulses, i)) * 1000;
}
// Prepare to write duty cycle.
const char *filePath = StringValueCStr(dutyPath);
FILE *dutyFile = fopen(filePath, "w");
if (dutyFile == NULL) {
VALUE errorMessage = rb_sprintf("Could not open PWM duty_cycle file: %s", filePath);
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(errorMessage));
}
fclose(dutyFile);
const char *cDuty = StringValueCStr(dutyString);
// Toggle duty cycle between given value and 0, to modulate the PWM carrier.
for (uint32_t i=0; i<pulseCount; i++) {
if (i % 2 == 0) {
dutyFile = fopen(filePath, "w");
fputs(cDuty, dutyFile);
fclose(dutyFile);
} else {
dutyFile = fopen(filePath, "w");
fputs("0", dutyFile);
fclose(dutyFile);
}
// Wait for pulse time.
nanoDelay(nanoPulses[i]);
}
// Leave the pin low.
dutyFile = fopen(filePath, "w");
fputs("0", dutyFile);
fclose(dutyFile);
return UINT2NUM(pulseCount);
}
|