Skip to content

Commit

Permalink
add PWM.set_period_ns and PWM.set_pulse_width_ns
Browse files Browse the repository at this point in the history
  • Loading branch information
streamnsight committed Sep 22, 2016
1 parent ee28799 commit 51a8663
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
49 changes: 49 additions & 0 deletions source/c_pwm.c
Expand Up @@ -126,6 +126,33 @@ int pwm_set_frequency(const char *key, float freq) {
return 1;
}

int pwm_set_period_ns(const char *key, unsigned long period_ns) {
int len;
char buffer[80];
unsigned long period_ns;
struct pwm_exp *pwm;

if (freq <= 0.0)
return -1;

pwm = lookup_exported_pwm(key);

if (pwm == NULL) {
return -1;
}

//period_ns = (unsigned long)(1e9 / freq);

if (period_ns != pwm->period_ns) {
pwm->period_ns = period_ns;

len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); BUF2SMALL(buffer);
ssize_t s = write(pwm->period_fd, buffer, len); ASSRT(s == len);
}

return 1;
}

int pwm_set_polarity(const char *key, int polarity) {
int len;
char buffer[80];
Expand Down Expand Up @@ -175,6 +202,28 @@ int pwm_set_duty_cycle(const char *key, float duty) {
return 0;
}

int pwm_set_pulse_width_ns(const char *key, unsigned long pulse_width_ns) {
int len;
char buffer[80];
struct pwm_exp *pwm;

pwm = lookup_exported_pwm(key);

if (pwm == NULL) {
return -1;
}

if (pulse_width_ns < 0 || pulse_width_ns > pwm->period_ns)
return -1;

pwm->duty = pulse_width_ns //(unsigned long)(pwm->period_ns * (duty / 100.0));

len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty); BUF2SMALL(buffer);
ssize_t s = write(pwm->duty_fd, buffer, len); ASSRT(s == len);

return 0;
}

int pwm_set_enable(const char *key, int enable)
{
int len;
Expand Down
2 changes: 2 additions & 0 deletions source/c_pwm.h
Expand Up @@ -32,6 +32,8 @@ SOFTWARE.
int pwm_start(const char *key, float duty, float freq, int polarity);
int pwm_disable(const char *key);
int pwm_set_frequency(const char *key, float freq);
int pwm_set_period_ns(const char *key, unsigned long period_ns);
int pwm_set_duty_cycle(const char *key, float duty);
int pwm_set_pulse_width_ns(const char *key, unsigned long pulse_width_ns);
int pwm_set_enable(const char *key, int enable);
void pwm_cleanup(void);
63 changes: 63 additions & 0 deletions source/py_pwm.c
Expand Up @@ -134,6 +134,38 @@ static PyObject *py_set_duty_cycle(PyObject *self, PyObject *args, PyObject *kwa
Py_RETURN_NONE;
}

// python method PWM.set_pulse_width(channel, pulse_width_ns)
static PyObject *py_set_pulse_width_ns(PyObject *self, PyObject *args, PyObject *kwargs)
{
char key[8];
char *channel;
unsigned long pulse_width_ns = 0.0;
static char *kwlist[] = {"channel", "pulse_width_ns", NULL};

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|k", kwlist, &channel, &pulse_width_ns))
return NULL;

pwm = lookup_exported_pwm(key);

if (pwm == NULL) {
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
return NULL;
}

if (pulse_width_ns < 0.0 || pulse_width_ns > pwm->period_ns)
{
PyErr_SetString(PyExc_ValueError, "pulse width must have a value from 0 to period");
return NULL;
}

if (pwm_set_pulse_width_ns(key, duty_cycle) == -1) {
PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first");
return NULL;
}

Py_RETURN_NONE;
}

// python method PWM.set_frequency(channel, frequency)
static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwargs)
{
Expand Down Expand Up @@ -164,6 +196,35 @@ static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwar
Py_RETURN_NONE;
}

// python method PWM.set_period_ns(channel, period_ns)
static PyObject *py_set_period_ns(PyObject *self, PyObject *args, PyObject *kwargs)
{
char key[8];
char *channel;
unsigned long period_ns = 2e6;
static char *kwlist[] = {"channel", "period_ns", NULL};

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|k", kwlist, &channel, &period_ns))
return NULL;

if (period_ns <= 0)
{
PyErr_SetString(PyExc_ValueError, "period must be greater than 0ns");
return NULL;
}

if (!get_pwm_key(channel, key)) {
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
return NULL;
}

if (pwm_set_period_ns(key, period_ns) == -1) {
PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first");
return NULL;
}

Py_RETURN_NONE;
}

static const char moduledocstring[] = "Hardware PWM functionality of a CHIP using Python";

Expand All @@ -172,6 +233,8 @@ PyMethodDef pwm_methods[] = {
{"stop", (PyCFunction)py_stop_channel, METH_VARARGS | METH_KEYWORDS, "Stop the PWM channel. channel can be in the form of 'PWM0', or 'U13_18'"},
{ "set_duty_cycle", (PyCFunction)py_set_duty_cycle, METH_VARARGS, "Change the duty cycle\ndutycycle - between 0.0 and 100.0" },
{ "set_frequency", (PyCFunction)py_set_frequency, METH_VARARGS, "Change the frequency\nfrequency - frequency in Hz (freq > 0.0)" },
{ "set_period_ns", (PyCFunction)py_set_period_ns, METH_VARARGS, "Change the period\nperiod_ns - period in nanoseconds" },
{ "set_pulse_width_ns", (PyCFunction)py_set_pulse_width_ns, METH_VARARGS, "Change the period\npulse_width_ns - pulse width in nanoseconds" },
{"cleanup", py_cleanup, METH_VARARGS, "Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection"},
//{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"},
{NULL, NULL, 0, NULL}
Expand Down

0 comments on commit 51a8663

Please sign in to comment.