diff --git a/tests/atmega8/adc/Makefile b/tests/atmega8/adc/Makefile new file mode 100644 index 0000000000000..a75b46960448b --- /dev/null +++ b/tests/atmega8/adc/Makefile @@ -0,0 +1,9 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +FEATURES_REQUIRED = periph_adc + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/adc/README.md b/tests/atmega8/adc/README.md new file mode 100644 index 0000000000000..7ad2990acf2f3 --- /dev/null +++ b/tests/atmega8/adc/README.md @@ -0,0 +1,13 @@ +Expected result +=============== +When running this test, you should see the samples of all configured ADC lines +continuously streamed to std-out. + +Background +========== +This test application will initialize each configured ADC lines to sample with +10-bit accuracy. Once configured the application will continuously convert each +available channel and print the conversion results to std-out. + +For verification of the output connect the ADC pins to known voltage levels +and compare the output. diff --git a/tests/atmega8/adc/main.c b/tests/atmega8/adc/main.c new file mode 100644 index 0000000000000..57736cf8750ac --- /dev/null +++ b/tests/atmega8/adc/main.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014-2015 Freie Universität Berlin + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test application for peripheral ADC drivers + * + * @author Hauke Petersen + * @author Hugues Larrive + * + * @} + */ + +#include + +#include "periph/adc.h" + +#define RES ADC_RES_10BIT + +int main(void) +{ + int sample = 0; + + puts("\nRIOT ADC peripheral driver test\n"); + puts("This test will sample all available ADC lines with\n" + "a 10-bit resolution and print the sampled results to STDIO\n\n"); + + /* initialize all available ADC lines */ + for (unsigned i = 0; i < ADC_NUMOF; i++) { + if (adc_init(ADC_LINE(i)) < 0) { + printf("Initialization of ADC_LINE(%u) failed\n", i); + return 1; + } else { + printf("Successfully initialized ADC_LINE(%u)\n", i); + } + } + + while (1) { + for (unsigned i = 0; i < ADC_NUMOF; i++) { + sample = adc_sample(ADC_LINE(i), RES); + if (sample < 0) { + printf("ADC_LINE(%u): selected resolution not applicable\n", i); + } else { + printf("%i\t", sample); + } + } + printf("\n"); + } + + return 0; +} diff --git a/tests/atmega8/gpio/Makefile b/tests/atmega8/gpio/Makefile new file mode 100644 index 0000000000000..d0174894c503e --- /dev/null +++ b/tests/atmega8/gpio/Makefile @@ -0,0 +1,17 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +FEATURES_REQUIRED += periph_gpio + +USEMODULE += shell + +CFLAGS += -DNDEBUG -DLOG_LEVEL=LOG_NONE +DISABLE_MODULE += core_msg +DEVELHELP = 0 +CFLAGS += -DTHREAD_STACKSIZE_IDLE=74 +CFLAGS += -DTHREAD_STACKSIZE_MAIN=168 + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/gpio/main.c b/tests/atmega8/gpio/main.c new file mode 100644 index 0000000000000..05997e67078e4 --- /dev/null +++ b/tests/atmega8/gpio/main.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2014,2017 Freie Universität Berlin + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test application for GPIO peripheral drivers + * + * @author Hauke Petersen + * @author Hugues Larrive + * + * @} + */ + +#include +#include + +#include "shell.h" +#include "periph/gpio.h" + +#define SHELL_BUFSIZE (16) + +static int init_pin(int argc, char **argv, gpio_mode_t mode) +{ + int po, pi; + + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + po = atoi(argv[1]); + pi = atoi(argv[2]); + + if (gpio_init(GPIO_PIN(po, pi), mode) < 0) { + printf("Error to initialize GPIO_PIN(%i, %02i)\n", po, pi); + return 1; + } + + return 0; +} + +static int init_out(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_OUT); +} + +static int init_in(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_IN); +} + +static int init_in_pu(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_IN_PU); +} + +static int init_in_pd(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_IN_PD); +} + +static int init_od(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_OD); +} + +static int init_od_pu(int argc, char **argv) +{ + return init_pin(argc, argv, GPIO_OD_PU); +} + +static int cmd_read(int argc, char **argv) +{ + int port, pin; + + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + port = atoi(argv[1]); + pin = atoi(argv[2]); + + if (gpio_read(GPIO_PIN(port, pin))) { + printf("GPIO_PIN(%i.%02i) is HIGH\n", port, pin); + } + else { + printf("GPIO_PIN(%i.%02i) is LOW\n", port, pin); + } + + return 0; +} + +static int cmd_set(int argc, char **argv) +{ + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + gpio_set(GPIO_PIN(atoi(argv[1]), atoi(argv[2]))); + + return 0; +} + +static int cmd_clear(int argc, char **argv) +{ + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + gpio_clear(GPIO_PIN(atoi(argv[1]), atoi(argv[2]))); + + return 0; +} + +static int cmd_toggle(int argc, char **argv) +{ + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + gpio_toggle(GPIO_PIN(atoi(argv[1]), atoi(argv[2]))); + + return 0; +} + +static const shell_command_t shell_commands[] = { + { "init_out", "init as output (push-pull mode)", init_out }, + { "init_in", "init as input w/o pull resistor", init_in }, + { "init_in_pu", "init as input with pull-up", init_in_pu }, + { "init_in_pd", "init as input with pull-down", init_in_pd }, + { "init_od", "init as output (open-drain without pull resistor)", init_od }, + { "init_od_pu", "init as output (open-drain with pull-up)", init_od_pu }, + { "read", "read pin status", cmd_read }, + { "set", "set pin to HIGH", cmd_set }, + { "clear", "set pin to LOW", cmd_clear }, + { "toggle", "toggle pin", cmd_toggle }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + puts("GPIO peripheral driver test\n"); + + /* start the shell */ + char line_buf[SHELL_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_BUFSIZE); + + return 0; +} diff --git a/tests/atmega8/i2c/Makefile b/tests/atmega8/i2c/Makefile new file mode 100644 index 0000000000000..386ba022d91e6 --- /dev/null +++ b/tests/atmega8/i2c/Makefile @@ -0,0 +1,15 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +USEMODULE += pcf8574a +EXTERNAL_MODULE_DIRS += ./ +USEMODULE += hd44780_avr + +CFLAGS += -DHD44780_PARAM_COLS=20 +CFLAGS += -DHD44780_PARAM_ROWS=4 +CFLAGS += -DPCF8574A_BASE_ADDR=0x3F + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/i2c/hd44780_avr/Makefile b/tests/atmega8/i2c/hd44780_avr/Makefile new file mode 100644 index 0000000000000..48422e909a47d --- /dev/null +++ b/tests/atmega8/i2c/hd44780_avr/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/atmega8/i2c/hd44780_avr/hd44780_avr.c b/tests/atmega8/i2c/hd44780_avr/hd44780_avr.c new file mode 100644 index 0000000000000..8166b97b939a1 --- /dev/null +++ b/tests/atmega8/i2c/hd44780_avr/hd44780_avr.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_hd44780 + * + * @{ + * @file + * @brief Driver for the HD44780 LCD + * + * @note The display is also known as LCM1602C from Arduino kits + * + * @author Sebastian Meiling + * @author Hugues Larrive + * + * @} + */ + +#include + +#include "log.h" +#ifdef MODULE_PCF857X +#include "pcf857x.h" +#include "pcf857x_params.h" +#else +#include "periph/gpio.h" +#endif +/** As xtimer was too big to fit in atmega8's 8 Kbytes flash memory, this + * driver was hacked to remove xtimer dependency */ +#define F_CPU (CLOCK_CORECLOCK) +#define __DELAY_BACKWARD_COMPATIBLE__ +#include "util/delay.h" +static void xtimer_usleep(uint32_t us) +{ + _delay_us(us); +} +#define ZTIMER_USEC 0 + +#include "hd44780_avr.h" +#include "hd44780_avr_internal.h" +/************************** end of the hack ****************************/ + + +#ifdef MODULE_PCF857X +static pcf857x_t _pcf857x_dev; +#endif + +static inline void _command(const hd44780_t *dev, uint8_t value); +static void _pulse(const hd44780_t *dev); +static void _send(const hd44780_t *dev, uint8_t value, hd44780_state_t state); +static void _write_bits(const hd44780_t *dev, uint8_t bits, uint8_t value); + +static inline void _gpio_set(gpio_t pin); +static inline void _gpio_clear(gpio_t pin); +static inline int _gpio_init(gpio_t pin, gpio_mode_t mode); + +/** + * @brief Send a command to the display + * + * @param[in] dev device descriptor of display to initialize + * @param[in] value the command + */ +static inline void _command(const hd44780_t *dev, uint8_t value) +{ + _send(dev, value, HD44780_OFF); +} + +/** + * @brief Send a pulse to the display to enable new state + * + * @param[in] dev device descriptor of display to initialize + */ +static void _pulse(const hd44780_t *dev) +{ + _gpio_clear(dev->p.enable); + xtimer_usleep(HD44780_PULSE_WAIT_SHORT); + _gpio_set(dev->p.enable); + xtimer_usleep(HD44780_PULSE_WAIT_SHORT); + _gpio_clear(dev->p.enable); + xtimer_usleep(HD44780_PULSE_WAIT_LONG); +} + +/** + * @brief Send a data value to the display + * + * @param[in] dev device descriptor of display to initialize + * @param[in] value the data value, either char or command + * @param[in] state send state, to distinguish chars and commands + */ +static void _send(const hd44780_t *dev, uint8_t value, hd44780_state_t state) +{ + (state == HD44780_ON) ? _gpio_set(dev->p.rs) : _gpio_clear(dev->p.rs); + /* if RW pin is available, set it to LOW */ + if (gpio_is_valid(dev->p.rw)) { + _gpio_clear(dev->p.rw); + } + /* write data in 8Bit or 4Bit mode */ + if (dev->flag & HD44780_8BITMODE) { + _write_bits(dev, 8, value); + } + else { + _write_bits(dev, 4, value>>4); + _write_bits(dev, 4, value); + } +} + +static void _write_bits(const hd44780_t *dev, uint8_t bits, uint8_t value) +{ + for (unsigned i = 0; i < bits; ++i) { + if ((value >> i) & 0x01) { + _gpio_set(dev->p.data[i]); + } + else { + _gpio_clear(dev->p.data[i]); + } + } + _pulse(dev); +} + +static inline int _gpio_init(gpio_t pin, gpio_mode_t mode) +{ +#ifdef MODULE_PCF857X + return pcf857x_gpio_init(&_pcf857x_dev, pin, mode); +#else + return gpio_init(pin, mode); +#endif +} + +static inline void _gpio_set(gpio_t pin) +{ +#ifdef MODULE_PCF857X + pcf857x_gpio_set(&_pcf857x_dev, pin); +#else + gpio_set(pin); +#endif +} + +static inline void _gpio_clear(gpio_t pin) +{ +#ifdef MODULE_PCF857X + pcf857x_gpio_clear(&_pcf857x_dev, pin); +#else + gpio_clear(pin); +#endif +} + +int hd44780_init(hd44780_t *dev, const hd44780_params_t *params) +{ + /* write config params to device descriptor */ + dev->p = *params; + /* verify cols and rows */ + if ((dev->p.cols > HD44780_MAX_COLS) || (dev->p.rows > HD44780_MAX_ROWS) + || (dev->p.rows * dev->p.cols > 80)) { + LOG_ERROR("hd44780_init: invalid LCD size!\n"); + return -1; + } + dev->flag = 0; + /* set mode depending on configured pins */ + if (gpio_is_valid(dev->p.data[4])) { + dev->flag |= HD44780_8BITMODE; + } + else { + dev->flag |= HD44780_4BITMODE; + } + /* set flag for 1 or 2 row mode, 4 rows are 2 rows split half */ + if (dev->p.rows > 1) { + dev->flag |= HD44780_2LINE; + } + else { + dev->flag |= HD44780_1LINE; + } + /* set char size to 5x8 as default, 5x10 is hardly used by LCDs anyway */ + dev->flag |= HD44780_5x8DOTS; + /* calc and set row offsets, depending on number of columns */ + dev->roff[0] = 0x00; + dev->roff[1] = 0x40; + dev->roff[2] = 0x00 + dev->p.cols; + dev->roff[3] = 0x40 + dev->p.cols; + +#ifdef MODULE_PCF857X + /* + * TODO: We need an approach for defining and initializing the PCF8574. + * With this approach, only one PCF8574 could exist in the system + */ + pcf857x_init(&_pcf857x_dev, &pcf857x_params[0]); +#endif + + _gpio_init(dev->p.rs, GPIO_OUT); + /* RW (read/write) of LCD not required, set it to GPIO_UNDEF */ + if (gpio_is_valid(dev->p.rw)) { + _gpio_init(dev->p.rw, GPIO_OUT); + } + _gpio_init(dev->p.enable, GPIO_OUT); + /* configure all data pins as output */ + for (int i = 0; i < ((dev->flag & HD44780_8BITMODE) ? 8 : 4); ++i) { + _gpio_init(dev->p.data[i], GPIO_OUT); + } + /* see hitachi HD44780 datasheet pages 45/46 for init specs */ + xtimer_usleep(HD44780_INIT_WAIT_XXL); + _gpio_clear(dev->p.rs); + _gpio_clear(dev->p.enable); + if (gpio_is_valid(dev->p.rw)) { + _gpio_clear(dev->p.rw); + } + /* put the LCD into 4 bit or 8 bit mode */ + if (!(dev->flag & HD44780_8BITMODE)) { + /* see hitachi HD44780 datasheet figure 24, pg 46 */ + _write_bits(dev, 4, 0x03); + xtimer_usleep(HD44780_INIT_WAIT_LONG); + + _write_bits(dev, 4, 0x03); + xtimer_usleep(HD44780_INIT_WAIT_LONG); + + _write_bits(dev, 4, 0x03); + xtimer_usleep(HD44780_INIT_WAIT_SHORT); + + _write_bits(dev, 4, 0x02); + } else { + /* see hitachi HD44780 datasheet page 45 figure 23 */ + _command(dev, HD44780_FUNCTIONSET | dev->flag); + xtimer_usleep(HD44780_INIT_WAIT_LONG); /* wait more than 4.1ms */ + + _command(dev, HD44780_FUNCTIONSET | dev->flag); + xtimer_usleep(HD44780_INIT_WAIT_SHORT); + + _command(dev, HD44780_FUNCTIONSET | dev->flag); + } + _command(dev, HD44780_FUNCTIONSET | dev->flag); + + /* turn the display on with no cursor or blinking default, and clear */ + dev->ctrl = HD44780_DISPLAYON | HD44780_CURSOROFF | HD44780_BLINKOFF; + hd44780_display(dev, HD44780_ON); + hd44780_clear(dev); + /* Initialize to default text direction for western languages */ + dev->mode = HD44780_ENTRYLEFT | HD44780_ENTRYSHIFTDECREMENT; + _command(dev, HD44780_ENTRYMODESET | dev->mode); + + return 0; +} + +void hd44780_clear(const hd44780_t *dev) +{ + _command(dev, HD44780_CLEARDISPLAY); + xtimer_usleep(HD44780_CMD_WAIT); +} + +void hd44780_home(const hd44780_t *dev) +{ + _command(dev, HD44780_RETURNHOME); + xtimer_usleep(HD44780_CMD_WAIT); +} + +void hd44780_set_cursor(const hd44780_t *dev, uint8_t col, uint8_t row) +{ + if (row >= dev->p.rows) { + row = dev->p.rows - 1; + } + _command(dev, HD44780_SETDDRAMADDR | (col + dev->roff[row])); +} + +void hd44780_display(hd44780_t *dev, hd44780_state_t state) +{ + if (state == HD44780_ON) { + dev->ctrl |= HD44780_DISPLAYON; + } + else { + dev->ctrl &= ~HD44780_DISPLAYON; + } + _command(dev, HD44780_DISPLAYCONTROL | dev->ctrl); +} + +void hd44780_cursor(hd44780_t *dev, hd44780_state_t state) +{ + if (state == HD44780_ON) { + dev->ctrl |= HD44780_CURSORON; + } + else { + dev->ctrl &= ~HD44780_CURSORON; + } + _command(dev, HD44780_DISPLAYCONTROL | dev->ctrl); +} + +void hd44780_blink(hd44780_t *dev, hd44780_state_t state) +{ + if (state == HD44780_ON) { + dev->ctrl |= HD44780_BLINKON; + } + else { + dev->ctrl &= ~HD44780_BLINKON; + } + _command(dev, HD44780_DISPLAYCONTROL | dev->ctrl); +} + +void hd44780_scroll_left(const hd44780_t *dev) +{ + _command(dev, HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVELEFT); +} + +void hd44780_scroll_right(const hd44780_t *dev) { + _command(dev, HD44780_CURSORSHIFT | HD44780_DISPLAYMOVE | HD44780_MOVERIGHT); +} + +void hd44780_left2right(hd44780_t *dev) +{ + dev->mode |= HD44780_ENTRYLEFT; + _command(dev, HD44780_ENTRYMODESET | dev->mode); +} + +void hd44780_right2left(hd44780_t *dev) +{ + dev->mode &= ~HD44780_ENTRYLEFT; + _command(dev, HD44780_ENTRYMODESET | dev->mode); +} + +void hd44780_autoscroll(hd44780_t *dev, hd44780_state_t state) +{ + if (state == HD44780_ON) { + dev->mode |= HD44780_ENTRYSHIFTINCREMENT; + } + else { + dev->mode &= ~HD44780_ENTRYSHIFTINCREMENT; + } + _command(dev, HD44780_ENTRYMODESET | dev->mode); +} + +void hd44780_create_char(const hd44780_t *dev, uint8_t location, uint8_t charmap[]) +{ + location &= 0x7; /* 8 locations (0-7) possible */ + _command(dev, HD44780_SETCGRAMADDR | (location << 3)); + for (unsigned i = 0; i < HD44780_CGRAM_SIZE; ++i) { + hd44780_write(dev, charmap[i]); + } +} + +void hd44780_write(const hd44780_t *dev, uint8_t value) +{ + _send(dev, value, HD44780_ON); +} + +void hd44780_print(const hd44780_t *dev, const char *data ) +{ + while (*data != '\0') { + hd44780_write(dev, *data++); + } +} diff --git a/tests/atmega8/i2c/hd44780_avr/hd44780_avr.h b/tests/atmega8/i2c/hd44780_avr/hd44780_avr.h new file mode 100644 index 0000000000000..4a51a1af87b1a --- /dev/null +++ b/tests/atmega8/i2c/hd44780_avr/hd44780_avr.h @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_hd44780 HD44780 LCD driver + * @ingroup drivers_display + * @brief Driver for the Hitachi HD44780 LCD driver + * + * @note The driver currently supports direct addressing, no I2C + * + * @{ + * + * @file + * @brief Interface definition for the HD44780 LCD driver + * + * @author Sebastian Meiling + */ +#ifndef HD44780_H +#define HD44780_H + +#include + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximal number of columns supported by the driver + */ +#define HD44780_MAX_COLS (40U) + +/** + * @brief Maximal number of rows supported by the driver + */ +#define HD44780_MAX_ROWS (4U) + +/** + * @brief Number of data pins for communication 4 or 8. + */ +#define HD44780_MAX_PINS (8U) + +/** + * @brief Size of RAM for custom chars + * + * Generally the driver could support 8 chars of size 5x8 or 4 of size 5x10. + * However, most displays only use the former, which is (hard wired) default. + */ +#define HD44780_CGRAM_SIZE (8U) + +/** + * @brief Parameters needed for device initialization + */ +typedef struct { + uint8_t cols; /**< number of LCD cols */ + uint8_t rows; /**< number of LCD rows */ + gpio_t rs; /**< rs gpio pin */ + gpio_t rw; /**< rw gpio pin */ + gpio_t enable; /**< enable gpio pin */ + gpio_t data[HD44780_MAX_PINS]; /**< data gpio pins */ +} hd44780_params_t; + +/** + * @brief Device descriptor for HD44780 LCD + */ +typedef struct { + hd44780_params_t p; /**< LCD config parameters */ + uint8_t flag; /**< LCD functional flags */ + uint8_t ctrl; /**< LCD control flags */ + uint8_t mode; /**< LCD mode flags */ + uint8_t roff[HD44780_MAX_ROWS]; /**< offsets for LCD rows */ +} hd44780_t; + +/** + * @brief Simple state values + */ +typedef enum { + HD44780_OFF, /**< disable feature */ + HD44780_ON /**< enable feature */ +} hd44780_state_t; + +/** + * @brief Initialize the given driver + * + * @param[out] dev device descriptor of display to initialize + * @param[in] params configuration parameters + * + * @return 0 on success, otherwise error + */ +int hd44780_init(hd44780_t *dev, const hd44780_params_t *params); + +/** + * @brief Clear display, delete all chars + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_clear(const hd44780_t *dev); + +/** + * @brief Reset cursor to row 0 and column 0 + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_home(const hd44780_t *dev); + +/** + * @brief Set cursor to specific position in column and row + * + * @param[in] dev device descriptor of LCD + * @param[in] col column position + * @param[in] row row position + */ +void hd44780_set_cursor(const hd44780_t *dev, uint8_t col, uint8_t row); + +/** + * @brief Turn display on or off + * + * @param[in] dev device descriptor of LCD + * @param[in] state display on or off + */ +void hd44780_display(hd44780_t *dev, hd44780_state_t state); + +/** + * @brief Show cursor, on or off + * + * @param[in] dev device descriptor of LCD + * @param[in] state cursor on or off + */ +void hd44780_cursor(hd44780_t *dev, hd44780_state_t state); + +/** + * @brief Blink cursor, on or off + * + * @param[in] dev device descriptor of LCD + * @param[in] state blink on or off + */ +void hd44780_blink(hd44780_t *dev, hd44780_state_t state); + +/** + * @brief Enable left scrolling + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_scroll_left(const hd44780_t *dev); + +/** + * @brief Enable right scrolling + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_scroll_right(const hd44780_t *dev); + +/** + * @brief Set display direction left to right + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_left2right(hd44780_t *dev); + +/** + * @brief Set display direction right to left + * + * @param[in] dev device descriptor of LCD + */ +void hd44780_right2left(hd44780_t *dev); + +/** + * @brief Display autoscroll on or off + * + * @param[in] dev device descriptor of LCD + * @param[in] state scroll on or off + */ +void hd44780_autoscroll(hd44780_t *dev, hd44780_state_t state); + +/** + * @brief Create and store a custom character on display memory + * + * @param[in] dev device descriptor of LCD + * @param[in] location memory location + * @param[in] charmap character bitmap + * + * @pre charmap has to be of size HD44780_CGRAM_SIZE, which is 8 by default + */ +void hd44780_create_char(const hd44780_t *dev, uint8_t location, uint8_t charmap[]); + +/** + * @brief Write a single character on the LCD + * + * @param[in] dev device descriptor of LCD + * @param[in] value the character to print, i.e., memory location + */ +void hd44780_write(const hd44780_t *dev, uint8_t value); + +/** + * @brief Write a string on the LCD + * + * @param[in] dev device descriptor of LCD + * @param[in] data the string to print + */ +void hd44780_print(const hd44780_t *dev, const char *data); + +#ifdef __cplusplus +} +#endif + +#endif /* HD44780_H */ +/** @} */ diff --git a/tests/atmega8/i2c/hd44780_avr/hd44780_avr_internal.h b/tests/atmega8/i2c/hd44780_avr/hd44780_avr_internal.h new file mode 100644 index 0000000000000..6d3d57e0e4e58 --- /dev/null +++ b/tests/atmega8/i2c/hd44780_avr/hd44780_avr_internal.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_hd44780 + * + * @{ + * @file + * @brief Internal config and parameters for the HD44780 display + * + * @author Sebastian Meiling + */ + +#ifndef HD44780_INTERNAL_H +#define HD44780_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name HD44780 LCD commands + * @{ + */ +#define HD44780_CLEARDISPLAY (0x01) +#define HD44780_RETURNHOME (0x02) +#define HD44780_ENTRYMODESET (0x04) +#define HD44780_DISPLAYCONTROL (0x08) +#define HD44780_CURSORSHIFT (0x10) +#define HD44780_FUNCTIONSET (0x20) +#define HD44780_SETCGRAMADDR (0x40) +#define HD44780_SETDDRAMADDR (0x80) +/** @} */ + +/** + * @name HD44780 LCD entry modes flags + * @{ + */ +#define HD44780_ENTRYRIGHT (0x00) +#define HD44780_ENTRYLEFT (0x02) +#define HD44780_ENTRYSHIFTINCREMENT (0x01) +#define HD44780_ENTRYSHIFTDECREMENT (0x00) +/** @} */ + +/** + * @name HD44780 LCD control flags + * @{ + */ +#define HD44780_DISPLAYON (0x04) +#define HD44780_DISPLAYOFF (0x00) +#define HD44780_CURSORON (0x02) +#define HD44780_CURSOROFF (0x00) +#define HD44780_BLINKON (0x01) +#define HD44780_BLINKOFF (0x00) +/** @} */ + +/** + * @name HD44780 display and cursor shift flags + * @{ + */ +#define HD44780_DISPLAYMOVE (0x08) +#define HD44780_CURSORMOVE (0x00) +#define HD44780_MOVERIGHT (0x04) +#define HD44780_MOVELEFT (0x00) +/**@}*/ + +/** + * @name HD44780 LCD functional flags + * @{ + */ +#define HD44780_8BITMODE (0x10) +#define HD44780_4BITMODE (0x00) +#define HD44780_2LINE (0x08) +#define HD44780_1LINE (0x00) +#define HD44780_5x10DOTS (0x04) +#define HD44780_5x8DOTS (0x00) +/** @} */ + +/** + * @name HD44780 LCD timings + * @{ + */ +#define HD44780_CMD_WAIT (2000U) +#define HD44780_INIT_WAIT_XXL (50000U) +#define HD44780_INIT_WAIT_LONG (4500U) +#define HD44780_INIT_WAIT_SHORT (150U) +#define HD44780_PULSE_WAIT_SHORT (1U) +#define HD44780_PULSE_WAIT_LONG (100U) +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HD44780_INTERNAL_H */ +/** @} */ diff --git a/tests/atmega8/i2c/hd44780_avr/hd44780_avr_params.h b/tests/atmega8/i2c/hd44780_avr/hd44780_avr_params.h new file mode 100644 index 0000000000000..51c65c6327bf2 --- /dev/null +++ b/tests/atmega8/i2c/hd44780_avr/hd44780_avr_params.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_hd44780 + * + * @{ + * @file + * @brief Pinout config for the HD44780 display + * + * @author Sebastian Meiling + */ +#ifndef HD44780_PARAMS_H +#define HD44780_PARAMS_H + +#include "board.h" +#ifdef MODULE_PCF857X +#include "pcf857x.h" +#else +#include "periph/gpio.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* The default pins corresponds to Arduino pins on the Arduino Zero board. */ + +#ifndef HD44780_PARAM_COLS +#define HD44780_PARAM_COLS (16U) +#endif +#ifndef HD44780_PARAM_ROWS +#define HD44780_PARAM_ROWS (2U) +#endif + +#ifndef MODULE_PCF857X + +#ifndef HD44780_PARAM_PIN_RS +#define HD44780_PARAM_PIN_RS GPIO_PIN(0, 14) /* Arduino D2 */ +#endif +#ifndef HD44780_PARAM_PIN_RW +#define HD44780_PARAM_PIN_RW GPIO_UNDEF +#endif +#ifndef HD44780_PARAM_PIN_ENABLE +#define HD44780_PARAM_PIN_ENABLE GPIO_PIN(0, 9) /* Arduino D3 */ +#endif +#ifndef HD44780_PARAM_PINS_DATA +#define HD44780_PARAM_PINS_DATA { GPIO_PIN(0, 8), /* Arduino D4 */ \ + GPIO_PIN(0, 15), /* Arduino D5 */ \ + GPIO_PIN(0, 20), /* Arduino D6 */ \ + GPIO_PIN(0, 21), /* Arduino D7 */ \ + GPIO_UNDEF, \ + GPIO_UNDEF, \ + GPIO_UNDEF, \ + GPIO_UNDEF } +#endif + +#else /* !MODULE_PCF857X */ + +#ifndef HD44780_PARAM_PIN_RS +#define HD44780_PARAM_PIN_RS PCF857X_GPIO_PIN(0, 0) /* Bit 0 */ +#endif +#ifndef HD44780_PARAM_PIN_RW +#define HD44780_PARAM_PIN_RW PCF857X_GPIO_PIN(0, 1) /* Bit 1 */ +#endif +#ifndef HD44780_PARAM_PIN_ENABLE +#define HD44780_PARAM_PIN_ENABLE PCF857X_GPIO_PIN(0, 2) /* Bit 2 */ +#endif +#ifndef HD44780_PARAM_PINS_DATA +#define HD44780_PARAM_PINS_DATA { PCF857X_GPIO_PIN(0, 4), /* Bit 4 */ \ + PCF857X_GPIO_PIN(0, 5), /* Bit 5 */ \ + PCF857X_GPIO_PIN(0, 6), /* Bit 6 */ \ + PCF857X_GPIO_PIN(0, 7), /* Bit 7 */ \ + GPIO_UNDEF, \ + GPIO_UNDEF, \ + GPIO_UNDEF, \ + GPIO_UNDEF } +#endif + +#endif /* !MODULE_PCF857X */ + +#ifndef HD44780_PARAMS +#define HD44780_PARAMS { .cols = HD44780_PARAM_COLS, \ + .rows = HD44780_PARAM_ROWS, \ + .rs = HD44780_PARAM_PIN_RS, \ + .rw = HD44780_PARAM_PIN_RW, \ + .enable = HD44780_PARAM_PIN_ENABLE, \ + .data = HD44780_PARAM_PINS_DATA } +#endif + +/** + * @brief LCM1602C configuration + */ +static const hd44780_params_t hd44780_params[] = +{ + HD44780_PARAMS, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* HD44780_PARAMS_H */ +/** @} */ diff --git a/tests/atmega8/i2c/main.c b/tests/atmega8/i2c/main.c new file mode 100644 index 0000000000000..f37790579dbd6 --- /dev/null +++ b/tests/atmega8/i2c/main.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Application to test i2c on atmega8 using an hacked + * hd44780 LCD driver and a pcf8574a i2c I/O expander. + * + * @author Sebastian Meiling + * @author Hugues Larrive + * + * @} + */ + +#include + +#include "hd44780_avr/hd44780_avr.h" +#include "hd44780_avr/hd44780_avr_params.h" + +int main(void) +{ + hd44780_t dev; + /* init display */ + hd44780_init(&dev, &hd44780_params[0]); + hd44780_clear(&dev); + hd44780_home(&dev); + hd44780_print(&dev, "Test i2c on atmega8"); + hd44780_set_cursor(&dev, 3, 1); + hd44780_print(&dev, "RIOT is here!"); + hd44780_set_cursor(&dev, 0, 2); + hd44780_print(&dev, "You can read this so"); + hd44780_set_cursor(&dev, 2, 3); + hd44780_print(&dev, "i2c is working!"); + + return 0; +} diff --git a/tests/atmega8/pwm/Makefile b/tests/atmega8/pwm/Makefile new file mode 100644 index 0000000000000..8ea3df5a4a63d --- /dev/null +++ b/tests/atmega8/pwm/Makefile @@ -0,0 +1,9 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +FEATURES_REQUIRED = periph_pwm + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/pwm/README.md b/tests/atmega8/pwm/README.md new file mode 100644 index 0000000000000..23b0c052e0d51 --- /dev/null +++ b/tests/atmega8/pwm/README.md @@ -0,0 +1,8 @@ +Expected result +=============== +If everything is running as supposed to, you should see a 1KHz PWM with oscillating duty cycle +on each channel of the selected PWM device. + +Background +========== +Test for the low-level PWM driver. diff --git a/tests/atmega8/pwm/main.c b/tests/atmega8/pwm/main.c new file mode 100644 index 0000000000000..b470bf3bfb70d --- /dev/null +++ b/tests/atmega8/pwm/main.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014-2015 Freie Universität Berlin + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test for low-level PWM drivers + * + * This test initializes the given PWM device to run at 1KHz with a 1000 step + * resolution. + * + * The PWM is then continuously oscillating it's duty cycle between 0% to 100% + * every 1s on every channel. + * + * @author Hauke Petersen + * @author Semjon Kerner + * @author Hugues Larrive + * + * @} + */ + +#include +#include +#include +#include + +#include "periph/pwm.h" + +#define F_CPU (CLOCK_CORECLOCK) +#define __DELAY_BACKWARD_COMPATIBLE__ +#include "util/delay.h" + +#define OSC_INTERVAL (400) /* 400us */ +#define OSC_STEP (10) +#define OSC_MODE PWM_LEFT +#define OSC_FREQU (1000U) +#define OSC_STEPS (256U) +#define PWR_SLEEP (1U) + +static uint32_t initialized; + +static int _oscillate(void) +{ + int state = 0; + int step = OSC_STEP; + + puts("\nRIOT PWM test"); + puts("Connect an LED or scope to PWM pins to see something.\n"); + + printf("Available PWM device between 0 and %d\n", PWM_NUMOF - 1); + for (unsigned i = 0; i < PWM_NUMOF; i++) { + uint32_t real_f = pwm_init(PWM_DEV(i), OSC_MODE, OSC_FREQU, OSC_STEPS); + if (real_f == 0) { + printf("Error: initializing PWM_%u.\n", i); + return 1; + } + else { + printf("Initialized PWM_%u @ %" PRIu32 "Hz.\n", i, real_f); + } + } + + puts("\nLetting the PWM pin (PB3 on atmega8) oscillate now..."); + while (1) { + for (unsigned i = 0; i < PWM_NUMOF; i++) { + for (uint8_t chan = 0; chan < pwm_channels(PWM_DEV(i)); chan++) { + pwm_set(PWM_DEV(i), chan, state); + } + } + + state += step; + if (state <= 0 || state >= (int)OSC_STEPS) { + step = -step; + } + + _delay_us(OSC_INTERVAL); + } + + return 0; +} + +int main(void) +{ + puts("PWM peripheral driver test\n"); + initialized = 0; + + _oscillate(); + + return 0; +} diff --git a/tests/atmega8/shell/Makefile b/tests/atmega8/shell/Makefile new file mode 100644 index 0000000000000..dce740465bfe7 --- /dev/null +++ b/tests/atmega8/shell/Makefile @@ -0,0 +1,16 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +USEMODULE += shell_cmds_default +#~ USEMODULE += ps +DEVELHELP = 0 + +CFLAGS += -DNDEBUG -DLOG_LEVEL=LOG_NONE +DISABLE_MODULE += core_msg +CFLAGS += -DTHREAD_STACKSIZE_IDLE=74 +CFLAGS += -DTHREAD_STACKSIZE_MAIN=150 + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/shell/ReadMe.txt b/tests/atmega8/shell/ReadMe.txt new file mode 100644 index 0000000000000..16bf30e2416f5 --- /dev/null +++ b/tests/atmega8/shell/ReadMe.txt @@ -0,0 +1,14 @@ +This application shows how to use own or the system shell commands. In order to use +the system shell commands: + +1. Additionally to the module: shell, shell_commands, + the module for the corresponding system command is to include, e.g. + module ps for the ps command (cf. the Makefile in the application root + directory). +2. Start the shell like this: + 2.1 reserve buffer: + char line_buf[SHELL_DEFAULT_BUFSIZE]; + 2.1a run shell only with system commands: + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + 2.1b run shell with provided commands in addition to system commands: + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); diff --git a/tests/atmega8/shell/main.c b/tests/atmega8/shell/main.c new file mode 100644 index 0000000000000..aaf48314752a3 --- /dev/null +++ b/tests/atmega8/shell/main.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Kaspar Schleiser + * Copyright (C) 2013 Freie Universität Berlin + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @file + * @brief shows how to set up own and use the system shell commands. + * By typing help in the serial console, all the supported commands + * are listed. + * + * @author Kaspar Schleiser + * @author Zakaria Kasmi + * @author Hugues Larrive + * + */ + +#include +#include + +#include "shell.h" + +/* define buffer to be used by the shell. Note: This is intentionally + * smaller than 64 bytes, as the EDBG integrated UART bridge of the samr21-xpro + * (and likely all other EDBG boards) drops chars when sending more than 64 + * bytes at a time. This results in the buffer overflow test failing. */ +static char line_buf[16]; + +static int print_teststart(int argc, char **argv) +{ + (void)argc; + (void)argv; + printf("[TEST_START]\n"); + + return 0; +} + +static int print_testend(int argc, char **argv) +{ + (void)argc; + (void)argv; + printf("[TEST_END]\n"); + + return 0; +} + +static int print_shell_bufsize(int argc, char **argv) +{ + (void)argc; + (void)argv; + printf("%d\n", sizeof(line_buf)); + + return 0; +} + +static int print_echo(int argc, char **argv) +{ + for (int i = 0; i < argc; ++i) { + printf("\"%s\"", argv[i]); + } + puts(""); + + return 0; +} + +static int print_empty(int argc, char **argv) +{ + (void)argc; + (void)argv; + return 0; +} + +static const shell_command_t shell_commands[] = { + { "start_test", "starts a test", print_teststart }, + { "end_test", "ends a test", print_testend }, + { "bufsize", "Get the shell's buffer size", print_shell_bufsize }, + { "echo", "prints the input command", print_echo }, + { "empty", "print nothing on command", print_empty }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + printf("test_shell.\n"); + + shell_run(shell_commands, line_buf, sizeof(line_buf)); + + return 0; +} diff --git a/tests/atmega8/spi/Makefile b/tests/atmega8/spi/Makefile new file mode 100644 index 0000000000000..6a133d9ee59c4 --- /dev/null +++ b/tests/atmega8/spi/Makefile @@ -0,0 +1,15 @@ +RIOTBASE ?= $(CURDIR)/../../.. +BOARD ?= atmega8 +PORT ?= /dev/ttyACM0 + +include ../../Makefile.tests_common + +FEATURES_REQUIRED += periph_spi + +DEVELHELP = 0 +CFLAGS += -DNDEBUG -DLOG_LEVEL=LOG_NONE +DISABLE_MODULE += core_msg +CFLAGS += -DTHREAD_STACKSIZE_IDLE=64 +CFLAGS += -DTHREAD_STACKSIZE_MAIN=128 + +include $(RIOTBASE)/Makefile.include diff --git a/tests/atmega8/spi/main.c b/tests/atmega8/spi/main.c new file mode 100644 index 0000000000000..545f939a8db39 --- /dev/null +++ b/tests/atmega8/spi/main.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2023 Hugues Larrive + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Application for testing low-level SPI driver implementations + * + * This implementation covers both, master and slave configurations. + * + * @author Hauke Petersen + * @author Hugues Larrive + * + * @} + */ + +#include +#include +#include + +#include "shell.h" +#include "ps.h" +#include "periph/spi.h" + +#define DEFAULT_SPI_CS_PORT 1 +#define DEFAULT_SPI_CS_PIN 2 + +/** + * @brief Some parameters used for benchmarking + */ +#define BENCH_REDOS (1000) +#define BENCH_SMALL (2) +#define BENCH_LARGE (100) +#define BENCH_PAYLOAD ('b') +#define BENCH_REGADDR (0x23) + +/** + * @brief Benchmark buffers + */ +static uint8_t bench_wbuf[BENCH_LARGE]; +static uint8_t bench_rbuf[BENCH_LARGE]; + +static struct { + spi_t dev; + spi_mode_t mode; + spi_clk_t clk; + spi_cs_t cs; +} spiconf; + +int cmd_init(void) +{ + spiconf.dev = SPI_DEV(0); + spiconf.mode = SPI_MODE_0; + spiconf.clk = SPI_CLK_1MHZ; + spiconf.cs = (spi_cs_t)GPIO_PIN(DEFAULT_SPI_CS_PORT, DEFAULT_SPI_CS_PIN); + spi_init_cs(spiconf.dev, spiconf.cs); + return 0; +} + +int cmd_bench(void) +{ + uint8_t in; + uint8_t out = (uint8_t)BENCH_PAYLOAD; + + if (spiconf.dev == SPI_UNDEF) { + puts("error: SPI is not initialized, please initialize bus first"); + return 1; + } + + /* prepare buffer */ + memset(bench_wbuf, BENCH_PAYLOAD, BENCH_LARGE); + + /* get access to the bus */ + spi_acquire(spiconf.dev, spiconf.cs, spiconf.mode, spiconf.clk); + + puts("### Running some benchmarks ###"); + + /* 1 - write 1000 times 1 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + in = spi_transfer_byte(spiconf.dev, spiconf.cs, false, out); + (void)in; + } + printf(" 1 - write %i times %i byte\n", BENCH_REDOS, 1); + + /* 2 - write 1000 times 2 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + bench_wbuf, NULL, BENCH_SMALL); + } + printf(" 2 - write %i times %i byte\n", BENCH_REDOS, BENCH_SMALL); + + /* 3 - write 1000 times 100 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + bench_wbuf, NULL, BENCH_LARGE); + } + printf(" 3 - write %i times %i byte\n", BENCH_REDOS, BENCH_LARGE); + + /* 4 - write 1000 times 1 byte to register */ + for (int i = 0; i < BENCH_REDOS; i++) { + in = spi_transfer_reg(spiconf.dev, spiconf.cs, BENCH_REGADDR, out); + (void)in; + } + printf(" 4 - write %i times %i byte to register\n", BENCH_REDOS, 1); + + /* 5 - write 1000 times 2 byte to register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + bench_wbuf, NULL, BENCH_SMALL); + } + printf(" 5 - write %i times %i byte to register\n", BENCH_REDOS, BENCH_SMALL); + + /* 6 - write 1000 times 100 byte to register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + bench_wbuf, NULL, BENCH_LARGE); + } + printf(" 6 - write %i times %i byte to register\n", BENCH_REDOS, BENCH_LARGE); + + /* 7 - read 1000 times 2 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + NULL, bench_rbuf, BENCH_SMALL); + } + printf(" 7 - read %i times %i byte\n", BENCH_REDOS, BENCH_SMALL); + + /* 8 - read 1000 times 100 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + NULL, bench_rbuf, BENCH_LARGE); + } + printf(" 8 - read %i times %i byte\n", BENCH_REDOS, BENCH_LARGE); + + /* 9 - read 1000 times 2 byte from register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + NULL, bench_rbuf, BENCH_SMALL); + } + printf(" 9 - read %i times %i byte from register\n", BENCH_REDOS, BENCH_SMALL); + + /* 10 - read 1000 times 100 byte from register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + NULL, bench_rbuf, BENCH_LARGE); + } + printf("10 - read %i times %i byte from register\n", BENCH_REDOS, BENCH_LARGE); + + /* 11 - transfer 1000 times 2 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + bench_wbuf, bench_rbuf, BENCH_SMALL); + } + printf("11 - transfer %i times %i byte\n", BENCH_REDOS, BENCH_SMALL); + + /* 12 - transfer 1000 times 100 byte */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_bytes(spiconf.dev, spiconf.cs, false, + bench_wbuf, bench_rbuf, BENCH_LARGE); + } + printf("12 - transfer %i times %i byte\n", BENCH_REDOS, BENCH_LARGE); + + /* 13 - transfer 1000 times 2 byte from/to register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + bench_wbuf, bench_rbuf, BENCH_SMALL); + } + printf("13 - transfer %i times %i byte to register\n", BENCH_REDOS, BENCH_SMALL); + + /* 14 - transfer 1000 times 100 byte from/to register */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_transfer_regs(spiconf.dev, spiconf.cs, BENCH_REGADDR, + bench_wbuf, bench_rbuf, BENCH_LARGE); + } + printf("14 - transfer %i times %i byte to register\n", BENCH_REDOS, BENCH_LARGE); + + /* 15 - release & acquire the bus 1000 times */ + for (int i = 0; i < BENCH_REDOS; i++) { + spi_release(spiconf.dev); + spi_acquire(spiconf.dev, spiconf.cs, spiconf.mode, spiconf.clk); + } + printf("15 - acquire/release %i times\n", BENCH_REDOS); + + spi_release(spiconf.dev); + puts("### All runs complete ###\n"); + + return 0; +} + +int main(void) +{ + puts("SPI peripheral driver test"); + + printf("There are %i SPI devices configured for your platform.\n", + (int)SPI_NUMOF); + + /* reset local SPI configuration */ + spiconf.dev = SPI_UNDEF; + + cmd_init(); + + while (1) { + cmd_bench(); + } + + return 0; +}