From 05994bd90cb36f10ff72c6a70d7cecc61b67fb2f Mon Sep 17 00:00:00 2001 From: Leo C Date: Fri, 21 Nov 2014 13:49:19 +0100 Subject: Rename pin.. to gpio.. --- avr/Tupfile | 17 +-- avr/cmd_gpio.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++ avr/cmd_pin.c | 328 ----------------------------------------------- avr/command_tbl.c | 45 +++---- avr/gpio.c | 371 +++++++++++++++++++++++++++++++++++++++++++++++++++++ avr/pin.c | 372 ------------------------------------------------------ include/gpio.h | 17 +++ include/pin.h | 17 --- 8 files changed, 744 insertions(+), 750 deletions(-) create mode 100644 avr/cmd_gpio.c delete mode 100644 avr/cmd_pin.c create mode 100644 avr/gpio.c delete mode 100644 avr/pin.c create mode 100644 include/gpio.h delete mode 100644 include/pin.h diff --git a/avr/Tupfile b/avr/Tupfile index acb4aa5..a50b3b9 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -3,10 +3,12 @@ include_rules PROG = stamp-monitor SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c -SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_pin.c cmd_misc.c +SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_gpio.c cmd_misc.c +SRC += cmd_sd.c SRC += env.c xmalloc.c date.c con-utils.c print-utils.c getopt-min.c -SRC += timer.c serial.c i2c.c pcf8583.c -SRC += background.c z180-serv.c z80-if.c pin.c +SRC += timer.c serial.c i2c.c pcf8583.c mmc.c +SRC += background.c z180-serv.c z80-if.c gpio.c +SRC += $(TOP)/fatfs/src/ff.c SRC_Z = ../z180/hdrom.c @@ -22,7 +24,7 @@ INCLUDES += -I$(TOP)/include ############################################################################### -TOOLCHAINDIR = +TOOLCHAINDIR = TOOLCHAIN = avr CC = $(TOOLCHAIN)-gcc @@ -45,8 +47,8 @@ CFLAGS = -g -Os CFLAGS += -mmcu=$(MCU_TARGET) CFLAGS += -std=gnu99 CFLAGS += -Wall -Wextra -CFLAGS += -Wredundant-decls -CFLAGS += -mrelax +CFLAGS += -Wredundant-decls +CFLAGS += -mrelax CFLAGS += -fno-common CFLAGS += -ffunction-sections CFLAGS += -fdata-sections @@ -74,7 +76,7 @@ LDFLAGS += -Wl,--cref !LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map !OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |> !OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss -!SIZE = |> ^ SIZE^ $(SIZE) %f |> +!SIZE = |> ^ SIZE^ $(SIZE) %f |> : foreach $(SRC) | ../z180/hdrom.h |> !cc |> {objs} : $(SRC_Z) |> !cc -D'const=const __flash' |> {objs} @@ -83,4 +85,3 @@ LDFLAGS += -Wl,--cref : $(PROG).elf |> !OBJCOPY |> %B.hex : $(PROG).elf |> !OBJDUMP |> %B.lss : $(PROG).elf |> !SIZE |> - diff --git a/avr/cmd_gpio.c b/avr/cmd_gpio.c new file mode 100644 index 0000000..84723d2 --- /dev/null +++ b/avr/cmd_gpio.c @@ -0,0 +1,327 @@ +#include "common.h" +#include +#include +#include + +#include "command.h" +#include "print-utils.h" +#include "getopt-min.h" +#include "env.h" +#include "gpio.h" +//#include "debug.h" + + + +static const int namestr = GPIO_MAX; +static char *pin_names[GPIO_MAX+1]; +static uint_least8_t pin_names_width; + +static void pinnames_get(void) +{ + static const FLASH char delim1[] = {":= "}; + static const FLASH char delim2[] = {", "}; + char *lp; + char *ptr; + uint_fast8_t i; + + if (pin_names[namestr] != NULL) + free(pin_names[namestr]); + memset(pin_names, 0, sizeof(pin_names)); + pin_names_width = 0; + + if ((lp = getenv(PSTR(ENV_PINALIAS))) != NULL) { + pin_names[namestr] = strdup(lp); + ptr = strtok_P(pin_names[namestr], delim1); + while (ptr != NULL) { + if (((i = strtoul(ptr, &lp, 10)) < GPIO_MAX) && + lp != ptr && + (ptr = strtok_P(NULL, delim2)) != NULL ) { + pin_names[i] = ptr; + ptr = strtok_P(NULL, delim1); + } + } + + for (i = 0; i < GPIO_MAX; i++) + if (strlen(pin_names[i]) > pin_names_width) + pin_names_width = strlen(pin_names[i]); + } +} + + +static size_t xstrlen(char *s) +{ + if (s == NULL) + return 0; + else + return strlen(s); +} + +static const FLASH char * const FLASH pinconf_str[] = { + FSTR("?"), + FSTR("Input"), + FSTR("Pullup"), + FSTR("Output"), + FSTR("Clock"), + }; + +static const FLASH char * const FLASH pinlevel_str[] = { + FSTR("Low"), + FSTR("High"), + FSTR(""), + }; + +static int print_pin(int pin, int multi) +{ + int pinconf; + const FLASH char *levelp; + long div; + + pinconf = gpio_config_get(pin); + if (pinconf == OUTPUT_TIMER) { + div = gpio_clockdiv_get(pin); + levelp = pinlevel_str[2]; + } else + levelp = pinlevel_str[gpio_read(pin)]; + + if (multi) { + printf_P(PSTR("%3d "), pin); + if (pin_names_width) { + printf_P(PSTR("%s "), pin_names[pin]); + print_blanks(pin_names_width - xstrlen(pin_names[pin])); + } + my_puts_P(pinconf_str[pinconf]); + print_blanks(7 - strlen_P(pinconf_str[pinconf])); + my_puts_P(levelp); + print_blanks(5 - strlen_P(levelp)); + if (pinconf == OUTPUT_TIMER) + printf_P(PSTR("%8ld %8ld"), + div, F_CPU/div); + } else { + printf_P(PSTR("%d: \"%s\", "), pin, pin_names[pin] ? pin_names[pin] : 0); + my_puts_P(pinconf_str[pinconf]); + printf_P(PSTR(", ")); + my_puts_P(levelp); + + if (pinconf == OUTPUT_TIMER) + printf_P(PSTR("divide by %ld (%ldHz)"), + div, F_CPU/div); + } + printf_P(PSTR("\n")); + + return 0; +} + +static int_fast8_t pinarg_insert(int pin, uint_fast8_t count, uint_fast8_t pinarg[]) +{ + uint_fast8_t pos; + + if (pin < 0 || pin >= GPIO_MAX) + return -1; + + for (pos = 0; pos < count; pos++) { + if (pin == pinarg[pos]) + return 0; + if (pin < pinarg[pos]) + break; + } + for (uint_fast8_t i = count-1; i == pos ; i--) + pinarg[i+1] = pinarg[i]; + pinarg[pos] = pin; + + return 1; +} + +static uint_fast8_t pinarg_get(char * arg, uint_fast8_t pinarg[]) +{ + char *endp; + uint_fast8_t pin1; + int_fast8_t rc; + uint_fast8_t count = 0; + + while (1) { + pin1 = strtoul(arg, &endp, 10); + if (endp != arg && *endp == '-') { + arg = endp+1; + uint_fast8_t pin2 = (int) strtoul(arg, &endp, 10); + if (pin1 < pin2) + for (; pin1 < pin2; pin1++) + if ((rc = pinarg_insert(pin1, count, pinarg)) >= 0) + count += rc; + else + return 0; + else + return 0; + } + if (endp != arg) { + if ((*endp == ',' || *endp == '\0') && + (rc = pinarg_insert(pin1, count, pinarg)) >= 0) { + count += rc; + if (*endp == '\0') + return count; + } else + return 0; + } else + return 0; + + arg = endp+1; + } +} + + +command_ret_t do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + char printheader = 1; + uint_fast8_t pinarg[GPIO_MAX]; + uint_fast8_t pinargc; + + (void) cmdtp; (void) flag; + + /* reset getopt() */ + optind = 1; + + int opt; + while ((opt = getopt(argc, argv, PSTR("s"))) != -1) { + switch (opt) { + case 's': + printheader = 0; + break; + default: /* '?' */ + return CMD_RET_USAGE; + } + } + + /* remaining arguments */ + argc -= optind; + + pinnames_get(); + + if (argc == 0) { + /* print cofig of all pins */ + for (pinargc = 0; pinargc < GPIO_MAX; pinargc++) + pinarg[pinargc] = pinargc; + } else { + /* get first arg */ + pinargc = pinarg_get(argv[optind++], pinarg); + if (pinargc == 0) + return CMD_RET_USAGE; + else + argc--; + } + + if (argc == 0) { + /* no more args, print config */ + if (pinargc == 1) + print_pin(pinarg[0], 0); + else { + if (printheader) { + if (pin_names_width > 0) { + if ( strlen("Name") > pin_names_width) + pin_names_width = strlen("Name"); + char s[pin_names_width+1]; + memset(s, ' ', pin_names_width); + s[pin_names_width] = '\0'; + strncpy_P(s, PSTR("Name"), 4); + printf_P(PSTR("Pin %s Config Level Divider Frequency/Hz\n"),s); + memset(s, '-', pin_names_width); + printf_P(PSTR("----%s-----------------------------------\n"), s); + } else + printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" + "--------------------------------------\n")); + } + for (uint_fast8_t i = 0; i < pinargc; i++) + print_pin(pinarg[i], 1); + } + return CMD_RET_SUCCESS; + } + + /* arguments must be in pairs: pins conf */ + if (argc % 2 != 1) + return CMD_RET_USAGE; + + while (argc > 0) { + char *endp; + gpiomode_t mode = NONE; + int level = 0; + unsigned long value = 0; + uint8_t hz_flag = 0; + + switch (toupper(argv[optind][0])) { + case 'H': + level = 1; + case 'L': + mode = OUTPUT; + break; + case 'P': + mode = INPUT_PULLUP; + break; + case 'I': + case 'T': + mode = INPUT; + break; + + default: + value = strtoul(argv[optind], &endp, 10); + switch (*endp) { + case 'M': + value *= 1000; + case 'K': + value *= 1000; + endp++; + } + + if (*endp && strcmp_P(endp, PSTR("Hz")) == 0) { + hz_flag = 1; + endp += 2; + } + + if (*endp != '\0') { + printf_P(PSTR("invalid parameter: '%s'\n"), argv[optind]); + return CMD_RET_USAGE; + } + + if (value == 0) { + printf_P(PSTR("invalid value: %lu \n")); + return CMD_RET_USAGE; + } + + if (hz_flag) { + if (value > F_CPU / 2) { + printf_P(PSTR("Max frequency is: %luHz\n"), F_CPU/2); + return CMD_RET_USAGE; + } + value = F_CPU/value; + } + mode = OUTPUT_TIMER; + + } + + if (mode == NONE) + return CMD_RET_USAGE; + + for (uint_fast8_t i = 0; i < pinargc; i++) { + switch (mode) { + case OUTPUT: + gpio_write(pinarg[i], level); + /* fall thru */ + case INPUT: + case INPUT_PULLUP: + gpio_config(pinarg[i], mode); + break; + case OUTPUT_TIMER: + if (gpio_clockdiv_set(pinarg[i], value) < 0) { + printf_P(PSTR("Setting pin %d to %lu failed.\n"), + pinarg[i], value); + } + break; + default: + break; + } + } + + optind++; + pinargc = pinarg_get(argv[optind++], pinarg); + argc -= 2; + } + + return CMD_RET_SUCCESS; +} diff --git a/avr/cmd_pin.c b/avr/cmd_pin.c deleted file mode 100644 index 83a55f7..0000000 --- a/avr/cmd_pin.c +++ /dev/null @@ -1,328 +0,0 @@ -#include "common.h" -#include -#include -#include - -#include "command.h" -#include "print-utils.h" -#include "getopt-min.h" -#include "env.h" -#include "pin.h" -//#include "debug.h" - - - -static const int namestr = PIN_MAX; -static char *pin_names[PIN_MAX+1]; -static uint_least8_t pin_names_width; - -static void pinnames_get(void) -{ - static const FLASH char delim1[] = {":= "}; - static const FLASH char delim2[] = {", "}; - char *lp; - char *ptr; - uint_fast8_t i; - - if (pin_names[namestr] != NULL) - free(pin_names[namestr]); - memset(pin_names, 0, sizeof(pin_names)); - pin_names_width = 0; - - if ((lp = getenv(PSTR(ENV_PINALIAS))) != NULL) { - pin_names[namestr] = strdup(lp); - ptr = strtok_P(pin_names[namestr], delim1); - while (ptr != NULL) { - if (((i = strtoul(ptr, &lp, 10)) < PIN_MAX) && - lp != ptr && - (ptr = strtok_P(NULL, delim2)) != NULL ) { - pin_names[i] = ptr; - ptr = strtok_P(NULL, delim1); - } - } - - for (i = 0; i < PIN_MAX; i++) - if (strlen(pin_names[i]) > pin_names_width) - pin_names_width = strlen(pin_names[i]); - } -} - - -static size_t xstrlen(char *s) -{ - if (s == NULL) - return 0; - else - return strlen(s); -} - -static const FLASH char * const FLASH pinconf_str[] = { - FSTR("?"), - FSTR("Input"), - FSTR("Pullup"), - FSTR("Output"), - FSTR("Clock"), - }; - -static const FLASH char * const FLASH pinlevel_str[] = { - FSTR("Low"), - FSTR("High"), - FSTR(""), - }; - -static int print_pin(int pin, int multi) -{ - int pinconf; - const FLASH char *levelp; - long div; - - pinconf = pin_config_get(pin); - if (pinconf == OUTPUT_TIMER) { - div = pin_clockdiv_get(pin); - levelp = pinlevel_str[2]; - } else - levelp = pinlevel_str[pin_read(pin)]; - - if (multi) { - printf_P(PSTR("%3d "), pin); - if (pin_names_width) { - printf_P(PSTR("%s "), pin_names[pin]); - print_blanks(pin_names_width - xstrlen(pin_names[pin])); - } - my_puts_P(pinconf_str[pinconf]); - print_blanks(7 - strlen_P(pinconf_str[pinconf])); - my_puts_P(levelp); - print_blanks(5 - strlen_P(levelp)); - if (pinconf == OUTPUT_TIMER) - printf_P(PSTR("%8ld %8ld"), - div, F_CPU/div); - } else { - printf_P(PSTR("%d: \"%s\", "), pin, pin_names[pin] ? pin_names[pin] : 0); - my_puts_P(pinconf_str[pinconf]); - printf_P(PSTR(", ")); - my_puts_P(levelp); - - if (pinconf == OUTPUT_TIMER) - printf_P(PSTR("divide by %ld (%ldHz)"), - div, F_CPU/div); - } - printf_P(PSTR("\n")); - - return 0; -} - -static int_fast8_t pinarg_insert(int pin, uint_fast8_t count, uint_fast8_t pinarg[]) -{ - uint_fast8_t pos; - - if (pin < 0 || pin >= PIN_MAX) - return -1; - - for (pos = 0; pos < count; pos++) { - if (pin == pinarg[pos]) - return 0; - if (pin < pinarg[pos]) - break; - } - for (uint_fast8_t i = count-1; i == pos ; i--) - pinarg[i+1] = pinarg[i]; - pinarg[pos] = pin; - - return 1; -} - -static uint_fast8_t pinarg_get(char * arg, uint_fast8_t pinarg[]) -{ - char *endp; - uint_fast8_t pin1; - int_fast8_t rc; - uint_fast8_t count = 0; - - while (1) { - pin1 = strtoul(arg, &endp, 10); - if (endp != arg && *endp == '-') { - arg = endp+1; - uint_fast8_t pin2 = (int) strtoul(arg, &endp, 10); - if (pin1 < pin2) - for (; pin1 < pin2; pin1++) - if ((rc = pinarg_insert(pin1, count, pinarg)) >= 0) - count += rc; - else - return 0; - else - return 0; - } - if (endp != arg) { - if ((*endp == ',' || *endp == '\0') && - (rc = pinarg_insert(pin1, count, pinarg)) >= 0) { - count += rc; - if (*endp == '\0') - return count; - } else - return 0; - } else - return 0; - - arg = endp+1; - } -} - - -command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - char printheader = 1; - uint_fast8_t pinarg[PIN_MAX]; - uint_fast8_t pinargc; - - (void) cmdtp; (void) flag; - - /* reset getopt() */ - optind = 1; - - int opt; - while ((opt = getopt(argc, argv, PSTR("s"))) != -1) { - switch (opt) { - case 's': - printheader = 0; - break; - default: /* '?' */ - return CMD_RET_USAGE; - } - } - - /* remaining arguments */ - argc -= optind; - - pinnames_get(); - - if (argc == 0) { - /* print cofig of all pins */ - for (pinargc = 0; pinargc < PIN_MAX; pinargc++) - pinarg[pinargc] = pinargc; - } else { - /* get first arg */ - pinargc = pinarg_get(argv[optind++], pinarg); - if (pinargc == 0) - return CMD_RET_USAGE; - else - argc--; - } - - if (argc == 0) { - /* no more args, print config */ - if (pinargc == 1) - print_pin(pinarg[0], 0); - else { - if (printheader) { - if (pin_names_width > 0) { - if ( strlen("Name") > pin_names_width) - pin_names_width = strlen("Name"); - char s[pin_names_width+1]; - memset(s, ' ', pin_names_width); - s[pin_names_width] = '\0'; - strncpy_P(s, PSTR("Name"), 4); - printf_P(PSTR("Pin %s Config Level Divider Frequency/Hz\n"),s); - memset(s, '-', pin_names_width); - printf_P(PSTR("----%s-----------------------------------\n"), s); - } else - printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" - "--------------------------------------\n")); - } - for (uint_fast8_t i = 0; i < pinargc; i++) - print_pin(pinarg[i], 1); - } - return CMD_RET_SUCCESS; - } - - /* arguments must be in pairs: pins conf */ - if (argc % 2 != 1) - return CMD_RET_USAGE; - - while (argc > 0) { - char *endp; - pinmode_t mode = NONE; - int level = 0; - unsigned long value = 0; - uint8_t hz_flag = 0; - - switch (toupper(argv[optind][0])) { - case 'H': - level = 1; - case 'L': - mode = OUTPUT; - break; - case 'P': - mode = INPUT_PULLUP; - break; - case 'I': - case 'T': - mode = INPUT; - break; - - default: - value = strtoul(argv[optind], &endp, 10); - switch (*endp) { - case 'M': - value *= 1000; - case 'K': - value *= 1000; - endp++; - } - - if (*endp && strcmp_P(endp, PSTR("Hz")) == 0) { - hz_flag = 1; - endp += 2; - } - - if (*endp != '\0') { - printf_P(PSTR("invalid parameter: '%s'\n"), argv[optind]); - return CMD_RET_USAGE; - } - - if (value == 0) { - printf_P(PSTR("invalid value: %lu \n")); - return CMD_RET_USAGE; - } - - if (hz_flag) { - if (value > F_CPU / 2) { - printf_P(PSTR("Max frequency is: %luHz\n"), F_CPU/2); - return CMD_RET_USAGE; - } - value = F_CPU/value; - } - mode = OUTPUT_TIMER; - - } - - if (mode == NONE) - return CMD_RET_USAGE; - - for (uint_fast8_t i = 0; i < pinargc; i++) { - switch (mode) { - case OUTPUT: - pin_write(pinarg[i], level); - /* fall thru */ - case INPUT: - case INPUT_PULLUP: - pin_config(pinarg[i], mode); - break; - case OUTPUT_TIMER: - if (pin_clockdiv_set(pinarg[i], value) < 0) { - printf_P(PSTR("Setting pin %d to %lu failed.\n"), - pinarg[i], value); - } - break; - default: - break; - } - } - - optind++; - pinargc = pinarg_get(argv[optind++], pinarg); - argc -= 2; - } - - return CMD_RET_SUCCESS; -} - diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 336c608..97110fd 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -20,7 +20,14 @@ extern command_ret_t do_dump_mem(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_eep_cp(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_busreq_pulse(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_date(cmd_tbl_t *, int, int, char * const []); -extern command_ret_t do_pin(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_gpio(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_sd(cmd_tbl_t *, int, int, char * const []); + +#ifdef CONFIG_SYS_LONGHELP +const FLASH char sd_help_text[] = + "bla \t- do bla\n" + ; +#endif /* CONFIG_SYS_LONGHELP */ cmd_tbl_t cmd_tbl[] = { @@ -134,31 +141,8 @@ CMD_TBL_ITEM( "" ), -#if 0 -CMD_TBL_ITEM( - clock, 2, 0, do_clock, - "Set or get CPU frequency", - "\n" - " - print frequency or state of clock pin\n" - "clock value[K|M]\n" - " - set frequency of clock pin to value\n" - "clock [high|low]\n" - " - set clock pin level high or low" -), CMD_TBL_ITEM( - clk2, 3, 0, do_clock2, - "Set or get clk2 frequency", - "\n" - " - print frequency or state of clk2 pin\n" - "clk2 [-d] value[K|M]\n" - " - set frequency of clk2 pin to value\n" - "clk2 [high|low]\n" - " - set clk2 pin level high or low" -), -#endif - -CMD_TBL_ITEM( - pin, CONFIG_SYS_MAXARGS, 0, do_pin, + pin, CONFIG_SYS_MAXARGS, 1, do_gpio, "Set or query pin state", "[-s] []\n" " - print cofiguration and state or frequency of pins\n" @@ -257,6 +241,17 @@ CMD_TBL_ITEM( " - print detailed usage of 'command'" ), +/* TODO: make macro CMD_TBL_ITEM work with this */ + {FSTR("sd"), CONFIG_SYS_MAXARGS, 1, do_sd, + FSTR("SD/MMC card handling commands"), +#ifdef CONFIG_SYS_LONGHELP + sd_help_text, +#endif /* CONFIG_SYS_LONGHELP */ +#ifdef CONFIG_AUTO_COMPLETE + 0, +#endif +}, + /* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */ {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help, FSTR("alias for 'help'"), diff --git a/avr/gpio.c b/avr/gpio.c new file mode 100644 index 0000000..3c47247 --- /dev/null +++ b/avr/gpio.c @@ -0,0 +1,371 @@ +#include "common.h" +#include +#include +#include "debug.h" +#include "gpio.h" + + +/* + +Pin Name Port Timer Mode max div max div min f [Hz] +---------------------------------------------------------------------------------- +0 PG5 OC0B PWM (2**8)*1024 262144 70.31 +1 PG4 +2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16 +3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746 +4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746 +5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16 +6 PG3 +7 PG2 +8 PG1 +9 PG0 +10 CLKO PE7 + + +pre Timer0 Timer1 Timer2 +-------------------------------------------------- +0 0 0 0 +1 1 1 1 +2 8 x8 8 x8 8 x8 +3 64 x8 64 x8 32 x4 +4 256 x4 256 x4 64 x2 +5 1024 x4 1024 x4 128 x2 +6 256 x2 +7 1024 x4 +-------------------------------------------------- + +*/ + + +#define PWMTOGGLE 0b01 +#define PWMPOS 0b10 +#define PWMNEG 0b11 + + +const FLASH uint8_t prescale_factors_01[] = + { 8, 8, 4, 4, 0 }; + +const FLASH uint8_t prescale_factors_2[] = + { 8, 4, 2, 2, 2, 4, 0 }; + +typedef volatile struct { + uint8_t pin; + uint8_t ddr; + uint8_t pout; +} port_t ; + +struct pindef_s { + port_t * const adr; + const uint8_t mask; +#define NO_TIMER 0 +#define TIMER0 (1 << 0) +#define TIMER1 (2 << 0) +#define TIMER2 (3 << 0) +#define TIMER (3 << 0) +#define T_16BIT (1 << 3) +#define CHANA (1 << 4) +#define CHANB (0 << 4) + const uint8_t timer; +}; + + +const FLASH struct pindef_s pinlist[GPIO_MAX] = { + { (port_t *) &PING, _BV(5), TIMER0 | CHANB }, + { (port_t *) &PING, _BV(4), NO_TIMER }, + { (port_t *) &PINB, _BV(4), TIMER2 | CHANA }, + { (port_t *) &PINB, _BV(5), TIMER1 | CHANA | T_16BIT }, + { (port_t *) &PINB, _BV(6), TIMER1 | CHANB | T_16BIT }, + { (port_t *) &PINB, _BV(7), TIMER0 | CHANA }, + { (port_t *) &PING, _BV(3), NO_TIMER }, + { (port_t *) &PING, _BV(2), NO_TIMER }, + { (port_t *) &PING, _BV(1), NO_TIMER }, + { (port_t *) &PING, _BV(0), NO_TIMER }, + { (port_t *) &PINE, _BV(7), NO_TIMER }, +}; + +void gpio_timer_off(uint8_t timertype) +{ + uint8_t chan_mask; + + if (timertype & CHANA) + chan_mask = 0xc0; + else + chan_mask = 0x30; + + switch (timertype & TIMER) { + case TIMER0: + if (TCCR0A & chan_mask) { + TCCR0B = 0; + TCCR0A = 0; + PRR0 |= _BV(PRTIM0); + } + break; + case TIMER1: + if (TCCR1A & chan_mask) { + TCCR1B = 0; + TCCR1A = 0; + PRR0 |= _BV(PRTIM1); + } + break; + case TIMER2: + if (TCCR2A & chan_mask) { + TCCR2B = 0; + TCCR2A = 0; + PRR0 |= _BV(PRTIM2); + } + break; + } +} + +int gpio_config(int pin, gpiomode_t mode) +{ + if ((unsigned) pin >= ARRAY_SIZE(pinlist)) { + /* Invalid pin number */ + return -1; + } else { + + port_t *p = pinlist[pin].adr; + uint8_t bit = pinlist[pin].mask; + + switch (mode) { + case INPUT: + gpio_timer_off(pinlist[pin].timer); + ATOMIC_BLOCK(ATOMIC_FORCEON) { + p->ddr &= ~bit; + p->pout &= ~bit; + } + break; + case INPUT_PULLUP: + gpio_timer_off(pinlist[pin].timer); + ATOMIC_BLOCK(ATOMIC_FORCEON) { + p->ddr &= ~bit; + p->pout |= bit; + } + break; + case OUTPUT: + gpio_timer_off(pinlist[pin].timer); + case OUTPUT_TIMER: + ATOMIC_BLOCK(ATOMIC_FORCEON) { + p->ddr |= bit; + } + break; + default: + /* Invalid pin mode */ + return -1; + } + } + return 0; +} + +void gpio_write(int pin, uint8_t val) +{ + port_t *p = pinlist[pin].adr; + uint8_t bit = pinlist[pin].mask; + + ATOMIC_BLOCK(ATOMIC_FORCEON) { + if (val) + p->pout |= bit; + else + p->pout &= ~bit; + } +} + +int gpio_read(int pin) +{ + port_t *p = pinlist[pin].adr; + uint8_t bit = pinlist[pin].mask; + + return (p->pin & bit) != 0; +} + +gpiomode_t gpio_config_get(int pin) +{ + uint8_t timertype = pinlist[pin].timer; + + if (timertype & TIMER) { + + uint8_t chan_mask; + if (timertype & CHANA) + chan_mask = 0xc0; + else + chan_mask = 0x30; + + switch (timertype & TIMER) { + case TIMER0: + if (TCCR0A & chan_mask) + return OUTPUT_TIMER; + break; + case TIMER1: + if (TCCR1A & chan_mask) + return OUTPUT_TIMER; + break; + case TIMER2: + if (TCCR2A & chan_mask) + return OUTPUT_TIMER; + break; + } + } + + port_t *p = pinlist[pin].adr; + uint8_t bit = pinlist[pin].mask; + + if (p->ddr & bit) + return OUTPUT; + + if (p->pout & bit) + return INPUT_PULLUP; + + return INPUT; +} + +/* + * return -1: pin has no timer output + * 0: pin is not configured for timer output + * > 0: divider + */ + +long gpio_clockdiv_get(int pin) +{ + long divider; + uint8_t prescale; + const FLASH uint8_t *pstab; + + uint8_t timertype = pinlist[pin].timer; + if ((timertype & TIMER) == 0) + return -1; + + if (gpio_config_get(pin) != OUTPUT_TIMER) + return 0; + + switch (timertype & TIMER) { + case TIMER0: + prescale = TCCR0B; + divider = OCR0A; + break; + + case TIMER1: + prescale = TCCR1B; + divider = ICR1; + break; + + case TIMER2: + prescale = TCCR2B; + divider = OCR2A; + break; + } + + prescale = (prescale & 0x07) - 1; + divider += 1; + + pstab = (timertype & TIMER) == TIMER2 ? + prescale_factors_2 : prescale_factors_01; + + while (prescale--) + divider *= pstab[prescale]; + + if ((timertype & (CHANA|T_16BIT)) == CHANA) + divider *= 2; + + return divider; +} + +int gpio_clockdiv_set(int pin, unsigned long divider) +{ + unsigned long ltop; + uint16_t top; + uint8_t prescale; + const FLASH uint8_t *pstab; + + uint8_t timertype = pinlist[pin].timer; + if ((timertype & TIMER) == 0) + return 0; + + if (divider < 2) + return -1; + + ltop = divider; + if ((timertype & (CHANA|T_16BIT)) == CHANA) + ltop /= 2; + + if (ltop > 1024 * ((timertype & T_16BIT) ? (1L<<16) : (1L<<8))) + return -1; + + prescale = 1; + pstab = (timertype & TIMER) == TIMER2 ? + prescale_factors_2 : prescale_factors_01; + +// debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n", +// pin, ltop, prescale); + + while (ltop > ((timertype & T_16BIT) ? (1L<<16) : (1L<<8))) { +// debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n", +// pin, ltop, prescale, *pstab); + + if (*pstab == 0) + return -1; + ltop /= *pstab++; + prescale++; + } + + if (ltop == 0) + return -1; + + top = ltop - 1; + + PING |= _BV(0); /* Debug */ + + switch (timertype & TIMER) { + case TIMER0: + PRR0 &= ~_BV(PRTIM0); + TCCR0B = (1 << WGM02); + TCNT0 = 0; + OCR0A = top; + if (timertype & CHANA) { + TCCR0A = (PWMTOGGLE << COM0A0) | (0b11 << WGM00); + } else { + OCR0B = top/2; + TCCR0A = (PWMPOS << COM0B0) | (0b11 << WGM10); + } + TCCR0B = (1 << WGM02) | (prescale << CS10); + break; + + case TIMER1: + PRR0 &= ~_BV(PRTIM1); + TCCR1B = (0b11 << WGM12); + TCNT1 = 0; + ICR1 = top; + if (timertype & CHANA) { + OCR1A = top/2; + TCCR1A = (PWMPOS << COM1A0) | (0b10 << WGM10); + } else { + OCR1B = top/2; + TCCR1A = (PWMPOS << COM1B0) | (0b10 << WGM10); + } +// debug("pin: %d, top: %u," +// " ICR1: %u, OCR1A: %u, OCR1B: %u\n", +// pin, top, ICR1, OCR1A, OCR1B); + + TCCR1B = (0b11 << WGM12) | (prescale << CS10); + break; + + case TIMER2: + PRR0 &= ~_BV(PRTIM2); + TCCR2B = (1 << WGM22); + TCNT2 = 0; + OCR2A = top; + if (timertype & CHANA) { + TCCR2A = (PWMTOGGLE << COM2A0) | (0b11 << WGM20); + } else { + OCR2B = top/2; + TCCR2A = (PWMPOS << COM2B0) | (0b11 << WGM10); + } + TCCR2B = (1 << WGM22) | (prescale << CS10); + break; + } + + PING |= _BV(0); /* Debug */ + + gpio_config(pin, OUTPUT_TIMER); + + return 0; +} diff --git a/avr/pin.c b/avr/pin.c deleted file mode 100644 index 6e88aa5..0000000 --- a/avr/pin.c +++ /dev/null @@ -1,372 +0,0 @@ -#include "common.h" -#include -#include -#include "debug.h" -#include "pin.h" - - -/* - -Pin Name Port Timer Mode max div max div min f [Hz] ----------------------------------------------------------------------------------- -0 PG5 OC0B PWM (2**8)*1024 262144 70.31 -1 PG4 -2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16 -3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746 -4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746 -5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16 -6 PG3 -7 PG2 -8 PG1 -9 PG0 -10 CLKO PE7 - - -pre Timer0 Timer1 Timer2 --------------------------------------------------- -0 0 0 0 -1 1 1 1 -2 8 x8 8 x8 8 x8 -3 64 x8 64 x8 32 x4 -4 256 x4 256 x4 64 x2 -5 1024 x4 1024 x4 128 x2 -6 256 x2 -7 1024 x4 --------------------------------------------------- - -*/ - - -#define PWMTOGGLE 0b01 -#define PWMPOS 0b10 -#define PWMNEG 0b11 - - -const FLASH uint8_t prescale_factors_01[] = - { 8, 8, 4, 4, 0 }; - -const FLASH uint8_t prescale_factors_2[] = - { 8, 4, 2, 2, 2, 4, 0 }; - -typedef volatile struct { - uint8_t pin; - uint8_t ddr; - uint8_t pout; -} port_t ; - -struct pindef_s { - port_t * const adr; - const uint8_t mask; -#define NO_TIMER 0 -#define TIMER0 (1 << 0) -#define TIMER1 (2 << 0) -#define TIMER2 (3 << 0) -#define TIMER (3 << 0) -#define T_16BIT (1 << 3) -#define CHANA (1 << 4) -#define CHANB (0 << 4) - const uint8_t timer; -}; - - -const FLASH struct pindef_s pinlist[PIN_MAX] = { - { (port_t *) &PING, _BV(5), TIMER0 | CHANB }, - { (port_t *) &PING, _BV(4), NO_TIMER }, - { (port_t *) &PINB, _BV(4), TIMER2 | CHANA }, - { (port_t *) &PINB, _BV(5), TIMER1 | CHANA | T_16BIT }, - { (port_t *) &PINB, _BV(6), TIMER1 | CHANB | T_16BIT }, - { (port_t *) &PINB, _BV(7), TIMER0 | CHANA }, - { (port_t *) &PING, _BV(3), NO_TIMER }, - { (port_t *) &PING, _BV(2), NO_TIMER }, - { (port_t *) &PING, _BV(1), NO_TIMER }, - { (port_t *) &PING, _BV(0), NO_TIMER }, - { (port_t *) &PINE, _BV(7), NO_TIMER }, -}; - -void pin_timer_off(uint8_t timertype) -{ - uint8_t chan_mask; - - if (timertype & CHANA) - chan_mask = 0xc0; - else - chan_mask = 0x30; - - switch (timertype & TIMER) { - case TIMER0: - if (TCCR0A & chan_mask) { - TCCR0B = 0; - TCCR0A = 0; - PRR0 |= _BV(PRTIM0); - } - break; - case TIMER1: - if (TCCR1A & chan_mask) { - TCCR1B = 0; - TCCR1A = 0; - PRR0 |= _BV(PRTIM1); - } - break; - case TIMER2: - if (TCCR2A & chan_mask) { - TCCR2B = 0; - TCCR2A = 0; - PRR0 |= _BV(PRTIM2); - } - break; - } -} - -int pin_config(int pin, pinmode_t mode) -{ - if ((unsigned) pin >= ARRAY_SIZE(pinlist)) { - /* Invalid pin number */ - return -1; - } else { - - port_t *p = pinlist[pin].adr; - uint8_t bit = pinlist[pin].mask; - - switch (mode) { - case INPUT: - pin_timer_off(pinlist[pin].timer); - ATOMIC_BLOCK(ATOMIC_FORCEON) { - p->ddr &= ~bit; - p->pout &= ~bit; - } - break; - case INPUT_PULLUP: - pin_timer_off(pinlist[pin].timer); - ATOMIC_BLOCK(ATOMIC_FORCEON) { - p->ddr &= ~bit; - p->pout |= bit; - } - break; - case OUTPUT: - pin_timer_off(pinlist[pin].timer); - case OUTPUT_TIMER: - ATOMIC_BLOCK(ATOMIC_FORCEON) { - p->ddr |= bit; - } - break; - default: - /* Invalid pin mode */ - return -1; - } - } - return 0; -} - -void pin_write(int pin, uint8_t val) -{ - port_t *p = pinlist[pin].adr; - uint8_t bit = pinlist[pin].mask; - - ATOMIC_BLOCK(ATOMIC_FORCEON) { - if (val) - p->pout |= bit; - else - p->pout &= ~bit; - } -} - -int pin_read(int pin) -{ - port_t *p = pinlist[pin].adr; - uint8_t bit = pinlist[pin].mask; - - return (p->pin & bit) != 0; -} - -pinmode_t pin_config_get(int pin) -{ - uint8_t timertype = pinlist[pin].timer; - - if (timertype & TIMER) { - - uint8_t chan_mask; - if (timertype & CHANA) - chan_mask = 0xc0; - else - chan_mask = 0x30; - - switch (timertype & TIMER) { - case TIMER0: - if (TCCR0A & chan_mask) - return OUTPUT_TIMER; - break; - case TIMER1: - if (TCCR1A & chan_mask) - return OUTPUT_TIMER; - break; - case TIMER2: - if (TCCR2A & chan_mask) - return OUTPUT_TIMER; - break; - } - } - - port_t *p = pinlist[pin].adr; - uint8_t bit = pinlist[pin].mask; - - if (p->ddr & bit) - return OUTPUT; - - if (p->pout & bit) - return INPUT_PULLUP; - - return INPUT; -} - -/* - * return -1: pin has no timer output - * 0: pin is not configured for timer output - * > 0: divider - */ - -long pin_clockdiv_get(int pin) -{ - long divider; - uint8_t prescale; - const FLASH uint8_t *pstab; - - uint8_t timertype = pinlist[pin].timer; - if ((timertype & TIMER) == 0) - return -1; - - if (pin_config_get(pin) != OUTPUT_TIMER) - return 0; - - switch (timertype & TIMER) { - case TIMER0: - prescale = TCCR0B; - divider = OCR0A; - break; - - case TIMER1: - prescale = TCCR1B; - divider = ICR1; - break; - - case TIMER2: - prescale = TCCR2B; - divider = OCR2A; - break; - } - - prescale = (prescale & 0x07) - 1; - divider += 1; - - pstab = (timertype & TIMER) == TIMER2 ? - prescale_factors_2 : prescale_factors_01; - - while (prescale--) - divider *= pstab[prescale]; - - if ((timertype & (CHANA|T_16BIT)) == CHANA) - divider *= 2; - - return divider; -} - -int pin_clockdiv_set(int pin, unsigned long divider) -{ - unsigned long ltop; - uint16_t top; - uint8_t prescale; - const FLASH uint8_t *pstab; - - uint8_t timertype = pinlist[pin].timer; - if ((timertype & TIMER) == 0) - return 0; - - if (divider < 2) - return -1; - - ltop = divider; - if ((timertype & (CHANA|T_16BIT)) == CHANA) - ltop /= 2; - - if (ltop > 1024 * ((timertype & T_16BIT) ? (1L<<16) : (1L<<8))) - return -1; - - prescale = 1; - pstab = (timertype & TIMER) == TIMER2 ? - prescale_factors_2 : prescale_factors_01; - -// debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n", -// pin, ltop, prescale); - - while (ltop > ((timertype & T_16BIT) ? (1L<<16) : (1L<<8))) { -// debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n", -// pin, ltop, prescale, *pstab); - - if (*pstab == 0) - return -1; - ltop /= *pstab++; - prescale++; - } - - if (ltop == 0) - return -1; - - top = ltop - 1; - - PING |= _BV(0); /* Debug */ - - switch (timertype & TIMER) { - case TIMER0: - PRR0 &= ~_BV(PRTIM0); - TCCR0B = (1 << WGM02); - TCNT0 = 0; - OCR0A = top; - if (timertype & CHANA) { - TCCR0A = (PWMTOGGLE << COM0A0) | (0b11 << WGM00); - } else { - OCR0B = top/2; - TCCR0A = (PWMPOS << COM0B0) | (0b11 << WGM10); - } - TCCR0B = (1 << WGM02) | (prescale << CS10); - break; - - case TIMER1: - PRR0 &= ~_BV(PRTIM1); - TCCR1B = (0b11 << WGM12); - TCNT1 = 0; - ICR1 = top; - if (timertype & CHANA) { - OCR1A = top/2; - TCCR1A = (PWMPOS << COM1A0) | (0b10 << WGM10); - } else { - OCR1B = top/2; - TCCR1A = (PWMPOS << COM1B0) | (0b10 << WGM10); - } -// debug("pin: %d, top: %u," -// " ICR1: %u, OCR1A: %u, OCR1B: %u\n", -// pin, top, ICR1, OCR1A, OCR1B); - - TCCR1B = (0b11 << WGM12) | (prescale << CS10); - break; - - case TIMER2: - PRR0 &= ~_BV(PRTIM2); - TCCR2B = (1 << WGM22); - TCNT2 = 0; - OCR2A = top; - if (timertype & CHANA) { - TCCR2A = (PWMTOGGLE << COM2A0) | (0b11 << WGM20); - } else { - OCR2B = top/2; - TCCR2A = (PWMPOS << COM2B0) | (0b11 << WGM10); - } - TCCR2B = (1 << WGM22) | (prescale << CS10); - break; - } - - PING |= _BV(0); /* Debug */ - - pin_config(pin, OUTPUT_TIMER); - - return 0; -} - diff --git a/include/gpio.h b/include/gpio.h new file mode 100644 index 0000000..ac48045 --- /dev/null +++ b/include/gpio.h @@ -0,0 +1,17 @@ +#ifndef GPIO_H +#define GPIO_H + +/* Number of user configurable I/O pins */ +#define GPIO_MAX 11 + +typedef enum {NONE, INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} gpiomode_t; + +int gpio_config(int pin, gpiomode_t mode); +gpiomode_t gpio_config_get(int pin); +int gpio_read(int pin); +void gpio_write(int pin, uint8_t val); +int gpio_clockdiv_set(int pin, unsigned long divider); +long gpio_clockdiv_get(int pin); + +#endif /* GPIO_H */ + diff --git a/include/pin.h b/include/pin.h deleted file mode 100644 index 5b37587..0000000 --- a/include/pin.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef PIN_H -#define PIN_H - -/* Number of user configurable I/O pins */ -#define PIN_MAX 11 - -typedef enum {NONE, INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t; - -int pin_config(int pin, pinmode_t mode); -pinmode_t pin_config_get(int pin); -int pin_read(int pin); -void pin_write(int pin, uint8_t val); -int pin_clockdiv_set(int pin, unsigned long divider); -long pin_clockdiv_get(int pin); - -#endif /* PIN_H */ - -- cgit v1.2.3