diff --git a/ChangeLog b/ChangeLog
index 7e419b6c..541b4467 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-05-05  Rene Liebscher <R.Liebscher@gmx.de>
+
+	* main.c: revert to rev 1159 (doing pgm_display after pgm_open)
+	* avrpart.[ch]: moved avr_pin_name to pindefs.[ch]
+	* pgm.c: moved pins_to_str to pindefs.[ch], added initialization of 
+          new pin definitions in pgm_new()
+	* pindefs.[ch]: added moved functions from other files, added a lot of 
+          documentation, reformatted files using astyle to have consistent spacing,
+          added a new generic check function for pins
+	* ft245r.c: used new generic pin check function
+
 2013-05-03  Rene Liebscher <R.Liebscher@gmx.de>
 
 	Create new pin definition data structures to support 0-based pin numbers,
diff --git a/avrpart.c b/avrpart.c
index 589f21ec..af17429e 100644
--- a/avrpart.c
+++ b/avrpart.c
@@ -595,24 +595,6 @@ static char * reset_disp_str(int r)
 }
 
 
-const char * avr_pin_name(int pinno)
-{
-  switch (pinno) {
-    case PPI_AVR_VCC   : return "VCC";
-    case PPI_AVR_BUFF  : return "BUFF";
-    case PIN_AVR_RESET : return "RESET";
-    case PIN_AVR_SCK   : return "SCK";
-    case PIN_AVR_MOSI  : return "MOSI";
-    case PIN_AVR_MISO  : return "MISO";
-    case PIN_LED_ERR   : return "ERRLED";
-    case PIN_LED_RDY   : return "RDYLED";
-    case PIN_LED_PGM   : return "PGMLED";
-    case PIN_LED_VFY   : return "VFYLED";
-    default : return "<unknown>";
-  }
-}
-
-
 void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
 {
   int i;
diff --git a/avrpart.h b/avrpart.h
index 05a60bfe..3396af77 100644
--- a/avrpart.h
+++ b/avrpart.h
@@ -222,7 +222,6 @@ void      avr_free_part(AVRPART * d);
 AVRPART * locate_part(LISTID parts, char * partdesc);
 AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
 void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose);
-const char * avr_pin_name(int);
 
 typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
                                  const char *cfgname, int cfglineno,
diff --git a/ft245r.c b/ft245r.c
index dfb0ff5d..6ab7c09b 100644
--- a/ft245r.c
+++ b/ft245r.c
@@ -328,34 +328,6 @@ static int ft245r_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) {
     return 3;
 }
 
-static int ft245r_check_pins(PROGRAMMER * pgm){
-    static const int pinlist[] = {PIN_AVR_SCK,PIN_AVR_MOSI,PIN_AVR_MISO,PIN_AVR_RESET,PPI_AVR_BUFF};
-    static const pinmask_t valid_pins[PIN_FIELD_SIZE] = { 0x000000ff }; // only lower 8 pins are allowed
-    pinmask_t already_used[PIN_FIELD_SIZE] = {0};
-    int i,j;
-
-    for( i=0; i<sizeof(pinlist)/sizeof(pinlist[0]); i++){
-        for( j=0; j<PIN_FIELD_SIZE; j++){
-            // check if it does not use any non valid pins
-            if(pgm->pin[pinlist[i]].mask[j] & ~valid_pins[j]){
-                fprintf(stderr,
-                    "%s: at least one pin is not a valid pin number\n",
-                    progname);
-                exit(1);
-            }
-            // check if it does not use same pins as other function
-            if(pgm->pin[pinlist[i]].mask[j] & already_used[j]){
-                fprintf(stderr,
-                    "%s: at least one pin is set for multiple functions.\n",
-                    progname);
-                exit(1);
-            }
-            already_used[j] |= pgm->pin[pinlist[i]].mask[j];
-        }
-    }
-    return 0;
-}
-
 /*
  * initialize the AVR device and prepare it to accept commands
  */
@@ -456,12 +428,26 @@ static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
     return 0;
 }
 
