aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-04-16 20:47:22 +0200
committerHarald Welte <laforge@gnumonks.org>2019-04-16 21:13:48 +0200
commit67b2abacd22a9b18ecb00932a1e32c77086d627c (patch)
treec3e17b31edd1b1553e215440d614fd0e2315c013
parent1762506a1f8f8e230d7ade1c84da92e2899e23ce (diff)
manual_test.c: New manual board testing mode
-rw-r--r--sysmoOCTSIM/gcc/Makefile3
-rw-r--r--sysmoOCTSIM/main.c3
-rw-r--r--sysmoOCTSIM/manual_test.c255
3 files changed, 260 insertions, 1 deletions
diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index 7496377..376ddaf 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -77,6 +77,7 @@ hal/src/hal_init.o \
gcc/gcc/startup_same54.o \
hal/src/hal_usb_device.o \
main.o \
+manual_test.o \
i2c_bitbang.o \
octsim_i2c.o \
ncn8025.o \
@@ -124,6 +125,7 @@ OBJS_AS_ARGS += \
"gcc/gcc/startup_same54.o" \
"hal/src/hal_usb_device.o" \
"main.o" \
+"manual_test.o" \
"i2c_bitbang.o" \
"octsim_i2c.o" \
"ncn8025.o" \
@@ -177,6 +179,7 @@ DEPS_AS_ARGS += \
"hal/src/hal_usart_async.d" \
"hpl/osc32kctrl/hpl_osc32kctrl.d" \
"main.d" \
+"manual_test.d" \
"i2c_bitbang.d" \
"octsim_i2c.d" \
"ncn8025.d" \
diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c
index 93b90db..6c4e9e6 100644
--- a/sysmoOCTSIM/main.c
+++ b/sysmoOCTSIM/main.c
@@ -211,7 +211,7 @@ DEFUN(sim_led, cmd_sim_led, "sim-led", "Set SIM LED (1=on, 0=off)")
-
+extern void testmode_init(void);
int main(void)
{
@@ -230,6 +230,7 @@ int main(void)
command_register(&cmd_sim_clkdiv);
command_register(&cmd_sim_voltage);
command_register(&cmd_sim_led);
+ testmode_init();
printf("\r\n\r\nsysmocom sysmoOCTSIM\r\n");
diff --git a/sysmoOCTSIM/manual_test.c b/sysmoOCTSIM/manual_test.c
new file mode 100644
index 0000000..5cc9bca
--- /dev/null
+++ b/sysmoOCTSIM/manual_test.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <parts.h>
+
+#include "atmel_start.h"
+#include "atmel_start_pins.h"
+
+#include "i2c_bitbang.h"
+#include "octsim_i2c.h"
+#include "ncn8025.h"
+
+#include "command.h"
+
+enum testmode_test {
+ TEST_USER_LED,
+ /* test the per-slot LED by blinking it shortly */
+ TEST_LED,
+ /* test the voltages of the SIMVCC */
+ TEST_VOLTAGE,
+ /* test the clock rates of the SIMCLK pin */
+ TEST_CLOCK,
+ /* test the RST line by asserting it low and then back high */
+ TEST_RST,
+ /* test the RST line by asserting it low and then back high */
+ TEST_IO,
+ _NUM_TESTS
+};
+static const char *test_names[_NUM_TESTS] = {
+ [TEST_USER_LED] = "USER_LED",
+ [TEST_LED] = "LED",
+ [TEST_VOLTAGE] = "VOLTAGE",
+ [TEST_CLOCK] = "CLOCK",
+ [TEST_RST] = "RST",
+ [TEST_IO] = "IO",
+};
+
+struct testmode_state {
+ uint8_t slot;
+ enum testmode_test test_nr;
+ int test_int;
+ struct ncn8025_settings ncn;
+};
+static struct testmode_state g_tms;
+
+#define BLINK_MS 500
+
+static void set_slot(uint8_t slot)
+{
+ printf("changing slot to %u\r\n", slot);
+ g_tms.slot = slot;
+ g_tms.ncn = (struct ncn8025_settings) {
+ .rstin = false,
+ .cmdvcc = false,
+ .led = false,
+ .clkdiv = SIM_CLKDIV_8,
+ .vsel = SIM_VOLT_3V0,
+ };
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+ ncn8025_get(g_tms.slot, &g_tms.ncn);
+}
+
+static void next_test(void)
+{
+ g_tms.test_nr = (g_tms.test_nr + 1) % _NUM_TESTS;
+ g_tms.test_int = 0;
+ printf("changing test to %s\r\n", test_names[g_tms.test_nr]);
+}
+
+static void test_user_led(void)
+{
+ printf("blinking User LED\r\n");
+
+ gpio_set_pin_function(PIN_PC26, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(PIN_PC26, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(PIN_PC26, true);
+ delay_ms(BLINK_MS);
+ gpio_set_pin_level(PIN_PC26, false);
+}
+
+static void test_led(void)
+{
+ printf("blinking Slot LED\r\n");
+
+ g_tms.ncn.led = true;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+ delay_ms(BLINK_MS);
+ g_tms.ncn.led = false;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+}
+
+static enum ncn8025_sim_voltage voltage[3] = { SIM_VOLT_1V8, SIM_VOLT_3V0, SIM_VOLT_5V0 };
+static const char *voltage_name[3] = { "1.8", "3.0", "5.0" };
+
+static void ncn_change_voltage(enum ncn8025_sim_voltage vsel)
+{
+ /* first disable the output; VSEL changes require output to be disabled */
+ g_tms.ncn.cmdvcc = false;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+
+ /* then re-enable it with the new voltage setting */
+ g_tms.ncn.vsel = vsel;
+ g_tms.ncn.cmdvcc = true;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+}
+
+static void test_voltage(void)
+{
+ printf("Testing Voltage %s\r\n", voltage_name[g_tms.test_int]);
+
+ ncn_change_voltage(voltage[g_tms.test_int]);
+ g_tms.test_int = (g_tms.test_int+1) % 3;
+}
+
+static enum ncn8025_sim_clkdiv clk_div[4] = { SIM_CLKDIV_8, SIM_CLKDIV_4, SIM_CLKDIV_2, SIM_CLKDIV_1 };
+static const uint8_t clk_div_val[4] = { 8, 4, 2, 1 };
+
+static void test_clock(void)
+{
+ printf("Testing Clock Divider %u\r\n", clk_div_val[g_tms.test_int]);
+ g_tms.ncn.cmdvcc = true;
+ g_tms.ncn.clkdiv = clk_div[g_tms.test_int];
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+ g_tms.test_int = (g_tms.test_int+1) % 4;
+}
+
+static void test_rst(void)
+{
+ printf("blinking RST\r\n");
+
+ /* well-defined voltage for LED brightness */
+ ncn_change_voltage(SIM_VOLT_3V0);
+
+ g_tms.ncn.cmdvcc = true;
+ g_tms.ncn.rstin = true;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+
+ delay_ms(BLINK_MS);
+
+ g_tms.ncn.rstin = false;
+ ncn8025_set(g_tms.slot, &g_tms.ncn);
+}
+
+#ifndef SIM7_IO
+#define SIM7_IO PIN_PB21
+#endif
+static const enum gpio_port sim_io_gpio[] = { SIM0_IO, SIM1_IO, SIM2_IO, SIM3_IO,
+ SIM4_IO, SIM5_IO, SIM6_IO, SIM7_IO };
+
+static void test_io(void)
+{
+ enum gpio_port gpio = sim_io_gpio[g_tms.slot];
+ printf("blinking I/O\r\n");
+
+ /* well-defined voltage for LED brightness */
+ ncn_change_voltage(SIM_VOLT_3V0);
+
+ gpio_set_pin_function(gpio, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(gpio, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(gpio, false);
+ delay_ms(BLINK_MS);
+ gpio_set_pin_level(gpio, true);
+
+ /* FIXME: restore tack to original function! */
+ //gpio_set_pin_function(sim_io_gpio[g_tms.slot], GPIO_PIN_FUNCTION_OFF);
+}
+
+typedef void (*test_fn)(void);
+static const test_fn test_functions[_NUM_TESTS] = {
+ [TEST_USER_LED] = test_user_led,
+ [TEST_LED] = test_led,
+ [TEST_VOLTAGE] = test_voltage,
+ [TEST_CLOCK] = test_clock,
+ [TEST_RST] = test_rst,
+ [TEST_IO] = test_io,
+};
+
+static void execute_test(void)
+{
+ printf("(%u) %-10s: ", g_tms.slot, test_names[g_tms.test_nr]);
+ test_functions[g_tms.test_nr]();
+}
+
+static int wait_for_key_and_process(void)
+{
+ int c;
+
+ do {
+ } while (!usart_sync_is_rx_not_empty(&UART_debug));
+
+ c = getchar();
+ if (c < 0)
+ return -1;
+
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ set_slot(c - '0');
+ execute_test();
+ break;
+ case 'n':
+ case 'N':
+ next_test();
+ execute_test();
+ break;
+ case 'Q':
+ case 'q':
+ printf("Leaving Test Mode\r\n");
+ return -1;
+ case ' ':
+ execute_test();
+ break;
+ }
+ return 0;
+}
+
+DEFUN(testmode_fn, cmd_testmode,
+ "testmode", "Enter board testing mode (Use `Q` to exit)")
+{
+ printf("Manual test mode. 'Q': exit, 'N': next test, SPACE: re-run, '0'-'7': slot\r\n");
+
+ printf("SPACE will start the current test (%s)\r\n", test_names[g_tms.test_nr]);
+ while (1) {
+ if (wait_for_key_and_process() < 0)
+ break;
+ }
+}
+
+void testmode_init(void)
+{
+ command_register(&cmd_testmode);
+}