From fd169ed72e1fe348169f7e835d5d15b70965c391 Mon Sep 17 00:00:00 2001 From: PaulPenson Date: Thu, 6 Feb 2014 22:34:25 +0000 Subject: [PATCH 1/5] Update pwm.h Added low level buffer operations --- source/c_pwm/pwm.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/c_pwm/pwm.h b/source/c_pwm/pwm.h index d181211..c4daebf 100644 --- a/source/c_pwm/pwm.h +++ b/source/c_pwm/pwm.h @@ -32,6 +32,11 @@ int clear_channel_gpio(int channel, int gpio); int print_channel(int channel); int add_channel_pulse(int channel, int gpio, int width_start, int width); +int buffer_set_on(int channel, int position); +int buffer_set_off(int channel, int position); +int buffer_assign(int channel, int gpio, int position); +int buffer_unassign(int channel, int gpio, int position); + char* get_error_message(void); void set_softfatal(int enabled); From 1b1010dc5d985f65c30bd25675eaedc0d444b846 Mon Sep 17 00:00:00 2001 From: PaulPenson Date: Thu, 6 Feb 2014 22:35:17 +0000 Subject: [PATCH 2/5] Update pwm.c --- source/c_pwm/pwm.c | 104 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/source/c_pwm/pwm.c b/source/c_pwm/pwm.c index 86729f3..5af180d 100644 --- a/source/c_pwm/pwm.c +++ b/source/c_pwm/pwm.c @@ -51,13 +51,13 @@ * PULSE WIDTH INCREMENT GRANULARITY * --------------------------------- * Another very important setting is the pulse width increment granularity, which - * defaults to 10µs and is used for _all_ DMA channels (since its passed to the PWM + * defaults to 10µs and is used for _all_ DMA channels (since its passed to the PWM * timing hardware). Under the hood you need to set the pulse widths as multiples - * of the increment-granularity. Eg. in order to set 500µs pulses with a granularity - * setting of 10µs, you'll need to set the pulse-width as 50 (50 * 10µs = 500µs). + * of the increment-granularity. Eg. in order to set 500µs pulses with a granularity + * setting of 10µs, you'll need to set the pulse-width as 50 (50 * 10µs = 500µs). * Less granularity needs more DMA memory. * - * To achieve shorter pulses than 10µs, you simply need set a lower granularity. + * To achieve shorter pulses than 10µs, you simply need set a lower granularity. * * * WARNING @@ -84,6 +84,7 @@ #include #include #include + #include "pwm.h" // 15 DMA channels are usable on the RPi (0..14) @@ -468,19 +469,104 @@ add_channel_pulse(int channel, int gpio, int width_start, int width) *(dp + width_start) |= 1 << gpio; cbp->dst = phys_gpset0; - // Do nothing for the specified width - for (i = 1; i < width - 1; i++) { - *(dp + width_start + i) &= ~(1 << gpio); // set just this gpio's bit to 0 - cbp += 2; - } + //PaulP - re-order to write the off code before clearing the mid region. + cbp += 2 * (width - 2); // Clear GPIO at end *(dp + width_start + width) |= 1 << gpio; cbp->dst = phys_gpclr0; + + //PaulP - force a cache flush so this is in the DMA chain now. + __clear_cache((char*) (dp + width_start + width), (char*) (dp + width_start + width + 1)); + __clear_cache((char*) (cbp), (char*) (cbp + 2)); + + // Do nothing for the specified width + for (i = 1; i < width - 1; i++) { + *(dp + width_start + i) &= ~(1 << gpio); // set just this gpio's bit to 0 + } + return EXIT_SUCCESS; } +//Write an 'on' instruction to the buffer at the specified position. +int +buffer_set_on(int channel, int position) +{ + static uint32_t phys_gpset0 = 0x7e200000 + 0x1c; + //log_debug("buffer_set_on: channel=%d, position=%d\n", channel, position); + if (!channels[channel].virtbase) + return fatal("Error: channel %d has not been initialized with 'init_channel(..)'\n", channel); + if (position > channels[channel].width_max || position < 0) + return fatal("Error: position exceeds max_width of %d\n", channels[channel].width_max); + + dma_cb_t *cbp = (dma_cb_t *) get_cb(channel) + (position * 2); + cbp->dst = phys_gpset0; + __clear_cache((char*) cbp, (char*) (cbp + 2)); + + return EXIT_SUCCESS; +} + +//Write an 'off' instruction to the buffer at the specified position. +int +buffer_set_off(int channel, int position) +{ + static uint32_t phys_gpclr0 = 0x7e200000 + 0x28; + + //log_debug("buffer_set_on: channel=%d, position=%d\n", channel, position); + if (!channels[channel].virtbase) + return fatal("Error: channel %d has not been initialized with 'init_channel(..)'\n", channel); + if (position > channels[channel].width_max || position < 0) + return fatal("Error: position exceeds max_width of %d\n", channels[channel].width_max); + + dma_cb_t *cbp = (dma_cb_t *) get_cb(channel) + (position * 2); + cbp->dst = phys_gpclr0; + __clear_cache((char*) cbp, (char*) (cbp + 2)); + + return EXIT_SUCCESS; +} + +//Assign a gpio channel to a specific point in the buffer +int +buffer_assign(int channel, int gpio, int position) +{ + uint32_t *dp = (uint32_t *) channels[channel].virtbase; + + //log_debug("buffer_assign: channel=%d, gpio=%d, position=%d\n", channel, gpio, position); + if (!channels[channel].virtbase) + return fatal("Error: channel %d has not been initialized with 'init_channel(..)'\n", channel); + if (position > channels[channel].width_max || position < 0) + return fatal("Error: position exceeds max_width of %d\n", channels[channel].width_max); + + if ((gpio_setup & 1< channels[channel].width_max || position < 0) + return fatal("Error: position exceeds max_width of %d\n", channels[channel].width_max); + + if ((gpio_setup & 1< Date: Thu, 6 Feb 2014 22:35:49 +0000 Subject: [PATCH 3/5] Update pwm_py.c --- source/c_pwm/pwm_py.c | 70 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/source/c_pwm/pwm_py.c b/source/c_pwm/pwm_py.c index 7a008c1..4192ca3 100644 --- a/source/c_pwm/pwm_py.c +++ b/source/c_pwm/pwm_py.c @@ -131,6 +131,70 @@ py_add_channel_pulse(PyObject *self, PyObject *args) return Py_None; } +// python function (void) buffer_set_on(int channel, int position) +static PyObject* +py_buffer_set_on(PyObject *self, PyObject *args) +{ + int channel, position; + + if (!PyArg_ParseTuple(args, "ii", &channel, &position)) + return NULL; + + if (buffer_set_on(channel, position) == EXIT_FAILURE) + return raise_error(); + + Py_INCREF(Py_None); + return Py_None; +} + +// python function (void) buffer_set_off(int channel, int position) +static PyObject* +py_buffer_set_off(PyObject *self, PyObject *args) +{ + int channel, position; + + if (!PyArg_ParseTuple(args, "ii", &channel, &position)) + return NULL; + + if (buffer_set_off(channel, position) == EXIT_FAILURE) + return raise_error(); + + Py_INCREF(Py_None); + return Py_None; +} + +// python function (void) buffer_assign(int channel, int gpio, int position) +static PyObject* +py_buffer_assign(PyObject *self, PyObject *args) +{ + int channel, gpio, position; + + if (!PyArg_ParseTuple(args, "iii", &channel, &gpio, &position)) + return NULL; + + if (buffer_assign(channel, gpio, position) == EXIT_FAILURE) + return raise_error(); + + Py_INCREF(Py_None); + return Py_None; +} + +// python function (void) buffer_assign(int channel, int gpio, int position) +static PyObject* +py_buffer_unassign(PyObject *self, PyObject *args) +{ + int channel, gpio, position; + + if (!PyArg_ParseTuple(args, "iii", &channel, &gpio, &position)) + return NULL; + + if (buffer_unassign(channel, gpio, position) == EXIT_FAILURE) + return raise_error(); + + Py_INCREF(Py_None); + return Py_None; +} + // python function print_channel(int channel) static PyObject* py_print_channel(PyObject *self, PyObject *args) @@ -205,7 +269,11 @@ static PyMethodDef pwm_methods[] = { {"init_channel", py_init_channel, METH_VARARGS, "Setup a channel with a specific period time and hardware"}, {"clear_channel", py_clear_channel, METH_VARARGS, "Clear all pulses on this channel"}, {"clear_channel_gpio", py_clear_channel_gpio, METH_VARARGS, "Clear one specific GPIO from this channel"}, - {"add_channel_pulse", py_add_channel_pulse, METH_VARARGS, "Add a specific pulse to a channel"}, + {"add_channel_pulse", py_add_channel_pulse, METH_VARARGS, "Add a specific pulse to a channel"}, + {"buffer_set_on", py_buffer_set_on, METH_VARARGS, "Write an off instruction to the buffer at the specified position"}, + {"buffer_set_off", py_buffer_set_off, METH_VARARGS, "Write an off instruction to the buffer at the specified position"}, + {"buffer_assign", py_buffer_assign, METH_VARARGS, "Assign a gpio channel to a specific point in the buffer"}, + {"buffer_unassign", py_buffer_unassign, METH_VARARGS, "Unassign a gpio channel to a specific point in the buffer"}, {"print_channel", py_print_channel, METH_VARARGS, "Print info about a specific channel"}, {"set_loglevel", py_set_loglevel, METH_VARARGS, "Set the loglevel to either 0 (debug) or 1 (errors)"}, {"is_setup", py_is_setup, METH_VARARGS, "Returns 1 is setup(..) has been called, else 0"}, From 7662013f644fd70068c423849ff5984ff991b88c Mon Sep 17 00:00:00 2001 From: PaulPenson Date: Thu, 6 Feb 2014 22:38:39 +0000 Subject: [PATCH 4/5] Update __init__.py --- source/RPIO/PWM/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/RPIO/PWM/__init__.py b/source/RPIO/PWM/__init__.py index f500164..226fc6e 100644 --- a/source/RPIO/PWM/__init__.py +++ b/source/RPIO/PWM/__init__.py @@ -114,6 +114,21 @@ def add_channel_pulse(dma_channel, gpio, start, width): """ return _PWM.add_channel_pulse(dma_channel, gpio, start, width) +def buffer_set_on(dma_channel, position): + """Write an on instruction to the buffer at the specified position""" + return _PWM.buffer_set_on(dma_channel, position) + +def buffer_set_off(dma_channel, position): + """Write an off instruction to the buffer at the specified position""" + return _PWM.buffer_set_off(dma_channel, position) + +def buffer_assign(dma_channel, gpio, position): + """Assign a gpio channel to a specific point in the buffer""" + return _PWM.buffer_assign(dma_channel, gpio, position) + +def buffer_unassign(dma_channel, gpio, position): + """Unassign a gpio channel to a specific point in the buffer""" + return _PWM.buffer_unassign(dma_channel, gpio, position) def print_channel(channel): """ Print info about a specific channel to stdout """ From 30a5ae66e914c1708fc3413af7e13209a1bc226b Mon Sep 17 00:00:00 2001 From: PaulPenson Date: Thu, 6 Feb 2014 22:42:10 +0000 Subject: [PATCH 5/5] Update pwm_py.c --- source/c_pwm/pwm_py.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/c_pwm/pwm_py.c b/source/c_pwm/pwm_py.c index 4192ca3..3a16d88 100644 --- a/source/c_pwm/pwm_py.c +++ b/source/c_pwm/pwm_py.c @@ -270,7 +270,7 @@ static PyMethodDef pwm_methods[] = { {"clear_channel", py_clear_channel, METH_VARARGS, "Clear all pulses on this channel"}, {"clear_channel_gpio", py_clear_channel_gpio, METH_VARARGS, "Clear one specific GPIO from this channel"}, {"add_channel_pulse", py_add_channel_pulse, METH_VARARGS, "Add a specific pulse to a channel"}, - {"buffer_set_on", py_buffer_set_on, METH_VARARGS, "Write an off instruction to the buffer at the specified position"}, + {"buffer_set_on", py_buffer_set_on, METH_VARARGS, "Write an on instruction to the buffer at the specified position"}, {"buffer_set_off", py_buffer_set_off, METH_VARARGS, "Write an off instruction to the buffer at the specified position"}, {"buffer_assign", py_buffer_assign, METH_VARARGS, "Assign a gpio channel to a specific point in the buffer"}, {"buffer_unassign", py_buffer_unassign, METH_VARARGS, "Unassign a gpio channel to a specific point in the buffer"},