+/* lower 8 pins are accepted, they might be also inverted */
+static const struct pindef_t valid_pins = {{0xff},{0xff}} ;
+
+static const struct pin_checklist_t pin_checklist[] = {
+    { PIN_AVR_SCK,  1, &valid_pins},
+    { PIN_AVR_MOSI, 1, &valid_pins},
+    { PIN_AVR_MISO, 1, &valid_pins},
+    { PIN_AVR_RESET,1, &valid_pins},
+    { PPI_AVR_BUFF, 0, &valid_pins},
+};
 
 static int ft245r_open(PROGRAMMER * pgm, char * port) {
     int rv;
     int devnum = -1;
 
-    ft245r_check_pins(pgm);
+    rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]));
+    if(rv) {
+        pgm->display(pgm, progbuf);
+        return rv;
+    }
 
     strcpy(pgm->port, port);
 
@@ -556,14 +542,17 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
 
 
 static void ft245r_close(PROGRAMMER * pgm) {
-    // I think the switch to BB mode and back flushes the buffer.
-    ftdi_set_bitmode(handle, 0, BITMODE_SYNCBB); // set Synchronous BitBang, all in puts
-    ftdi_set_bitmode(handle, 0, BITMODE_RESET); // disable Synchronous BitBang
-    pthread_cancel(readerthread);
-    pthread_join(readerthread, NULL);
-    ftdi_usb_close(handle);
-    ftdi_deinit (handle);
-    free(handle);
+    if (handle) {
+        // I think the switch to BB mode and back flushes the buffer.
+        ftdi_set_bitmode(handle, 0, BITMODE_SYNCBB); // set Synchronous BitBang, all in puts
+        ftdi_set_bitmode(handle, 0, BITMODE_RESET); // disable Synchronous BitBang
+        pthread_cancel(readerthread);
+        pthread_join(readerthread, NULL);
+        ftdi_usb_close(handle);
+        ftdi_deinit (handle);
+        free(handle);
+        handle = NULL;
+    }
 }
 
 static void ft245r_display(PROGRAMMER * pgm, const char * p) {
@@ -849,6 +838,8 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
     pgm->paged_load = ft245r_paged_load;
 
     pgm->read_sig_bytes = ft245r_read_sig_bytes;
+
+    handle = NULL;
 }
 
 #else
diff --git a/main.c b/main.c
index 9c14147e..b9e91888 100644
--- a/main.c
+++ b/main.c
@@ -921,12 +921,6 @@ int main(int argc, char * argv [])
     pgm->ispdelay = ispdelay;
   }
 
-  if (verbose) {
-    avr_display(stderr, p, progbuf, verbose);
-    fprintf(stderr, "\n");
-    programmer_display(pgm, progbuf);
-  }
-
   rc = pgm->open(pgm, port);
   if (rc < 0) {
     exitrc = 1;
@@ -943,7 +937,7 @@ int main(int argc, char * argv [])
     if (pgm->perform_osccal == 0) {
       fprintf(stderr,
               "%s: programmer does not support RC oscillator calibration\n",
-              progname);
+	      progname);
       exitrc = 1;
     } else {
       fprintf(stderr, "%s: performing RC oscillator calibration\n", progname);
@@ -957,6 +951,12 @@ int main(int argc, char * argv [])
     goto main_exit;
   }
 
+  if (verbose) {
+    avr_display(stderr, p, progbuf, verbose);
+    fprintf(stderr, "\n");
+    programmer_display(pgm, progbuf);
+  }
+
   if (quell_progress < 2) {
     fprintf(stderr, "\n");
   }
diff --git a/pgm.c b/pgm.c
index b82e0847..416da650 100644
--- a/pgm.c
+++ b/pgm.c
@@ -83,8 +83,10 @@ PROGRAMMER * pgm_new(void)
   pgm->baudrate = 0;
   pgm->initpgm = NULL;
 
