aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Kconfig3
-rw-r--r--src/Makefile1
-rw-r--r--src/avr/Kconfig1
-rw-r--r--src/gpiocmds.c72
-rw-r--r--src/pwmcmds.c78
5 files changed, 85 insertions, 70 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 0445685e..db265c96 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -21,6 +21,9 @@ config HAVE_GPIO_ADC
config HAVE_GPIO_SPI
bool
default n
+config HAVE_GPIO_HARD_PWM
+ bool
+ default n
config INLINE_STEPPER_HACK
# Enables gcc to inline stepper_event() into the main timer irq handler
diff --git a/src/Makefile b/src/Makefile
index 5c7dc085..b4a4c33e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -3,3 +3,4 @@
src-y += sched.c command.c stepper.c basecmd.c gpiocmds.c endstop.c
src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c
src-$(CONFIG_HAVE_GPIO_SPI) += spicmds.c
+src-$(CONFIG_HAVE_GPIO_HARD_PWM) += pwmcmds.c
diff --git a/src/avr/Kconfig b/src/avr/Kconfig
index efc8484a..8d5d4522 100644
--- a/src/avr/Kconfig
+++ b/src/avr/Kconfig
@@ -7,6 +7,7 @@ config AVR_SELECT
default y
select HAVE_GPIO_ADC
select HAVE_GPIO_SPI
+ select HAVE_GPIO_HARD_PWM
config BOARD_DIRECTORY
string
diff --git a/src/gpiocmds.c b/src/gpiocmds.c
index 283d3d2e..70608a6f 100644
--- a/src/gpiocmds.c
+++ b/src/gpiocmds.c
@@ -4,12 +4,11 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include <stddef.h> // offsetof
#include "basecmd.h" // alloc_oid
-#include "board/gpio.h" // struct gpio
+#include "board/gpio.h" // struct gpio_out
#include "board/irq.h" // irq_save
#include "command.h" // DECL_COMMAND
-#include "sched.h" // DECL_TASK
+#include "sched.h" // sched_timer
/****************************************************************
@@ -87,73 +86,6 @@ DECL_COMMAND(command_set_digital_out, "set_digital_out pin=%u value=%c");
/****************************************************************
- * Hardware PWM pins
- ****************************************************************/
-
-struct pwm_out_s {
- struct timer timer;
- struct gpio_pwm pin;
- uint32_t max_duration;
- uint8_t value, default_value;
-};
-
-static uint8_t
-pwm_event(struct timer *timer)
-{
- struct pwm_out_s *p = container_of(timer, struct pwm_out_s, timer);
- gpio_pwm_write(p->pin, p->value);
- if (p->value == p->default_value || !p->max_duration)
- return SF_DONE;
- p->timer.waketime += p->max_duration;
- p->timer.func = digital_end_event;
- return SF_RESCHEDULE;
-}
-
-void
-command_config_pwm_out(uint32_t *args)
-{
- struct pwm_out_s *p = alloc_oid(args[0], command_config_pwm_out, sizeof(*p));
- p->default_value = args[3];
- p->pin = gpio_pwm_setup(args[1], args[2], p->default_value);
- p->max_duration = args[4];
-}
-DECL_COMMAND(command_config_pwm_out,
- "config_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c"
- " max_duration=%u");
-
-void
-command_schedule_pwm_out(uint32_t *args)
-{
- struct pwm_out_s *p = lookup_oid(args[0], command_config_pwm_out);
- sched_del_timer(&p->timer);
- p->timer.func = pwm_event;
- p->timer.waketime = args[1];
- p->value = args[2];
- sched_timer(&p->timer);
-}
-DECL_COMMAND(command_schedule_pwm_out,
- "schedule_pwm_out oid=%c clock=%u value=%c");
-
-static void
-pwm_shutdown(void)
-{
- uint8_t i;
- struct pwm_out_s *p;
- foreach_oid(i, p, command_config_pwm_out) {
- gpio_pwm_write(p->pin, p->default_value);
- }
-}
-DECL_SHUTDOWN(pwm_shutdown);
-
-void
-command_set_pwm_out(uint32_t *args)
-{
- gpio_pwm_setup(args[0], args[1], args[2]);
-}
-DECL_COMMAND(command_set_pwm_out, "set_pwm_out pin=%u cycle_ticks=%u value=%c");
-
-
-/****************************************************************
* Soft PWM output pins
****************************************************************/
diff --git a/src/pwmcmds.c b/src/pwmcmds.c
new file mode 100644
index 00000000..bc9fec03
--- /dev/null
+++ b/src/pwmcmds.c
@@ -0,0 +1,78 @@
+// Commands for controlling hardware based pulse-width-modulator pins
+//
+// Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "basecmd.h" // alloc_oid
+#include "board/gpio.h" // struct gpio_pwm
+#include "command.h" // DECL_COMMAND
+#include "sched.h" // sched_timer
+
+struct pwm_out_s {
+ struct timer timer;
+ struct gpio_pwm pin;
+ uint32_t max_duration;
+ uint8_t value, default_value;
+};
+
+static uint8_t
+pwm_end_event(struct timer *timer)
+{
+ shutdown("Missed scheduling of next hard pwm event");
+}
+
+static uint8_t
+pwm_event(struct timer *timer)
+{
+ struct pwm_out_s *p = container_of(timer, struct pwm_out_s, timer);
+ gpio_pwm_write(p->pin, p->value);
+ if (p->value == p->default_value || !p->max_duration)
+ return SF_DONE;
+ p->timer.waketime += p->max_duration;
+ p->timer.func = pwm_end_event;
+ return SF_RESCHEDULE;
+}
+
+void
+command_config_pwm_out(uint32_t *args)
+{
+ struct pwm_out_s *p = alloc_oid(args[0], command_config_pwm_out, sizeof(*p));
+ p->default_value = args[3];
+ p->pin = gpio_pwm_setup(args[1], args[2], p->default_value);
+ p->max_duration = args[4];
+}
+DECL_COMMAND(command_config_pwm_out,
+ "config_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c"
+ " max_duration=%u");
+
+void
+command_schedule_pwm_out(uint32_t *args)
+{
+ struct pwm_out_s *p = lookup_oid(args[0], command_config_pwm_out);
+ sched_del_timer(&p->timer);
+ p->timer.func = pwm_event;
+ p->timer.waketime = args[1];
+ p->value = args[2];
+ sched_timer(&p->timer);
+}
+DECL_COMMAND(command_schedule_pwm_out,
+ "schedule_pwm_out oid=%c clock=%u value=%c");
+
+static void
+pwm_shutdown(void)
+{
+ uint8_t i;
+ struct pwm_out_s *p;
+ foreach_oid(i, p, command_config_pwm_out) {
+ gpio_pwm_write(p->pin, p->default_value);
+ }
+}
+DECL_SHUTDOWN(pwm_shutdown);
+
+void
+command_set_pwm_out(uint32_t *args)
+{
+ gpio_pwm_setup(args[0], args[1], args[2]);
+}
+DECL_COMMAND(command_set_pwm_out, "set_pwm_out pin=%u cycle_ticks=%u value=%c");