public synchronized static Future<?> blink(GpioPinDigitalOutput pin, long delay, long duration, PinState blinkState) {

        // perform the initial startup and cleanup for this pin 
        init(pin);
        
        // we only blink for requests with a valid delay in milliseconds
        if (delay > 0) {
            // make sure pin starts in active state
            pin.setState(blinkState);
            
            // create future job to toggle the pin state
            ScheduledFuture<?> scheduledFutureBlinkTask = scheduledExecutorService
                .scheduleAtFixedRate(new GpioBlinkTaskImpl(pin), delay, delay, TimeUnit.MILLISECONDS);
                
            // get pending tasks for the current pin
            ArrayList<ScheduledFuture<?>> tasks;
            if (!pinTaskQueue.containsKey(pin)) {
                pinTaskQueue.put(pin, new ArrayList<ScheduledFuture<?>>());
            }
            tasks = pinTaskQueue.get(pin);

            // add the new scheduled task to the tasks collection
            tasks.add(scheduledFutureBlinkTask);

            // if a duration was defined, then schedule a future task to kill the blinker task
            if (duration > 0) {
                // create future job to stop blinking
                ScheduledFuture<?> scheduledFutureBlinkStopTask = scheduledExecutorService
                    .schedule(new GpioBlinkStopTaskImpl(pin,PinState.getInverseState(blinkState), scheduledFutureBlinkTask), duration, TimeUnit.MILLISECONDS);

                // add the new scheduled stop task to the tasks collection
                tasks.add(scheduledFutureBlinkStopTask);

                // create future task to clean up completed tasks
                createCleanupTask(duration + 500);                
            }      

            // return future task
            return scheduledFutureBlinkTask;
        }
        
        // no future task when a delay time has not been specified
        return null;
    }