-  for (i=0; i<N_PINS; i++)
+  for (i=0; i<N_PINS; i++) {
     pgm->pinno[i] = 0;
+    pin_clear_all(&(pgm->pin[i]));
+  }
 
   /*
    * mandatory functions - these are called without checking to see
@@ -211,34 +213,6 @@ void programmer_display(PROGRAMMER * pgm, const char * p)
   pgm->display(pgm, p);
 }
 
-static char * pins_to_str(const struct pindef_t * const pindef)
-{
-  static char buf[(PIN_MAX+1)*5]; // should be enough for PIN_MAX=255
-  char *p = buf;
-  int n;
-  int pin;
-  const char * fmt;
-
-  buf[0] = 0;
-  for (pin = PIN_MIN; pin <= PIN_MAX; pin++) {
-    int index = pin/PIN_FIELD_ELEMENT_SIZE;
-    int bit = pin%PIN_FIELD_ELEMENT_SIZE;
-    if (pindef->mask[index] & (1 << bit)) {
-      if (pindef->inverse[index] & (1 << bit)) {
-         fmt = (buf[0]==0)?"~%d":",~%d";
-      } else {
-         fmt = (buf[0]==0)?" %d":",%d";
-      }
-      n = sprintf(p, fmt, pin);
-      p += n;
-    }
-  }
-
-  if (buf[0] == 0)
-     return " (not used)";
-
-  return buf;
-}
 
 void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show)
 {
diff --git a/pindefs.c b/pindefs.c
index 9ce9ddc3..b4268a7d 100644
--- a/pindefs.c
+++ b/pindefs.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include "avrdude.h"
 #include "pindefs.h"
 #include "pgm.h"
 
@@ -31,13 +32,14 @@
  * @param[in] pin number of pin [0..PIN_MAX]
  * @param[in] inverse inverse (true) or normal (false) pin
  */
-void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse){
+void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse) {
 
-  pindef->mask[pin/PIN_FIELD_ELEMENT_SIZE] |= 1 << (pin % PIN_FIELD_ELEMENT_SIZE);
-  if (inverse)
-    pindef->inverse[pin/PIN_FIELD_ELEMENT_SIZE] |=  (1 << (pin % PIN_FIELD_ELEMENT_SIZE));
-  else
-    pindef->inverse[pin/PIN_FIELD_ELEMENT_SIZE] &= ~(1 << (pin % PIN_FIELD_ELEMENT_SIZE));
+  pindef->mask[pin / PIN_FIELD_ELEMENT_SIZE] |= 1 << (pin % PIN_FIELD_ELEMENT_SIZE);
+  if(inverse) {
+    pindef->inverse[pin / PIN_FIELD_ELEMENT_SIZE] |= (1 << (pin % PIN_FIELD_ELEMENT_SIZE));
+  } else {
+    pindef->inverse[pin / PIN_FIELD_ELEMENT_SIZE] &= ~(1 << (pin % PIN_FIELD_ELEMENT_SIZE));
+  }
 }
 
 /**
@@ -45,8 +47,8 @@ void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inv
  *
  * @param[out] pindef pin definition to clear
  */
-void pin_clear_all(struct pindef_t * const pindef){
-    memset(pindef,0,sizeof(struct pindef_t));
+void pin_clear_all(struct pindef_t * const pindef) {
+  memset(pindef, 0, sizeof(struct pindef_t));
 }
 
 /**
@@ -55,22 +57,22 @@ void pin_clear_all(struct pindef_t * const pindef){
  * @param[in] pindef new pin definition structure
  * @param[out] pinno old pin definition integer
  */
-static void pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno){
-    bool found = false;
-    int i;
-    for (i=0;i<PIN_MAX;i++){
-      if (pindef->mask[i/PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))){
-        if(found){
-	    fprintf(stderr,"Multiple pins found\n"); //TODO
-	    exit(1);
-	}
-	found = true;
-	*pinno = i;
-	if (pindef->inverse[i/PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))){
-	    *pinno |= PIN_INVERSE;
-	}
+static void pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno) {
+  bool found = false;
+  int i;
+  for(i = 0; i < PIN_MAX; i++) {
+    if(pindef->mask[i / PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))) {
+      if(found) {
+        fprintf(stderr, "Multiple pins found\n"); //TODO
+        exit(1);
+      }
+      found = true;
+      *pinno = i;
+      if(pindef->inverse[i / PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))) {
+        *pinno |= PIN_INVERSE;
       }
     }
+  }
 }
 
 /**
@@ -79,29 +81,29 @@ static void pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned in
  * @param[in] pindef new pin definition structure
  * @param[out] pinno old pin definition integer
  */
