#include "arduino_pwm.h" #if defined(ARDUINO_ARCH_ESP8266) #include #endif extern "C" { #if defined(ARDUINO_ARCH_ESP8266) void c_pwm_sub(mrb_vm *vm, mrb_value *v){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; if(handle->freq_num==0){ stopWaveform(handle->pin_num); }else{ uint32_t timeLow=(uint32_t)(1e6/(handle->freq_num)); uint32_t timeHigh=(uint32_t)(timeLow*(handle->duty_num)/100); timeLow = timeHigh>timeLow ? 0 : timeLow-timeHigh; pinMode(handle->pin_num, OUTPUT); startWaveform(handle->pin_num, timeHigh, timeLow); } } void c_pwm_new(mrb_vm *vm, mrb_value *v, int argc){ v[0] = mrbc_instance_new(vm, v[0].cls, sizeof(PWM_HANDLE)); PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; handle->pin_num = GET_INT_ARG(1); handle->freq_num = 1000; handle->duty_num = 50.0; MRBC_KW_ARG(frequency, freq, duty); if( MRBC_ISNUMERIC(duty) ) handle->duty_num = MRBC_TO_FLOAT(duty); if( MRBC_ISNUMERIC(frequency) ) handle->freq_num = MRBC_TO_FLOAT(frequency); if( MRBC_ISNUMERIC(freq) ) handle->freq_num = MRBC_TO_FLOAT(freq); MRBC_KW_DELETE(frequency, freq, duty); c_pwm_sub(vm,v); } static void c_pwm_duty(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; handle->duty_num = MRBC_ARG_F(1); c_pwm_sub(vm,v); } static void c_pwm_frequency(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; handle->freq_num = MRBC_ARG_F(1); c_pwm_sub(vm,v); } static void c_pwm_period_us(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; uint16_t us = MRBC_ARG_I(1); float freq = (us == 0 ? 0 : 1e6 / us); handle->freq_num = freq; c_pwm_sub(vm,v); } static void c_pwm_pulse_width_us(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; handle->duty_num = MRBC_ARG_I(1)*(handle->freq_num)/1e6*100; c_pwm_sub(vm,v); } #else void c_pwm_new(mrb_vm *vm, mrb_value *v, int argc){ v[0] = mrbc_instance_new(vm, v[0].cls, sizeof(PWM_HANDLE)); PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; handle->pin_num = GET_INT_ARG(1); MRBC_KW_ARG(frequency, freq, duty); if( MRBC_ISNUMERIC(duty) ) analogWrite( handle->pin_num, MRBC_TO_INT(duty)*255/100 ); if( MRBC_ISNUMERIC(frequency) ) tone( handle->pin_num, MRBC_TO_INT(frequency) ); if( MRBC_ISNUMERIC(freq) ) tone( handle->pin_num, MRBC_TO_INT(freq) ); MRBC_KW_DELETE(frequency, freq, duty); } static void c_pwm_duty(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; analogWrite( handle->pin_num, MRBC_ARG_I(1)*255/100 ); } static void c_pwm_frequency(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; tone( handle->pin_num, MRBC_ARG_I(1) ); } static void c_pwm_period_us(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; uint16_t us = MRBC_ARG_I(1); double freq = (us == 0 ? 0 : 1e6 / us); tone( handle->pin_num, freq ); } /* static void c_pwm_pulse_width_us(mrbc_vm *vm, mrbc_value *v, int argc){ PWM_HANDLE *handle = (PWM_HANDLE *)v[0].instance->data; } */ #endif void mrbc_init_class_pwm(void){ mrbc_class *pwm = mrbc_define_class(0, "PWM", mrbc_class_object); mrbc_define_method(0, pwm, "new", c_pwm_new); mrbc_define_method(0, pwm, "duty", c_pwm_duty); mrbc_define_method(0, pwm, "frequency", c_pwm_frequency); mrbc_define_method(0, pwm, "period_us", c_pwm_period_us); #if defined(ARDUINO_ARCH_ESP8266) mrbc_define_method(0, pwm, "pulse_width_us", c_pwm_pulse_width_us); #endif } } //extern