diff --git a/avr.c b/avr.c index ebed6dc9..88d93754 100644 --- a/avr.c +++ b/avr.c @@ -110,19 +110,16 @@ int avr_txrx_bit ( int fd, int bit ) * read the result bit (it is either valid from a previous clock * pulse or it is ignored in the current context) */ - r = ppi_get(fd, PPISTATUS, AVR_DATA); + r = ppi_getpin(fd, PIN_AVR_MISO); /* set the data input line as desired */ - if (bit) - ppi_set(fd, PPIDATA, AVR_INSTR); - else - ppi_clr(fd, PPIDATA, AVR_INSTR); + ppi_setpin(fd, PIN_AVR_MOSI, bit); /* * pulse the clock line, clocking in the MOSI data, and clocking out * the next result bit */ - ppi_pulse(fd, PPIDATA, AVR_CLOCK); + ppi_pulsepin(fd, PIN_AVR_SCK); return r; } @@ -400,7 +397,7 @@ int avr_signature ( int fd, unsigned char sig[4] ) */ void avr_powerup ( int fd ) { - ppi_set(fd, PPIDATA, AVR_POWER); /* power up */ + ppi_set(fd, PPIDATA, PPI_AVR_VCC); /* power up */ usleep(100000); } @@ -410,7 +407,7 @@ void avr_powerup ( int fd ) */ void avr_powerdown ( int fd ) { - ppi_clr(fd, PPIDATA, AVR_POWER); /* power down */ + ppi_clr(fd, PPIDATA, PPI_AVR_VCC); /* power down */ } @@ -424,9 +421,10 @@ int avr_initialize ( int fd, struct avrpart * p ) avr_powerup(fd); - ppi_clr(fd, PPIDATA, AVR_CLOCK); - ppi_clr(fd, PPIDATA, AVR_RESET); - ppi_pulse(fd, PPIDATA, AVR_RESET); + + ppi_setpin(fd, PIN_AVR_SCK, 0); + ppi_setpin(fd, PIN_AVR_RESET, 0); + ppi_pulsepin(fd, PIN_AVR_RESET); usleep(20000); /* 20 ms XXX should be a per-chip parameter */ @@ -447,7 +445,7 @@ int avr_initialize ( int fd, struct avrpart * p ) rc = avr_program_enable ( fd ); if (rc == 0) break; - ppi_pulse(fd, PPIDATA, AVR_CLOCK); + ppi_pulsepin(fd, PIN_AVR_SCK); tries++; } while (tries < 32); diff --git a/avr.h b/avr.h index 9a22e5d8..a77adca5 100644 --- a/avr.h +++ b/avr.h @@ -34,14 +34,18 @@ #include -/* - * bit definitions for AVR device connections - */ -#define AVR_POWER 0xf1 /* bit 0 and 4...7 of data register */ -#define AVR_CLOCK 0x02 /* bit 1 of data register */ -#define AVR_INSTR 0x04 /* bit 2 of data register */ -#define AVR_RESET 0x08 /* bit 3 of data register */ -#define AVR_DATA 0x40 /* bit 6 of status register */ + +#define PPI_AVR_VCC 0x0f /* ppi pins 2-5, data reg bits 0-3 */ +#define PIN_AVR_BUFF 6 +#define PIN_AVR_RESET 7 +#define PIN_AVR_SCK 8 +#define PIN_AVR_MOSI 9 +#define PIN_AVR_MISO 10 +#define PIN_LED_ERR 1 +#define PIN_LED_RDY 14 +#define PIN_LED_PGM 16 +#define PIN_LED_VFY 17 + /* @@ -61,7 +65,7 @@ struct avrmem { AVRMEM memtype; int startaddr; int size; - unsigned char buf; + unsigned char * buf; struct avrmem * next; }; #endif @@ -72,20 +76,14 @@ struct avrpart { int memsize[AVR_MAXMEMTYPES]; /* sizes for eeprom, flash, etc, indexed by AVR_EEPROM or AVR_FLASH */ -#if 0 - int flash_size; /* size in bytes of flash */ - int eeprom_size; /* size in bytes of eeprom */ -#endif unsigned char f_readback; /* flash write polled readback value */ unsigned char e_readback[2]; /* eeprom write polled readback values */ int min_write_delay; /* microseconds */ int max_write_delay; /* microseconds */ int chip_erase_delay; /* microseconds */ - unsigned char * mem[AVR_MAXMEMTYPES]; -#if 0 - unsigned char * flash; - unsigned char * eeprom; -#endif + unsigned char * mem[AVR_MAXMEMTYPES]; /* pointers to avr memory + buffers, indexed by + AVR_EEPROM or AVR_FLASH */ }; extern struct avrpart parts[]; diff --git a/main.c b/main.c index 06165500..2a365eaf 100644 --- a/main.c +++ b/main.c @@ -32,25 +32,44 @@ /* * Code to program an Atmel AVR AT90S device using the parallel port. * - * Make the following connections: + * Make the following (minimal) connections: * - * Parallel Port Atmel AVR - * ------------- ---------------------------- - * Pin 2 -> Vcc (see NOTE below) - * Pin 3 -> SCK CLOCK IN - * Pin 4 -> MOSI Instruction input - * Pin 5 -> /RESET - * Pin 6,7,8,9 -> Vcc (Can be tied together with Schottky diodes) - * Pin 10 <- MISO Data out - * Pin 18 <- GND + * Parallel Port Programmer Function + * ------------- ----------------------------- + * Pins 2-5 -> Vcc (see note below) + * Pin 7 -> AVR /RESET + * Pin 8 -> AVR SCK (clock input) + * Pin 9 -> AVR MOSI (instruction in) + * Pin 10 <- AVR MISO (data out) + * Pin 18 Signal Ground + * + * Additionally, the following conntections can be made to enable + * additional features: + * + * Parallel Port Programmer Function + * ------------- ----------------------------- + * Pin 1 STATUS LED, active low (program or verify error) + * Pin 6 -> /ENABLE ('367 bus driver) + * Pin 14 STATUS LED, active low (ready) + * Pin 16 STATUS LED, active low (programming) + * Pin 17 STATUS LED, active low (verifying) + * + * Pin 6 can be tied to the enable line of a 74HC367 in order to + * isolate and buffer the data to and from the PC parallel port. + * This is useful for connecting to a device in-circuit, and keeps + * the state of the parallel port pins from interfering with the + * normal operation of the target system. When programming is + * complete, this pin is driven high, causing to pins of the '367 to + * float. * * NOTE on Vcc connection: make sure your parallel port can supply an - * adequate amount of current to power your device. 6-10 mA is - * common for parallel port signal lines, but is not guaranteed, - * especially for notebook computers. Optionally, you can tie pins - * 6, 7, 8, and 9 also to Vcc with Schottky diodes to supply - * additional current. If in doubt, don't risk damaging your - * parallel port, use an external power supply. + * adequate amount of current to power your device. 6-10 mA per pin + * is common for parallel port signal lines, but is not guaranteed, + * especially for notebook computers. For additional power, use + * multiple pins tied together with Schottky diodes. If in doubt, + * don't risk damaging your parallel port, use an external power + * supply. + * */ #include @@ -104,16 +123,16 @@ int getexitspecs ( char *s, int *set, int *clr ) while ((cp = strtok(s, ","))) { if (strcmp(cp, "reset") == 0) { - *clr |= AVR_RESET; + *clr |= ppi_getpinmask(PIN_AVR_RESET); } else if (strcmp(cp, "noreset") == 0) { - *set |= AVR_RESET; + *set |= ppi_getpinmask(PIN_AVR_RESET); } else if (strcmp(cp, "vcc") == 0) { - *set |= AVR_POWER; + *set |= PPI_AVR_VCC; } else if (strcmp(cp, "novcc") == 0) { - *clr |= AVR_POWER; + *clr |= PPI_AVR_VCC; } else { return -1; @@ -374,6 +393,10 @@ int main ( int argc, char * argv [] ) exitrc = 0; +#if 0 + ppi_sense(fd); +#endif + ppidata = ppi_getall(fd, PPIDATA); if (ppidata < 0) { fprintf ( stderr, "%s: error reading status of ppi data port\n", progname); diff --git a/ppi.c b/ppi.c index 0c85a3ba..286f613b 100644 --- a/ppi.c +++ b/ppi.c @@ -37,6 +37,36 @@ extern char * progname; +struct ppipins_t { + int pin; + int reg; + int bit; + int inverted; +}; + +static struct ppipins_t pins[] = { + { 1, PPICTRL, 0x01, 1 }, + { 2, PPIDATA, 0x01, 0 }, + { 3, PPIDATA, 0x02, 0 }, + { 4, PPIDATA, 0x04, 0 }, + { 5, PPIDATA, 0x08, 0 }, + { 6, PPIDATA, 0x10, 0 }, + { 7, PPIDATA, 0x20, 0 }, + { 8, PPIDATA, 0x40, 0 }, + { 9, PPIDATA, 0x80, 0 }, + { 10, PPISTATUS, 0x40, 0 }, + { 11, PPISTATUS, 0x80, 1 }, + { 12, PPISTATUS, 0x20, 0 }, + { 13, PPISTATUS, 0x10, 0 }, + { 14, PPICTRL, 0x02, 1 }, + { 15, PPISTATUS, 0x08, 0 }, + { 16, PPICTRL, 0x04, 0 }, + { 17, PPICTRL, 0x08, 1 } +}; + +#define NPINS (sizeof(pins)/sizeof(struct ppipins_t)) + + /* * set 'get' and 'set' appropriately for subsequent passage to ioctl() * to get/set the specified PPI registers. @@ -125,7 +155,7 @@ int ppi_get ( int fd, int reg, int bit ) ioctl(fd, get, &v); v &= bit; - return (v == bit); + return v; /* v == bit */ } /* @@ -198,24 +228,114 @@ int ppi_pulse ( int fd, int reg, int bit ) } +int ppi_setpin ( int fd, int pin, int value ) +{ + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + if (pins[pin].inverted) + value = !value; + + if (value) + ppi_set(fd, pins[pin].reg, pins[pin].bit); + else + ppi_clr(fd, pins[pin].reg, pins[pin].bit); + + return 0; +} + + +int ppi_getpin ( int fd, int pin ) +{ + int value; + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + value = ppi_get(fd, pins[pin].reg, pins[pin].bit); + + if (value) + value = 1; + + if (pins[pin].inverted) + value = !value; + + return value; +} + + +int ppi_pulsepin ( int fd, int pin ) +{ + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + + return 0; +} + + +int ppi_getpinmask ( int pin ) +{ + if (pin < 1 || pin > 17) + return -1; + + return pins[pin-1].bit; +} + + +int ppi_getpinreg ( int pin ) +{ + if (pin < 1 || pin > 17) + return -1; + + return pins[pin-1].reg; +} + + /* * infinite loop, sensing on the pin that we use to read data out of * the device; this is a debugging aid, you can insert a call to this * function in 'main()' and can use it to determine whether your sense * pin is actually sensing. */ -int ppi_sense_test ( int fd, int reg, int bit ) +int ppi_sense ( int fd ) { - unsigned char v, pv; + unsigned int r, pr; + unsigned int v; + int count; + char buf[128]; + int i; - pv = 1; + count = 0; + + fprintf ( stderr, + "parallel port data:\n" + " 111111111\n" + "123456789012345678\n" ); + + buf[17] = 0; + pr = 1; do { - usleep(100000); /* check every 100 ms */ - v = ppi_get(fd, reg, bit); - if (v != pv) { - fprintf ( stderr, "sense bit = %d\n", v ); + usleep(1); /* don't be too much of a cpu hog */ + for (i=1; i<=17; i++) { + buf[i-1] = ppi_getpin(fd, i); + if (buf[i-1]) + buf[i-1] = '|'; + else + buf[i-1] = '.'; } - pv = v; + fprintf(stderr, "\r \r%s", buf); + } while(1); return 0; diff --git a/ppi.h b/ppi.h index 66c51764..1225e6fa 100644 --- a/ppi.h +++ b/ppi.h @@ -41,21 +41,33 @@ enum { PPISTATUS }; -int ppi_getops ( int reg, unsigned long * get, unsigned long * set ); +int ppi_getops ( int reg, unsigned long * get, unsigned long * set ); -int ppi_set ( int fd, int reg, int bit ); +int ppi_set ( int fd, int reg, int bit ); -int ppi_clr ( int fd, int reg, int bit ); +int ppi_clr ( int fd, int reg, int bit ); -int ppi_get ( int fd, int reg, int bit ); +int ppi_get ( int fd, int reg, int bit ); -int ppi_toggle ( int fd, int reg, int bit ); +int ppi_toggle ( int fd, int reg, int bit ); -int ppi_getall ( int fd, int reg ); +int ppi_getall ( int fd, int reg ); -int ppi_setall ( int fd, int reg, int val ); +int ppi_setall ( int fd, int reg, int val ); -int ppi_pulse ( int fd, int reg, int bit ); +int ppi_pulse ( int fd, int reg, int bit ); + +int ppi_setpin ( int fd, int pin, int value ); + +int ppi_getpin ( int fd, int pin ); + +int ppi_pulsepin ( int fd, int pin ); + +int ppi_getpinmask ( int pin ); + +int ppi_getpinreg ( int pin ); + +int ppi_sense ( int fd ); #endif