-static void pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned int * const pinno){
-    int i;
+static void pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned int * const pinno) {
+  int i;
 
-    for (i=0;i<PIN_FIELD_SIZE;i++){
-      if(i == 0) {
-	if ((pindef->mask[i] & ~PIN_MASK) != 0){
-	    fprintf(stderr,"Pins of higher index than max field size for old pinno found\n");
-	    exit(1);
-	}
-	if (pindef->mask[i] == pindef->inverse[i]) { /* all set bits in mask are set in inverse */
-	    *pinno = pindef->mask[i];
-	    *pinno |= PIN_INVERSE;
-	} else if (pindef->mask[i] == ((~pindef->inverse[i]) & pindef->mask[i])) { /* all set bits in mask are cleared in inverse */
-	    *pinno = pindef->mask[i];
-	} else {
-	    fprintf(stderr,"pins have different polarity set\n");
-	    exit(1);
-        }
-      } else if (pindef->mask[i] != 0){
-	    fprintf(stderr,"Pins have higher number than fit in old format\n");
-	    exit(1);
+  for(i = 0; i < PIN_FIELD_SIZE; i++) {
+    if(i == 0) {
+      if((pindef->mask[i] & ~PIN_MASK) != 0) {
+        fprintf(stderr, "Pins of higher index than max field size for old pinno found\n");
+        exit(1);
       }
+      if(pindef->mask[i] == pindef->inverse[i]) {  /* all set bits in mask are set in inverse */
+        *pinno = pindef->mask[i];
+        *pinno |= PIN_INVERSE;
+      } else if(pindef->mask[i] == ((~pindef->inverse[i]) & pindef->mask[i])) {  /* all set bits in mask are cleared in inverse */
+        *pinno = pindef->mask[i];
+      } else {
+        fprintf(stderr, "pins have different polarity set\n");
+        exit(1);
+      }
+    } else if(pindef->mask[i] != 0) {
+      fprintf(stderr, "Pins have higher number than fit in old format\n");
+      exit(1);
     }
+  }
 }
 
 
@@ -114,13 +116,243 @@ void pgm_fill_old_pins(struct programmer_t * const pgm) {
 
   pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_VCC]),  &(pgm->pinno[PPI_AVR_VCC]));
   pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_BUFF]), &(pgm->pinno[PPI_AVR_BUFF]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_AVR_RESET]),&(pgm->pinno[PIN_AVR_RESET]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_AVR_SCK]),  &(pgm->pinno[PIN_AVR_SCK]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_AVR_MOSI]), &(pgm->pinno[PIN_AVR_MOSI]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_AVR_MISO]), &(pgm->pinno[PIN_AVR_MISO]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_LED_ERR]),  &(pgm->pinno[PIN_LED_ERR]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_LED_RDY]),  &(pgm->pinno[PIN_LED_RDY]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_LED_PGM]),  &(pgm->pinno[PIN_LED_PGM]));
