aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--src/Kconfig6
-rw-r--r--src/Makefile4
-rw-r--r--src/adccmds.c117
-rw-r--r--src/avr/Kconfig5
-rw-r--r--src/gpiocmds.c111
6 files changed, 135 insertions, 113 deletions
diff --git a/Makefile b/Makefile
index 1ca95481..170ce9fb 100644
--- a/Makefile
+++ b/Makefile
@@ -25,8 +25,8 @@ CPP=cpp
PYTHON=python
# Source files
-src-y=sched.c command.c stepper.c basecmd.c gpiocmds.c spicmds.c endstop.c
-dirs-y=src
+src-y =
+dirs-y = src
# Default compiler flags
cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
@@ -58,6 +58,7 @@ MAKEFLAGS += --no-print-directory
endif
# Include board specific makefile
+include src/Makefile
-include src/$(patsubst "%",%,$(CONFIG_BOARD_DIRECTORY))/Makefile
################ Common build rules
diff --git a/src/Kconfig b/src/Kconfig
index e7460cce..ac9322ee 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -13,6 +13,12 @@ endchoice
source "src/avr/Kconfig"
source "src/simulator/Kconfig"
+# The HAVE_GPIO_x options allow boards to disable support for some
+# commands if the hardware does not support the feature.
+config HAVE_GPIO_ADC
+ bool
+ default n
+
config INLINE_STEPPER_HACK
# Enables gcc to inline stepper_event() into the main timer irq handler
bool
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 00000000..5a640863
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,4 @@
+# Main code build rules
+
+src-y += sched.c command.c stepper.c basecmd.c gpiocmds.c spicmds.c endstop.c
+src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c
diff --git a/src/adccmds.c b/src/adccmds.c
new file mode 100644
index 00000000..2ae7f43c
--- /dev/null
+++ b/src/adccmds.c
@@ -0,0 +1,117 @@
+// Commands for controlling GPIO analog-to-digital input 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_adc
+#include "board/irq.h" // irq_save
+#include "command.h" // DECL_COMMAND
+#include "sched.h" // DECL_TASK
+
+struct analog_in {
+ struct timer timer;
+ uint32_t rest_time, sample_time, next_begin_time;
+ uint16_t value, min_value, max_value;
+ struct gpio_adc pin;
+ uint8_t state, sample_count;
+};
+
+static uint8_t
+analog_in_event(struct timer *timer)
+{
+ struct analog_in *a = container_of(timer, struct analog_in, timer);
+ if (gpio_adc_sample(a->pin)) {
+ a->timer.waketime += gpio_adc_sample_time();
+ return SF_RESCHEDULE;
+ }
+ uint16_t value = gpio_adc_read(a->pin);
+ uint8_t state = a->state;
+ if (state >= a->sample_count) {
+ state = 0;
+ } else {
+ value += a->value;
+ }
+ a->value = value;
+ a->state = state+1;
+ if (a->state < a->sample_count) {
+ a->timer.waketime += a->sample_time;
+ return SF_RESCHEDULE;
+ }
+ if (a->value < a->min_value || a->value > a->max_value)
+ shutdown("adc out of range");
+ a->next_begin_time += a->rest_time;
+ a->timer.waketime = a->next_begin_time;
+ return SF_RESCHEDULE;
+}
+
+void
+command_config_analog_in(uint32_t *args)
+{
+ struct analog_in *a = alloc_oid(
+ args[0], command_config_analog_in, sizeof(*a));
+ a->timer.func = analog_in_event;
+ a->pin = gpio_adc_setup(args[1]);
+ a->state = 1;
+}
+DECL_COMMAND(command_config_analog_in, "config_analog_in oid=%c pin=%u");
+
+void
+command_query_analog_in(uint32_t *args)
+{
+ struct analog_in *a = lookup_oid(args[0], command_config_analog_in);
+ sched_del_timer(&a->timer);
+ gpio_adc_clear_sample(a->pin);
+ a->next_begin_time = args[1];
+ a->timer.waketime = a->next_begin_time;
+ a->sample_time = args[2];
+ a->sample_count = args[3];
+ a->state = a->sample_count + 1;
+ a->rest_time = args[4];
+ a->min_value = args[5];
+ a->max_value = args[6];
+ if (! a->sample_count)
+ return;
+ sched_timer(&a->timer);
+}
+DECL_COMMAND(command_query_analog_in,
+ "query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c"
+ " rest_ticks=%u min_value=%hu max_value=%hu");
+
+static void
+analog_in_task(void)
+{
+ static uint16_t next;
+ if (!sched_check_periodic(3, &next))
+ return;
+ uint8_t oid;
+ struct analog_in *a;
+ foreach_oid(oid, a, command_config_analog_in) {
+ if (a->state != a->sample_count)
+ continue;
+ uint8_t flag = irq_save();
+ if (a->state != a->sample_count) {
+ irq_restore(flag);
+ continue;
+ }
+ uint16_t value = a->value;
+ uint32_t next_begin_time = a->next_begin_time;
+ a->state++;
+ irq_restore(flag);
+ sendf("analog_in_state oid=%c next_clock=%u value=%hu"
+ , oid, next_begin_time, value);
+ }
+}
+DECL_TASK(analog_in_task);
+
+static void
+analog_in_shutdown(void)
+{
+ uint8_t i;
+ struct analog_in *a;
+ foreach_oid(i, a, command_config_analog_in) {
+ gpio_adc_clear_sample(a->pin);
+ }
+}
+DECL_SHUTDOWN(analog_in_shutdown);
diff --git a/src/avr/Kconfig b/src/avr/Kconfig
index 24e33812..9cfbec07 100644
--- a/src/avr/Kconfig
+++ b/src/avr/Kconfig
@@ -2,6 +2,11 @@
if MACH_AVR
+config AVR_SELECT
+ bool
+ default y
+ select HAVE_GPIO_ADC
+
config BOARD_DIRECTORY
string
default "avr"
diff --git a/src/gpiocmds.c b/src/gpiocmds.c
index ff03dfd1..283d3d2e 100644
--- a/src/gpiocmds.c
+++ b/src/gpiocmds.c
@@ -288,114 +288,3 @@ soft_pwm_shutdown(void)
}
}
DECL_SHUTDOWN(soft_pwm_shutdown);
-
-
-/****************************************************************
- * Analog input pins
- ****************************************************************/
-
-struct analog_in {
- struct timer timer;
- uint32_t rest_time, sample_time, next_begin_time;
- uint16_t value, min_value, max_value;
- struct gpio_adc pin;
- uint8_t state, sample_count;
-};
-
-static uint8_t
-analog_in_event(struct timer *timer)
-{
- struct analog_in *a = container_of(timer, struct analog_in, timer);
- if (gpio_adc_sample(a->pin)) {
- a->timer.waketime += gpio_adc_sample_time();
- return SF_RESCHEDULE;
- }
- uint16_t value = gpio_adc_read(a->pin);
- uint8_t state = a->state;
- if (state >= a->sample_count) {
- state = 0;
- } else {
- value += a->value;
- }
- a->value = value;
- a->state = state+1;
- if (a->state < a->sample_count) {
- a->timer.waketime += a->sample_time;
- return SF_RESCHEDULE;
- }
- if (a->value < a->min_value || a->value > a->max_value)
- shutdown("adc out of range");
- a->next_begin_time += a->rest_time;
- a->timer.waketime = a->next_begin_time;
- return SF_RESCHEDULE;
-}
-
-void
-command_config_analog_in(uint32_t *args)
-{
- struct analog_in *a = alloc_oid(
- args[0], command_config_analog_in, sizeof(*a));
- a->timer.func = analog_in_event;
- a->pin = gpio_adc_setup(args[1]);
- a->state = 1;
-}
-DECL_COMMAND(command_config_analog_in, "config_analog_in oid=%c pin=%u");
-
-void
-command_query_analog_in(uint32_t *args)
-{
- struct analog_in *a = lookup_oid(args[0], command_config_analog_in);
- sched_del_timer(&a->timer);
- gpio_adc_clear_sample(a->pin);
- a->next_begin_time = args[1];
- a->timer.waketime = a->next_begin_time;
- a->sample_time = args[2];
- a->sample_count = args[3];
- a->state = a->sample_count + 1;
- a->rest_time = args[4];
- a->min_value = args[5];
- a->max_value = args[6];
- if (! a->sample_count)
- return;
- sched_timer(&a->timer);
-}
-DECL_COMMAND(command_query_analog_in,
- "query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c"
- " rest_ticks=%u min_value=%hu max_value=%hu");
-
-static void
-analog_in_task(void)
-{
- static uint16_t next;
- if (!sched_check_periodic(3, &next))
- return;
- uint8_t oid;
- struct analog_in *a;
- foreach_oid(oid, a, command_config_analog_in) {
- if (a->state != a->sample_count)
- continue;
- uint8_t flag = irq_save();
- if (a->state != a->sample_count) {
- irq_restore(flag);
- continue;
- }
- uint16_t value = a->value;
- uint32_t next_begin_time = a->next_begin_time;
- a->state++;
- irq_restore(flag);
- sendf("analog_in_state oid=%c next_clock=%u value=%hu"
- , oid, next_begin_time, value);
- }
-}
-DECL_TASK(analog_in_task);
-
-static void
-analog_in_shutdown(void)
-{
- uint8_t i;
- struct analog_in *a;
- foreach_oid(i, a, command_config_analog_in) {
- gpio_adc_clear_sample(a->pin);
- }
-}
-DECL_SHUTDOWN(analog_in_shutdown);