From 41d36f28612cb6c49cf0260236f3b834549883be Mon Sep 17 00:00:00 2001 From: Leo C Date: Tue, 14 Oct 2014 12:53:48 +0200 Subject: pin command, add user configurable i/o pins --- avr/Tupfile | 4 +- avr/cmd_boot.c | 299 +++++++++++++++++++++++++++++++++++++++++-- avr/command_tbl.c | 42 +++++- avr/getopt-min.c | 76 +++++++++++ avr/main.c | 9 +- avr/pin.c | 372 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ avr/serial.c | 2 +- avr/timer.c | 4 +- avr/z80-if.c | 103 +-------------- 9 files changed, 788 insertions(+), 123 deletions(-) create mode 100644 avr/getopt-min.c create mode 100644 avr/pin.c (limited to 'avr') diff --git a/avr/Tupfile b/avr/Tupfile index 9227f2b..cbceff8 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -4,9 +4,9 @@ PROG = stamp-test SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c SRC += cmd_help.c cmd_echo.c cmd_date.c cmd_mem.c cmd_boot.c -SRC += env.c xmalloc.c date.c +SRC += env.c xmalloc.c date.c getopt-min.c SRC += timer.c con-utils.c serial.c i2c.c pcf8583.c -SRC += background.c z180-serv.c z80-if.c +SRC += background.c z180-serv.c z80-if.c pin.c SRC_Z = ../z180/hdrom.c diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 58c4f56..285dd65 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -4,11 +4,16 @@ */ #include "common.h" #include +#include +#include #include #include #include "command.h" +#include "getopt-min.h" #include "z80-if.h" +#include "pin.h" +#include "debug.h" /* ugly hack to get Z180 loadfile into flash memory */ #define const const FLASH @@ -32,7 +37,7 @@ static void z80_load_mem(void) z80_bus_cmd(Request); z80_write_block((const FLASH unsigned char *) &hdrom[sec_base], /* src */ - hdrom_address[sec], /* dest */ + hdrom_address[sec], /* dest */ hdrom_length_of_sections[sec]); /* len */ z80_bus_cmd(Release); sec_base+=hdrom_length_of_sections[sec]; @@ -143,25 +148,47 @@ command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv return CMD_RET_SUCCESS; } - +#if 0 command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - uint32_t freq; + long freq; + char *endp; (void) cmdtp; (void) flag; - + if (argc == 2) { - freq = strtoul(argv[1], NULL, 10); - if (freq == 0) { - printf_P(PSTR("CPU clock cannot be 0\n")); - return CMD_RET_USAGE; + if (toupper(argv[1][0]) == 'L') + freq = 0; + else if (toupper(argv[1][0]) == 'H') + freq = LONG_MAX; + else { + freq = strtol(argv[1], &endp, 10); + switch (*endp) { + case 'M': + freq *= 1000; + case 'K': + freq *= 1000; + endp++; + case '\0': + if (*endp == '\0') + break; + default: + printf_P(PSTR("invalid value\n")); + return CMD_RET_USAGE; + } + + if (freq == 0) { + printf_P(PSTR("CPU clock cannot be 0\n")); + return CMD_RET_USAGE; + } + + +/* if (freq > (long) F_CPU / 2) { + printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2); + return CMD_RET_USAGE; + } +*/ } - - if (freq > F_CPU / 2) { - printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2); - return CMD_RET_USAGE; - } - if (z80_clock_set(freq) < 0) { printf_P(PSTR("Setting CPU clock freq. to %luHz failed.\n"), freq); @@ -174,3 +201,247 @@ command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_SUCCESS; } +command_ret_t do_clock2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + long value; + char *endp; + uint8_t div_flag = 0; + + (void) cmdtp; (void) flag; + + if (argc >= 2) { + if (argv[1][0] == '-' && argv[1][1] == 'd') { + div_flag = 1; + argc--; + argv++; + } + } + + if (argc == 2) { + if (toupper(argv[1][0]) == 'L') + value = 0; + else if (toupper(argv[1][0]) == 'H') + value = LONG_MAX; + else { + value = strtol(argv[1], &endp, 10); + switch (*endp) { + case 'M': + value *= 1000; + case 'K': + value *= 1000; + endp++; + case '\0': + if (*endp == '\0') + break; + default: + printf_P(PSTR("invalid value\n")); + return CMD_RET_USAGE; + } + + if (value == 0) { + printf_P(PSTR("clk2 cannot be 0\n")); + return CMD_RET_USAGE; + } + + if (div_flag) { + if (value > 256*1024L) { + printf_P(PSTR("Max clk2 divider is: %lu\n"), 256*1024L); + return CMD_RET_USAGE; + } + } else { + if (value > (long) F_CPU / 2) { + printf_P(PSTR("Max clk2 freq. is: %luHz\n"), F_CPU/2); + return CMD_RET_USAGE; + } + } + } + if (div_flag ? z80_clock2_divset(value) : z80_clock2_set(value) < 0) { + printf_P(PSTR("Setting clk2 freq. to %luHz failed.\n"), + value); + } + } + + printf_P(PSTR("clk2: %luHz\n"), z80_clock2_get()); + + + return CMD_RET_SUCCESS; +} +#endif + +// {INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t; + + +static void print_blanks(uint_fast8_t count) +{ + while(count--) + putchar(' '); +} + +static const FLASH char * const FLASH pinconf_str[] = { + FSTR("Input"), + FSTR("Pullup"), + FSTR("Output"), + FSTR("Clock"), + }; + +static const FLASH char * const FLASH pinlevel_str[] = { + FSTR("Low"), + FSTR("High"), + FSTR(""), + }; + +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); + my_puts_P(pinconf_str[pinconf]); + print_blanks(8 - strlen_P(pinconf_str[pinconf])); + my_puts_P(levelp); + print_blanks(6 - strlen_P(levelp)); + if (pinconf == OUTPUT_TIMER) + printf_P(PSTR("%7ld %8ld"), + div, F_CPU/div); + } else { + printf_P(PSTR("Pin %d: "), pin); + 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; +} + + +/* + * TODO: - pin groups + * - error if pin "config clock" on pins without clock + * - stat for single pin (group) + */ + +command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int opt, pin; + unsigned long value; + char *endp; + char printheader = 1; + + (void) cmdtp; (void) flag; + + /* reset getopt() */ + optind = 1; + + while ((opt = getopt(argc, argv, PSTR("s"))) != -1) { + switch (opt) { + case 's': + printheader = 0; + break; + default: /* '?' */ + return CMD_RET_USAGE; + } + } + +// if ((argc - optind) % 2 != 0) +// return CMD_RET_USAGE; + + debug("argc: %d, optind: %d\n", argc, optind); + + switch (argc - optind) { + case 0: + if (printheader) + printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" + "-----------------------------------------\n")); + for (pin = 0; pin < PIN_MAX; pin++) + print_pin(pin, 1); + + return CMD_RET_SUCCESS; + break; + case 1: + pin = strtol(argv[optind], &endp, 10); + print_pin(pin, 0); + return CMD_RET_SUCCESS; + break; + } + + while (optind < argc ) { + uint8_t hz_flag = 0; + + pin = strtol(argv[optind++], &endp, 10); + + switch (toupper(argv[optind][0])) { + case 'L': + case 'H': + pin_write(pin, toupper(argv[optind][0]) == 'H'); + pin_config(pin, OUTPUT); + break; + case 'P': + pin_config(pin, INPUT_PULLUP); + break; + case 'I': + case 'T': + pin_config(pin, 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; + } + + + debug("** setting pin '%d' to '%lu'\n", pin, value); + if (pin_clockdiv_set(pin, value) < 0) { + printf_P(PSTR("Setting pin %d to %lu failed.\n"), + pin, value); + } + } + + optind++; + } + + + return CMD_RET_SUCCESS; +} + diff --git a/avr/command_tbl.c b/avr/command_tbl.c index c721d53..71e70ea 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -18,7 +18,9 @@ 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_clock(cmd_tbl_t *, int, int, char * const []); +//extern command_ret_t do_clock(cmd_tbl_t *, int, int, char * const []); +//extern command_ret_t do_clock2(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_pin(cmd_tbl_t *, int, int, char * const []); cmd_tbl_t cmd_tbl[] = { @@ -120,10 +122,46 @@ CMD_TBL_ITEM( "Perform RESET of the CPU", "" ), + +#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, + "Set or get pin state", + "[-s][pins]\n" + " - print cofiguration and state or frequency of pins\n" + " print all pins, if argument is omitted\n" + "pin pins [h[igh]]|[l[ow]]\n" + " - config pins as output and set to level high or low\n" + "pin pins [ts]|[i[n]]|[p[ullup]]\n" + " - config pins as input/tristate or input with pullup\n" + "pin pins value[K|M][Hz]\n" + " - output a clock on pins\n" + " value is system clock divider or frequency, if 'Hz' is appended\n" + " divider is rounded down to next possible value (depends on pin)\n" + "\n" + "pins is a comma separated list of numbers or ranges, i.e. \"0,9,3-6\"\n" ), CMD_TBL_ITEM( diff --git a/avr/getopt-min.c b/avr/getopt-min.c new file mode 100644 index 0000000..778258d --- /dev/null +++ b/avr/getopt-min.c @@ -0,0 +1,76 @@ +#include "common.h" +#include + + +/* + * Minimum getopt, original version was: + */ + +/* + getopt -- public domain version of standard System V routine + + Strictly enforces the System V Command Syntax Standard; + provided by D A Gwyn of BRL for generic ANSI C implementations +*/ +/* $Id: getopt.c,v 1.2 1992/12/07 11:12:52 nickc Exp $ */ + +#include + +int optind = 1; /* next argv[] index */ +char *optarg; /* option parameter if any */ + + +int +getopt( /* returns letter, '?', EOF */ + int argc, /* argument count from main */ + char *const argv[], /* argument vector from main */ + const FLASH char *optstring ) /* allowed args, e.g. "ab:c" */ +{ + static int sp = 1; /* position within argument */ + int osp; /* saved `sp' for param test */ + int c; /* option letter */ + const FLASH char *cp; /* -> option in `optstring' */ + + optarg = NULL; + + if ( sp == 1 ) /* fresh argument */ + { + if ( optind >= argc /* no more arguments */ + || argv[optind][0] != '-' /* no more options */ + || argv[optind][1] == '\0' /* not option; stdin */ + ) + return EOF; + } + + c = argv[optind][sp]; /* option letter */ + osp = sp++; /* get ready for next letter */ + + if ( argv[optind][sp] == '\0' ) /* end of argument */ + { + ++optind; /* get ready for next try */ + sp = 1; /* beginning of next argument */ + } + + if ( c == ':' /* optstring syntax conflict */ + || (cp = strchr_P( optstring, c )) == NULL /* not found */ + ) + return '?'; + + if ( cp[1] == ':' ) /* option takes parameter */ + { + if ( osp != 1 ) + return '?'; + + if ( sp != 1 ) /* reset by end of argument */ + return '?'; + + if ( optind >= argc ) + return '?'; + + optarg = argv[optind]; /* make parameter available */ + ++optind; /* skip over parameter */ + } + + return c; +} + diff --git a/avr/main.c b/avr/main.c index 9d7c89f..0470fea 100644 --- a/avr/main.c +++ b/avr/main.c @@ -95,11 +95,10 @@ void setup_avr(void) CLKPR = 0; /* Timer */ - PRR0 &= ~_BV(PRTIM2); - OCR2A = F_CPU / 256 / 1000 - 1; /* Timer2: 1000Hz interval (OC2A) */ - TCCR2A = (0b10 << WGM20); /* CTC Mode */ - TCCR2B = (0b110 << CS20); /* Prescaler 256 */ - TIMSK2 = _BV(OCIE2A); /* Enable TC2.oca interrupt */ + PRR1 &= ~_BV(PRTIM3); + OCR3A = F_CPU / 1000 - 1; /* Timer3: 1000Hz interval (OC3A) */ + TCCR3B = (0b01< +#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 CLOCK 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_RESTORESTATE) { + p->ddr &= ~bit; + p->pout &= ~bit; + } + break; + case INPUT_PULLUP: + pin_timer_off(pinlist[pin].timer); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + p->ddr &= ~bit; + p->pout |= bit; + } + break; + case OUTPUT: + pin_timer_off(pinlist[pin].timer); + case OUTPUT_TIMER: + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + 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_RESTORESTATE) { + 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/avr/serial.c b/avr/serial.c index a5e2846..e897c84 100644 --- a/avr/serial.c +++ b/avr/serial.c @@ -17,7 +17,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(_write, -#define BUFFER_SIZE 64 +#define BUFFER_SIZE 128 #if ((BUFFER_SIZE-1) & BUFFER_SIZE) # error: BUFFER_SIZE not power of 2 diff --git a/avr/timer.c b/avr/timer.c index 56c7bed..e15a55b 100644 --- a/avr/timer.c +++ b/avr/timer.c @@ -19,10 +19,10 @@ volatile uint32_t timestamp; /*---------------------------------------------------------*/ -/* 1000Hz timer interrupt generated by OC2A */ +/* 1000Hz timer interrupt generated by OC3A */ /*---------------------------------------------------------*/ -ISR(TIMER2_COMPA_vect) +ISR(TIMER3_COMPA_vect) { static int_fast8_t tick_10ms; int_fast8_t i; diff --git a/avr/z80-if.c b/avr/z80-if.c index dd0dd96..a60a482 100644 --- a/avr/z80-if.c +++ b/avr/z80-if.c @@ -64,12 +64,6 @@ /* Number of array elements */ #define NELEMS(x) (sizeof x/sizeof *x) - -#define CONCAT(x,y) x ## y -#define EVALUATOR(x,y) CONCAT(x,y) - -#define GPIO_(X) CONCAT(GPIO, X) - struct bits { uint8_t b0:1; uint8_t b1:1; @@ -81,12 +75,14 @@ struct bits { uint8_t b7:1; } __attribute__((__packed__)); +typedef struct bits pbit_t; + #define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) -#define P_ZCLK PORTB -#define ZCLK 7 -#define DDR_ZCLK DDRB +//#define P_ZCLK PORTB +//#define ZCLK 5 +//#define DDR_ZCLK DDRB #define P_MREQ PORTD #define MREQ 4 #define DDR_MREQ DDRD @@ -130,7 +126,7 @@ struct bits { //#define ADB_PORT PORTE -#define Z80_O_ZCLK SBIT(P_ZCLK, 7) +//#define Z80_O_ZCLK SBIT(P_ZCLK, 5) #define Z80_O_MREQ SBIT(P_MREQ, 4) #define Z80_O_RD SBIT(P_RD, 3) #define Z80_O_WR SBIT(P_WR, 2) @@ -144,8 +140,6 @@ struct bits { #define MASK(n) ((1<<(n))-1) #define SMASK(w,s) (MASK(w) << (s)) -#define LOWSPEED 50000 - typedef union { uint32_t l; @@ -158,89 +152,6 @@ static zstate_t zstate; /*--------------------------------------------------------------------------*/ -static -uint8_t is_lowspeed() -{ - return (TCCR1B & 7) < 2 && - OCR1A > (F_CPU / 2 / LOWSPEED); -} - -static -void z80_setup_clock(void) -{ - /* ZCLK: Output and low */ - DDR_ZCLK |= _BV(ZCLK); - Z80_O_ZCLK = 0; - - DDRB |= _BV(6); /* Debug */ - PORTB |= _BV(6); /* Debug */ - - PRR0 &= ~_BV(PRTIM1); - - /* Timer1: CTC: Toggle OC1C on compare match */ - OCR1A = 0; - OCR1C = 0; - TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10); - TCCR1B = (0b01 << WGM12) | (0b001 << CS10); -} - - -int z80_clock_set(unsigned long freq) -{ - unsigned long ocrval = F_CPU / freq / 2; - uint8_t prescale = 0; - - while (ocrval > (1L<<16)) { - prescale++; - if (prescale < 3) - ocrval = ocrval / 8; - else - ocrval = ocrval / 4; - } - - if ((ocrval == 0) || (prescale > 4)) - return -1; - - ocrval -= 1; - - PINB |= _BV(6); /* Debug */ - - /* Stop Timer */ - TCCR1B = (0b01 << WGM12) | (0b000 << CS10); - TCNT1 = 0; - - OCR1A = ocrval; - OCR1CL = ocrval; - TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10); - TCCR1B = (0b01 << WGM12) | ((prescale+1) << CS10); - - if (ocrval == 0) - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - TCNT1 = 0xFFFF; - } - - PINB |= _BV(6); /* Debug */ - - return 0; -} - -uint32_t z80_clock_get(void) -{ - uint32_t count = (OCR1A + 1L) * 2; - uint8_t pre = (TCCR1B & 7) - 1; - - while (pre) { - if (pre > 2) - count *= 4; - else - count *= 8; - pre--; - } - - return F_CPU/count; -} - - static void z80_addrbus_set_tristate(void) { @@ -296,8 +207,6 @@ static void z80_reset_pulse(void) void z80_setup_bus(void) { - z80_setup_clock(); - /* /ZRESET: Output and low */ Z80_O_RST = 0; DDR_RST |= _BV(RST); -- cgit v1.2.3 From cd5ee5442821f283f6661befb24b885d944e4c5e Mon Sep 17 00:00:00 2001 From: Leo C Date: Tue, 14 Oct 2014 22:38:56 +0200 Subject: pin command: pin groups work now --- avr/Tupfile | 2 +- avr/cmd_boot.c | 163 ++++++++++++++++++++++++++++++++++++++++-------------- avr/command_tbl.c | 12 ++-- avr/getopt-min.c | 2 +- avr/main.c | 2 +- avr/pin.c | 2 +- include/pin.h | 2 +- 7 files changed, 134 insertions(+), 51 deletions(-) (limited to 'avr') diff --git a/avr/Tupfile b/avr/Tupfile index cbceff8..1300a4a 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -1,6 +1,6 @@ include_rules -PROG = stamp-test +PROG = stamp-monitor SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c SRC += cmd_help.c cmd_echo.c cmd_date.c cmd_mem.c cmd_boot.c diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 285dd65..26855f1 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -278,6 +278,7 @@ static void print_blanks(uint_fast8_t count) } static const FLASH char * const FLASH pinconf_str[] = { + FSTR("?"), FSTR("Input"), FSTR("Pullup"), FSTR("Output"), @@ -327,25 +328,74 @@ int print_pin(int pin, int multi) return 0; } +int pinarg_insert(int pin, int count, int pinarg[]) +{ + int pos; -/* - * TODO: - pin groups - * - error if pin "config clock" on pins without clock - * - stat for single pin (group) - */ - -command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) + 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 (int i = count-1; i == pos ; i--) + pinarg[i+1] = pinarg[i]; + pinarg[pos] = pin; + + return 1; +} + +int pinarg_get(char * arg, int pinarg[]) { - int opt, pin; - unsigned long value; + int count = 0; char *endp; + int pin1, pin2, rc; + + while (1) { + pin1 = (int) strtoul(arg, &endp, 10); + if (endp != arg && *endp == '-') { + arg = endp+1; + 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 && pin1 >= 0) { + 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; + int pinarg[PIN_MAX]; + int pinargc; (void) cmdtp; (void) flag; /* reset getopt() */ optind = 1; + int opt; while ((opt = getopt(argc, argv, PSTR("s"))) != -1) { switch (opt) { case 's': @@ -356,45 +406,59 @@ command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) } } -// if ((argc - optind) % 2 != 0) -// return CMD_RET_USAGE; - - debug("argc: %d, optind: %d\n", argc, optind); + /* remaining arguments */ + argc -= optind; + + 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--; + } - switch (argc - optind) { - case 0: - if (printheader) - printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" - "-----------------------------------------\n")); - for (pin = 0; pin < PIN_MAX; pin++) - print_pin(pin, 1); - - return CMD_RET_SUCCESS; - break; - case 1: - pin = strtol(argv[optind], &endp, 10); - print_pin(pin, 0); + if (argc == 0) { + /* no more args, print config */ + if (pinargc == 1) + print_pin(pinarg[0], 0); + else { + if (printheader) + printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" + "-----------------------------------------\n")); + for (int i = 0; i < pinargc; i++) + print_pin(pinarg[i], 1); + } return CMD_RET_SUCCESS; - break; } - while (optind < argc ) { + /* 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; - pin = strtol(argv[optind++], &endp, 10); - switch (toupper(argv[optind][0])) { - case 'L': case 'H': - pin_write(pin, toupper(argv[optind][0]) == 'H'); - pin_config(pin, OUTPUT); + level = 1; + case 'L': + mode = OUTPUT; break; case 'P': - pin_config(pin, INPUT_PULLUP); + mode = INPUT_PULLUP; break; case 'I': case 'T': - pin_config(pin, INPUT); + mode = INPUT; break; default: @@ -429,19 +493,38 @@ command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) } value = F_CPU/value; } + mode = OUTPUT_TIMER; + } - debug("** setting pin '%d' to '%lu'\n", pin, value); - if (pin_clockdiv_set(pin, value) < 0) { - printf_P(PSTR("Setting pin %d to %lu failed.\n"), - pin, value); + if (mode == NONE) + return CMD_RET_USAGE; + + for (int 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 71e70ea..e8af931 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -148,20 +148,20 @@ CMD_TBL_ITEM( CMD_TBL_ITEM( pin, CONFIG_SYS_MAXARGS, 0, do_pin, - "Set or get pin state", - "[-s][pins]\n" + "Set or query pin state", + "[-s] []\n" " - print cofiguration and state or frequency of pins\n" " print all pins, if argument is omitted\n" - "pin pins [h[igh]]|[l[ow]]\n" + "pin h[igh]|l[ow]\n" " - config pins as output and set to level high or low\n" - "pin pins [ts]|[i[n]]|[p[ullup]]\n" + "pin ts|i[n]|p[ullup]\n" " - config pins as input/tristate or input with pullup\n" - "pin pins value[K|M][Hz]\n" + "pin value[K|M][Hz]\n" " - output a clock on pins\n" " value is system clock divider or frequency, if 'Hz' is appended\n" " divider is rounded down to next possible value (depends on pin)\n" "\n" - "pins is a comma separated list of numbers or ranges, i.e. \"0,9,3-6\"\n" + " is a comma separated list of numbers or ranges, i.e. \"0,9,3-6\"\n" ), CMD_TBL_ITEM( diff --git a/avr/getopt-min.c b/avr/getopt-min.c index 778258d..571c14f 100644 --- a/avr/getopt-min.c +++ b/avr/getopt-min.c @@ -39,7 +39,7 @@ getopt( /* returns letter, '?', EOF */ || argv[optind][0] != '-' /* no more options */ || argv[optind][1] == '\0' /* not option; stdin */ ) - return EOF; + return -1; } c = argv[optind][sp]; /* option letter */ diff --git a/avr/main.c b/avr/main.c index 0470fea..e7ebd5d 100644 --- a/avr/main.c +++ b/avr/main.c @@ -228,7 +228,7 @@ int main(void) i2c_init(CONFIG_SYS_I2C_CLOCK); #endif - printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n")); + printf_P(PSTR("\nATMEGA1281+Z8S180 Stamp Monitor\n\n")); main_loop(); diff --git a/avr/pin.c b/avr/pin.c index 8a9f000..14896b3 100644 --- a/avr/pin.c +++ b/avr/pin.c @@ -12,7 +12,7 @@ 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 CLOCK PB5 OC1A PWM (2**16)*1024 67108864 0.2746 +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 diff --git a/include/pin.h b/include/pin.h index e673b56..5b37587 100644 --- a/include/pin.h +++ b/include/pin.h @@ -4,7 +4,7 @@ /* Number of user configurable I/O pins */ #define PIN_MAX 11 -typedef enum {INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t; +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); -- cgit v1.2.3 From 70c994914510f9db3ff71373cb96f50ee1669446 Mon Sep 17 00:00:00 2001 From: Leo C Date: Wed, 15 Oct 2014 21:20:41 +0200 Subject: Add pin_alias --- avr/cmd_boot.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-------- avr/main.c | 6 ++-- include/config.h | 7 +++++ 3 files changed, 83 insertions(+), 14 deletions(-) (limited to 'avr') diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 26855f1..1213365 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -6,11 +6,13 @@ #include #include #include +#include #include #include #include "command.h" #include "getopt-min.h" +#include "env.h" #include "z80-if.h" #include "pin.h" #include "debug.h" @@ -268,7 +270,41 @@ command_ret_t do_clock2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[] } #endif -// {INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t; + +static const int namestr = PIN_MAX; +static char *pin_names[PIN_MAX+1]; +static uint_least8_t pin_names_width; + +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 void print_blanks(uint_fast8_t count) @@ -277,6 +313,14 @@ static void print_blanks(uint_fast8_t count) putchar(' '); } +static int xstrlen(char *s) +{ + if (s == NULL) + return 0; + else + return strlen(s); +} + static const FLASH char * const FLASH pinconf_str[] = { FSTR("?"), FSTR("Input"), @@ -305,16 +349,20 @@ int print_pin(int pin, int multi) levelp = pinlevel_str[pin_read(pin)]; if (multi) { - printf_P(PSTR("%3d "), pin); + 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(8 - strlen_P(pinconf_str[pinconf])); + print_blanks(7 - strlen_P(pinconf_str[pinconf])); my_puts_P(levelp); - print_blanks(6 - strlen_P(levelp)); + print_blanks(5 - strlen_P(levelp)); if (pinconf == OUTPUT_TIMER) - printf_P(PSTR("%7ld %8ld"), + printf_P(PSTR("%8ld %8ld"), div, F_CPU/div); } else { - printf_P(PSTR("Pin %d: "), pin); + 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); @@ -409,11 +457,13 @@ command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) /* remaining arguments */ argc -= optind; - if (argc == 0) + pinnames_get(); + + if (argc == 0) { /* print cofig of all pins */ for (pinargc = 0; pinargc < PIN_MAX; pinargc++) pinarg[pinargc] = pinargc; - else { + } else { /* get first arg */ pinargc = pinarg_get(argv[optind++], pinarg); if (pinargc == 0) @@ -427,9 +477,21 @@ command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (pinargc == 1) print_pin(pinarg[0], 0); else { - if (printheader) - printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n" - "-----------------------------------------\n")); + 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 (int i = 0; i < pinargc; i++) print_pin(pinarg[i], 1); } diff --git a/avr/main.c b/avr/main.c index e7ebd5d..ba8a672 100644 --- a/avr/main.c +++ b/avr/main.c @@ -168,13 +168,13 @@ const char *bootdelay_process(void) char *s; int bootdelay; - bootdelay = (int) getenv_ulong(PSTR("bootdelay"), 10, CONFIG_BOOTDELAY); + bootdelay = (int) getenv_ulong(PSTR(ENV_BOOTDELAY), 10, CONFIG_BOOTDELAY); debug("### main_loop entered: bootdelay=%d\n\n", bootdelay); _delay_ms(20); - s = getenv(PSTR("bootcmd")); + s = getenv(PSTR(ENV_BOOTCMD)); stored_bootdelay = bootdelay; return s; } @@ -212,7 +212,7 @@ int main(void) if (reset_reason_is_power_on()) _delay_ms(CONFIG_PWRON_DELAY); - serial_setup(getenv_ulong(PSTR("baudrate"), 10, CONFIG_BAUDRATE)); + serial_setup(getenv_ulong(PSTR(ENV_BAUDRATE), 10, CONFIG_BAUDRATE)); sei(); #if DEBUG diff --git a/include/config.h b/include/config.h index 4093a67..c0777a8 100644 --- a/include/config.h +++ b/include/config.h @@ -1,6 +1,13 @@ #ifndef CONFIG_H #define CONFIG_H +/* Environment variables */ + +#define ENV_BAUDRATE "baudrate" +#define ENV_BOOTDELAY "bootdelay" +#define ENV_BOOTCMD "bootcmd" +#define ENV_PINALIAS "pin_alias" + #define CONFIG_ENV_SIZE 1600 #define CONFIG_ENV_OFFSET 0 #define CONFIG_ENVVAR_MAX 20 -- cgit v1.2.3 From 8f23e84c6a08a384d25582f9cf79c4f5549bc852 Mon Sep 17 00:00:00 2001 From: Leo C Date: Wed, 15 Oct 2014 23:44:26 +0200 Subject: Code reorg and cleanup --- avr/Tupfile | 6 +- avr/cmd_boot.c | 449 +------------------------------------------------- avr/cmd_mem.c | 11 +- avr/cmd_pin.c | 329 ++++++++++++++++++++++++++++++++++++ avr/command.c | 17 +- avr/print-utils.c | 10 ++ include/print-utils.h | 2 + 7 files changed, 354 insertions(+), 470 deletions(-) create mode 100644 avr/cmd_pin.c create mode 100644 avr/print-utils.c create mode 100644 include/print-utils.h (limited to 'avr') diff --git a/avr/Tupfile b/avr/Tupfile index 1300a4a..91562b4 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -3,9 +3,9 @@ include_rules PROG = stamp-monitor SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c -SRC += cmd_help.c cmd_echo.c cmd_date.c cmd_mem.c cmd_boot.c -SRC += env.c xmalloc.c date.c getopt-min.c -SRC += timer.c con-utils.c serial.c i2c.c pcf8583.c +SRC += cmd_help.c cmd_echo.c cmd_date.c cmd_mem.c cmd_boot.c cmd_pin.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_Z = ../z180/hdrom.c diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 1213365..17ed746 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -4,18 +4,11 @@ */ #include "common.h" #include -#include -#include -#include -#include #include #include "command.h" -#include "getopt-min.h" -#include "env.h" #include "z80-if.h" -#include "pin.h" -#include "debug.h" +//#include "debug.h" /* ugly hack to get Z180 loadfile into flash memory */ #define const const FLASH @@ -150,443 +143,3 @@ command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv return CMD_RET_SUCCESS; } -#if 0 -command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - long freq; - char *endp; - - (void) cmdtp; (void) flag; - - if (argc == 2) { - if (toupper(argv[1][0]) == 'L') - freq = 0; - else if (toupper(argv[1][0]) == 'H') - freq = LONG_MAX; - else { - freq = strtol(argv[1], &endp, 10); - switch (*endp) { - case 'M': - freq *= 1000; - case 'K': - freq *= 1000; - endp++; - case '\0': - if (*endp == '\0') - break; - default: - printf_P(PSTR("invalid value\n")); - return CMD_RET_USAGE; - } - - if (freq == 0) { - printf_P(PSTR("CPU clock cannot be 0\n")); - return CMD_RET_USAGE; - } - - -/* if (freq > (long) F_CPU / 2) { - printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2); - return CMD_RET_USAGE; - } -*/ - } - if (z80_clock_set(freq) < 0) { - printf_P(PSTR("Setting CPU clock freq. to %luHz failed.\n"), - freq); - } - } - - printf_P(PSTR("CPU clock: %luHz\n"), z80_clock_get()); - - - return CMD_RET_SUCCESS; -} - -command_ret_t do_clock2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - long value; - char *endp; - uint8_t div_flag = 0; - - (void) cmdtp; (void) flag; - - if (argc >= 2) { - if (argv[1][0] == '-' && argv[1][1] == 'd') { - div_flag = 1; - argc--; - argv++; - } - } - - if (argc == 2) { - if (toupper(argv[1][0]) == 'L') - value = 0; - else if (toupper(argv[1][0]) == 'H') - value = LONG_MAX; - else { - value = strtol(argv[1], &endp, 10); - switch (*endp) { - case 'M': - value *= 1000; - case 'K': - value *= 1000; - endp++; - case '\0': - if (*endp == '\0') - break; - default: - printf_P(PSTR("invalid value\n")); - return CMD_RET_USAGE; - } - - if (value == 0) { - printf_P(PSTR("clk2 cannot be 0\n")); - return CMD_RET_USAGE; - } - - if (div_flag) { - if (value > 256*1024L) { - printf_P(PSTR("Max clk2 divider is: %lu\n"), 256*1024L); - return CMD_RET_USAGE; - } - } else { - if (value > (long) F_CPU / 2) { - printf_P(PSTR("Max clk2 freq. is: %luHz\n"), F_CPU/2); - return CMD_RET_USAGE; - } - } - } - if (div_flag ? z80_clock2_divset(value) : z80_clock2_set(value) < 0) { - printf_P(PSTR("Setting clk2 freq. to %luHz failed.\n"), - value); - } - } - - printf_P(PSTR("clk2: %luHz\n"), z80_clock2_get()); - - - return CMD_RET_SUCCESS; -} -#endif - - -static const int namestr = PIN_MAX; -static char *pin_names[PIN_MAX+1]; -static uint_least8_t pin_names_width; - -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 void print_blanks(uint_fast8_t count) -{ - while(count--) - putchar(' '); -} - -static int 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(""), - }; - -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; -} - -int pinarg_insert(int pin, int count, int pinarg[]) -{ - int 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 (int i = count-1; i == pos ; i--) - pinarg[i+1] = pinarg[i]; - pinarg[pos] = pin; - - return 1; -} - -int pinarg_get(char * arg, int pinarg[]) -{ - int count = 0; - char *endp; - int pin1, pin2, rc; - - while (1) { - pin1 = (int) strtoul(arg, &endp, 10); - if (endp != arg && *endp == '-') { - arg = endp+1; - 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 && pin1 >= 0) { - 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; - int pinarg[PIN_MAX]; - int 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 (int 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 (int 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/cmd_mem.c b/avr/cmd_mem.c index f1f34c0..66dc88f 100644 --- a/avr/cmd_mem.c +++ b/avr/cmd_mem.c @@ -14,13 +14,14 @@ #include "common.h" #include #include +#include -#include "config.h" -#include "debug.h" #include "command.h" #include "cli_readline.h" +#include "print-utils.h" #include "con-utils.h" #include "z80-if.h" +//#include "debug.h" #ifndef CONFIG_SYS_MEMTEST_SCRATCH @@ -38,12 +39,6 @@ static uint32_t base_address = 0; /*--------------------------------------------------------------------------*/ -static void print_blanks(uint_fast8_t count) -{ - while(count--) - putchar(' '); -} - int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title) { uint8_t buf[16]; diff --git a/avr/cmd_pin.c b/avr/cmd_pin.c new file mode 100644 index 0000000..b46b853 --- /dev/null +++ b/avr/cmd_pin.c @@ -0,0 +1,329 @@ +#include "common.h" +#include +#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.c b/avr/command.c index f1e184a..2b53adf 100644 --- a/avr/command.c +++ b/avr/command.c @@ -1,29 +1,24 @@ - /* * Command Processor Table */ #include "common.h" - +#include #include #include -#include #include +#include #include "config.h" -#include "debug.h" +#include "print-utils.h" #include "con-utils.h" +#ifdef CONFIG_AUTO_COMPLETE #include "env.h" -#include "timer.h" +#endif +#include "debug.h" #include "command.h" -static void print_blanks(int_fast8_t count) -{ - while(count--) - my_puts_P(PSTR(" ")); -} - static void print_usage_line(const FLASH char *name, int width, const FLASH char *usage) { diff --git a/avr/print-utils.c b/avr/print-utils.c new file mode 100644 index 0000000..b814d97 --- /dev/null +++ b/avr/print-utils.c @@ -0,0 +1,10 @@ +#include +#include "print-utils.h" + +void print_blanks(uint_fast8_t count) +{ + while(count--) + putchar(' '); +} + + diff --git a/include/print-utils.h b/include/print-utils.h new file mode 100644 index 0000000..bcd9505 --- /dev/null +++ b/include/print-utils.h @@ -0,0 +1,2 @@ +void print_blanks(uint_fast8_t count); + -- cgit v1.2.3