-  pin_fill_old_pinno(  &(pgm->pin[PIN_LED_VFY]),  &(pgm->pinno[PIN_LED_VFY]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_AVR_RESET]), &(pgm->pinno[PIN_AVR_RESET]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SCK]),  &(pgm->pinno[PIN_AVR_SCK]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_AVR_MOSI]), &(pgm->pinno[PIN_AVR_MOSI]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_AVR_MISO]), &(pgm->pinno[PIN_AVR_MISO]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_LED_ERR]),  &(pgm->pinno[PIN_LED_ERR]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_LED_RDY]),  &(pgm->pinno[PIN_LED_RDY]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_LED_PGM]),  &(pgm->pinno[PIN_LED_PGM]));
+  pin_fill_old_pinno(&(pgm->pin[PIN_LED_VFY]),  &(pgm->pinno[PIN_LED_VFY]));
+
+}
+
+/**
+ * This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12
+ * Another execution of this function will overwrite the previous result in the static buffer.
+ * Consecutive pin number are representated as start-end.
+ *
+ * @param[in] pinmask the pin mask for which we want the string representation
+ * @returns pointer to a static string.
+ */
+const char * pinmask_to_str(const pinmask_t * const pinmask) {
+  static char buf[(PIN_MAX + 1) * 5]; // should be enough for PIN_MAX=255
+  char *p = buf;
+  int n;
+  int pin;
+  const char * fmt;
+  int start = -1;
+  int end = -1;
+
+  buf[0] = 0;
+  for(pin = PIN_MIN; pin <= PIN_MAX; pin++) {
+    int index = pin / PIN_FIELD_ELEMENT_SIZE;
+    int bit = pin % PIN_FIELD_ELEMENT_SIZE;
+    if(pinmask[index] & (1 << bit)) {
+      bool output = false;
+      if(start == -1) {
+        output = true;
+        start = pin;
+        end = start;
+      } else if(pin == end + 1) {
+        end = pin;
+      } else {
+        if(start != end) {
+          n = sprintf(p, "-%d", end);
+          p += n;
+        }
+        output = true;
+        start = pin;
+        end = start;
+      }
+      if(output) {
+        fmt = (buf[0] == 0) ? "%d" : ",%d";
+        n = sprintf(p, fmt, pin);
+        p += n;
+      }
+    }
+  }
+  if(start != end) {
+    n = sprintf(p, "-%d", end);
+    p += n;
+  }
+
+  if(buf[0] == 0)
+    return  "(no pins)";
+
+  return buf;
+}
+
+
+/**
+ * This function checks all pin of pgm against the constraints given in the checklist.
+ * It checks if 
+ * @li any invalid pins are used
+ * @li valid pins are used inverted when not allowed
+ * @li any pins are used by more than one function
+ * @li any mandatory pin is not set all.
+ *
+ * In case of any error it report the wrong function and the pin numbers.
+ * For verbose >= 2 it also reports the possible correct values.
+ * For verbose >=3 it shows also which pins were ok.
+ *
+ * @param[in] pgm the programmer to check
+ * @param[in] checklist the constraint for the pins
+ * @param[in] size the number of entries in checklist
+ * @returns 0 if all pin definitions are valid, -1 otherwise
+ */
+int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size) {
+  static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
+  int rv = 0; // return value
+  int pinname; // loop counter through pinnames
+  pinmask_t already_used_all[PIN_FIELD_SIZE] = {0}; // collect pin definitions of all pin names for check of double use
+  // loop over all possible pinnames
+  for(pinname = 0; pinname < N_PINS; pinname++) {
+    bool used = false;
+    bool invalid = false;
+    bool inverse = false;
+    int index;
+    int segment;
+    bool mandatory_used = false;
+    pinmask_t invalid_used[PIN_FIELD_SIZE] = {0};
+    pinmask_t inverse_used[PIN_FIELD_SIZE] = {0};
+    pinmask_t already_used[PIN_FIELD_SIZE] = {0};
+    const struct pindef_t * valid_pins = &no_valid_pins;
+    bool is_mandatory = false;
+    bool is_ok = true;
+    //find corresponding check pattern
+    for(index = 0; index < size; index++) {
+      if(checklist[index].pinname == pinname) {
+        valid_pins = checklist[index].valid_pins;
+        is_mandatory = checklist[index].mandatory;
+        break;
+      }
+    }
+
+    for(segment = 0; segment < PIN_FIELD_SIZE; segment++) {
+      // check if for mandatory any pin is defined
+      invalid_used[segment] = pgm->pin[pinname].mask[segment] & ~valid_pins->mask[segment];
+      if(is_mandatory && (0 != (pgm->pin[pinname].mask[segment] & valid_pins->mask[segment]))) {
+        mandatory_used = true;
+      }
+      // check if it does not use any non valid pins
+      invalid_used[segment] = pgm->pin[pinname].mask[segment] & ~valid_pins->mask[segment];
+      if(invalid_used[segment]) {
+        invalid = true;
+      }
+      // check if it does not use any valid pins as inverse if not allowed
+      inverse_used[segment] = pgm->pin[pinname].inverse[segment] & valid_pins->mask[segment] & ~valid_pins->inverse[segment];
+      if(inverse_used[segment]) {
+        inverse = true;
+      }
+      // check if it does not use same pins as other function
+      already_used[segment] = pgm->pin[pinname].mask[segment] & already_used_all[segment];
+      if(already_used[segment]) {
+        used = true;
+      }
+      already_used_all[segment] |= pgm->pin[pinname].mask[segment];
+    }
+    if(invalid) {
+      fprintf(stderr,
+              "%s: %s: Following pins are not valid pins for this function: %s\n",
+              progname, avr_pin_name(pinname), pinmask_to_str(invalid_used));
+      if(verbose >= 2) {
+        fprintf(stderr,
+                "%s: %s: Valid pins for this function are: %s\n",
+                progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
+      }
+      is_ok = false;
+    }
+    if(inverse) {
+      fprintf(stderr,
+              "%s: %s: Following pins are not usable as inverse pins for this function: %s\n",
+              progname, avr_pin_name(pinname), pinmask_to_str(inverse_used));
+      if(verbose >= 2) {
+        fprintf(stderr,
+                "%s: %s: Valid inverse pins for this function are: %s\n",
+                progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
+      }
+      is_ok = false;
+    }
+    if(used) {
+      fprintf(stderr,
+              "%s: %s: Following pins are set for other functions too: %s\n",
+              progname, avr_pin_name(pinname), pinmask_to_str(already_used));
+      is_ok = false;
+    }
+    if(!mandatory_used && is_mandatory && !invalid) {
+      fprintf(stderr,
+              "%s: %s: Mandatory pin is not defined.\n",
+              progname, avr_pin_name(pinname));
+      is_ok = false;
+    }
+    if(!is_ok) {
+      rv = -1;
+    } else if(verbose >= 3) {
+      fprintf(stderr,
+              "%s: %s: Pin is ok.\n",
+              progname, avr_pin_name(pinname));
+
+    }
+  }
+  return rv;
+}
+
+/**
+ * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
+ * Another execution of this function will overwrite the previous result in the static buffer.
+ *
+ * @param[in] pindef the pin definition for which we want the string representation
+ * @returns pointer to a static string.
+ */
+const char * pins_to_str(const struct pindef_t * const pindef) {
+  static char buf[(PIN_MAX + 1) * 5]; // should be enough for PIN_MAX=255
+  char *p = buf;
+  int n;
+  int pin;
+  const char * fmt;
+
+  buf[0] = 0;
+  for(pin = PIN_MIN; pin <= PIN_MAX; pin++) {
+    int index = pin / PIN_FIELD_ELEMENT_SIZE;
+    int bit = pin % PIN_FIELD_ELEMENT_SIZE;
+    if(pindef->mask[index] & (1 << bit)) {
+      if(pindef->inverse[index] & (1 << bit)) {
+        fmt = (buf[0] == 0) ? "~%d" : ",~%d";
+      } else {
+        fmt = (buf[0] == 0) ? " %d" : ",%d";
+      }
+      n = sprintf(p, fmt, pin);
+      p += n;
+    }
+  }
+
+  if(buf[0] == 0)
+    return " (not used)";
+
+  return buf;
+}
+
+/**
+ * Returns the name of the pin as string.
+ * 
+ * @param pinname the pinname which we want as string.
+ * @returns a string with the pinname, or <unknown> if pinname is invalid.
+ */
+const char * avr_pin_name(int pinname) {
+  switch(pinname) {
+  case PPI_AVR_VCC   : return "VCC";
+  case PPI_AVR_BUFF  : return "BUFF";
+  case PIN_AVR_RESET : return "RESET";
+  case PIN_AVR_SCK   : return "SCK";
+  case PIN_AVR_MOSI  : return "MOSI";
+  case PIN_AVR_MISO  : return "MISO";
+  case PIN_LED_ERR   : return "ERRLED";
+  case PIN_LED_RDY   : return "RDYLED";
+  case PIN_LED_PGM   : return "PGMLED";
+  case PIN_LED_VFY   : return "VFYLED";
+  default : return "<unknown>";
+  }
+}
+
 
-}
\ No newline at end of file
diff --git a/pindefs.h b/pindefs.h
index 8948dab9..252d67bc 100644
--- a/pindefs.h
+++ b/pindefs.h
@@ -35,7 +35,7 @@ typedef unsigned long pinmask_t;
 
 
 enum {
-  PPI_AVR_VCC=1,
+  PPI_AVR_VCC = 1,
   PPI_AVR_BUFF,
   PIN_AVR_RESET,
   PIN_AVR_SCK,
@@ -72,7 +72,7 @@ enum {
  * @param[in] x       input value
  * @param[in] pgm     the programmer whose pin definitions to use
  * @param[in] pinname the logical name of the pin (PIN_AVR_*, ...)
- * @param[in] level   the logical level (level != 0 => 1, level == 0 => 0), 
+ * @param[in] level   the logical level (level != 0 => 1, level == 0 => 0),
  *                      if the pin is defined as inverted the resulting bit is also inverted
  * @returns           the input value with the relevant bits modified
  */
@@ -106,16 +106,90 @@ enum {
  * Data structure to hold used pins by logical function (PIN_AVR_*, ...)
  */
 struct pindef_t {
-    pinmask_t mask[PIN_FIELD_SIZE]; ///< bitfield of used pins
-    pinmask_t inverse[PIN_FIELD_SIZE]; ///< bitfield of inverse/normal usage of used pins
+  pinmask_t mask[PIN_FIELD_SIZE]; ///< bitfield of used pins
+  pinmask_t inverse[PIN_FIELD_SIZE]; ///< bitfield of inverse/normal usage of used pins
 };
 
+/**
+ * Data structure to define a checklist of valid pins for each function.
+ */
+struct pin_checklist_t {
+  int pinname; ///< logical pinname eg. PIN_AVR_SCK
+  int mandatory; ///< is this a mandatory pin
+  const struct pindef_t* valid_pins; ///< mask defines allowed pins, inverse define is they might be used inverted
+};
+
+/**
+ * Adds a pin in the pin definition as normal or inverse pin.
+ *
+ * @param[out] pindef pin definition to update
+ * @param[in] pin number of pin [0..PIN_MAX]
+ * @param[in] inverse inverse (true) or normal (false) pin
+ */
 void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse);
 
+/**
+ * Clear all defined pins in pindef.
+ *
+ * @param[out] pindef pin definition to clear
+ */
 void pin_clear_all(struct pindef_t * const pindef);
 
 struct programmer_t; /* forward declaration */
+
+/**
+ * Convert for given programmer new pin definitions to old pin definitions.
+ *
+ * @param[inout] pgm programmer whose pins shall be converted.
+ */
 void pgm_fill_old_pins(struct programmer_t * const pgm);
 
+/**
+ * This function checks all pin of pgm against the constraints given in the checklist.
+ * It checks if 
+ * @li any invalid pins are used
+ * @li valid pins are used inverted when not allowed
+ * @li any pins are used by more than one function
+ * @li any mandatory pin is not set all.
+ *
+ * In case of any error it report the wrong function and the pin numbers.
+ * For verbose >= 2 it also reports the possible correct values.
+ * For verbose >=3 it shows also which pins were ok.
+ *
+ * @param[in] pgm the programmer to check
+ * @param[in] checklist the constraint for the pins
+ * @param[in] size the number of entries in checklist
+ * @returns 0 if all pin definitions are valid, -1 otherwise
+ */
+int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size);
+
+/**
+ * Returns the name of the pin as string.
+ * 
+ * @param pinname the pinname which we want as string.
+ * @returns a string with the pinname, or <unknown> if pinname is invalid.
+ */
+const char * avr_pin_name(int pinname);
+
+/**
+ * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
+ * Another execution of this function will overwrite the previous result in the static buffer.
+ *
+ * @param[in] pindef the pin definition for which we want the string representation
+ * @returns pointer to a static string.
+ */
+const char * pins_to_str(const struct pindef_t * const pindef);
+
+/**
+ * This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12
+ * Another execution of this function will overwrite the previous result in the static buffer.
+ * Consecutive pin number are representated as start-end.
+ *
+ * @param[in] pinmask the pin mask for which we want the string representation
+ * @returns pointer to a static string.
+ */
+const char * pinmask_to_str(const pinmask_t * const pinmask);
+
+
 #endif