diff --git a/Control/cardreader_interface.c b/Control/cardreader_interface.c
index 242b0c59c4e9d3a7a3214e3f2d8edb172d86120c..423063f55489edd0e7c543f67e2d8c8aadd433d8 100644
--- a/Control/cardreader_interface.c
+++ b/Control/cardreader_interface.c
@@ -32,8 +32,7 @@
  *    Card -> Host:   other ISO7816 status code (-> abort)
 **/
 
-
-void unlock(void);
+void cardreader_process_message(void);
 uint8_t check_card_status(uint8_t* msg_buffer, uint8_t length, uint8_t expected_body_length);
 void cardreader_select_auth_applet(void);
 uint8_t cardreader_select_auth_applet_result(uint8_t* msg_buffer, uint8_t length);
@@ -59,11 +58,11 @@ uint8_t cardreader_sys_get_card_status(void);
 static uint8_t cardreader_power_state = CARDREADER_POWER_STATE_OFF;
 static volatile uint8_t cardreader_startup_event = 0;
 
-#define AUTH_STATE_NONE 1
-#define AUTH_STATE_CARD_INSERTED 2
-#define AUTH_STATE_SELECTING_AUTH_APPLET 3
-#define AUTH_STATE_AUTH_REQUESTED_SENT 4
-#define AUTH_STATE_AUTH_VERYFIED 5
+#define AUTH_STATE_NONE 1                   //System idle
+#define AUTH_STATE_CARD_INSERTED 2          //Card has been inserted into th reader, auth will be started.
+#define AUTH_STATE_SELECTING_AUTH_APPLET 3  //APDU to select the portal auth application has been sent.
+#define AUTH_STATE_AUTH_REQUESTED_SENT 4    //Authorisation challange has been sent.
+#define AUTH_STATE_AUTH_VERYFIED 5          //Authorisation key has been verified, new key has been sent.
 
 volatile uint8_t auth_state = AUTH_STATE_NONE;
 volatile uint16_t state_timeout;
@@ -145,8 +144,10 @@ void cardreader_process(void){
 		return;
 	}
 	
-	if (!transport_data_available()) return;
-	
+	if (transport_data_available()) cardreader_process_message();
+}
+
+void cardreader_process_message(void){
 	uint8_t msg_buffer[100];
 	
 	uint16_t ret = transport_receive_message(msg_buffer, 100, 400);
@@ -337,11 +338,13 @@ uint8_t cardreader_update_key_result(uint8_t* msg_buffer, uint8_t length){
 // 	cardreader_display_show_result(1);
 	
 	cardreader_display_clear();
-	if (toggle_lock_unlock(cardreader_display_write_sz_P)){
+// 	if (
+	toggle_lock_unlock(cardreader_display_write_sz_P);
+// 		){
 // 		cardreader_display_write_sz_P(PSTR("Auth Successful"));
-		cardreader_display_move(0,1);
-		cardreader_display_write_sz_P(PSTR("Remove Card"));
-	}
+// 		cardreader_display_move(0,1);
+// 		cardreader_display_write_sz_P(PSTR("Remove Card"));
+// 	}
 	
 	keystore_update_salt();
 	
@@ -448,7 +451,6 @@ void cardreader_display_show_result(uint8_t success){
 	}
 }
 
-
 void cardreader_display_set_backlight(uint8_t on){
 	cardreader_display_message_t msg = {CARDREADER_MSG_TYPE_DISPALY};
 	msg.command = CARDREADER_DISPLAY_MSG_SET_BACKLIGHT;
@@ -457,4 +459,18 @@ void cardreader_display_set_backlight(uint8_t on){
 	
 	uint8_t success;
 	transport_receive_message(&success, 1, 3000);
+}
+
+void cardreader_display_show_door_retry(void){
+	cardreader_display_move(10,0);
+	cardreader_display_write_sz_P(PSTR("Retry"));
+}
+
+void cardreader_display_show_door_result(uint8_t success){
+	cardreader_display_move(0,1);
+	if (success) {
+		cardreader_display_write_sz_P(PSTR("OK, remove card "));
+	} else {
+		cardreader_display_write_sz_P(PSTR("Mechanical Fail!"));
+	}
 }
\ No newline at end of file
diff --git a/Control/cardreader_interface.h b/Control/cardreader_interface.h
index 8843bdf5d341f2531639f2ee408d220099178243..eaf9e16d21997c517faf0646652bd055584fa641 100644
--- a/Control/cardreader_interface.h
+++ b/Control/cardreader_interface.h
@@ -23,4 +23,7 @@ void cardreader_process(void);
 void cardreader_tick(void);
 
 uint8_t cardreader_init_card_key(KEY key);
-uint8_t cardreader_clear_card_key(void);
\ No newline at end of file
+uint8_t cardreader_clear_card_key(void);
+
+void cardreader_display_show_door_retry(void);
+void cardreader_display_show_door_result(uint8_t success);
\ No newline at end of file
diff --git a/Control/door.c b/Control/door.c
index a309e06e9af8cbaaf0b104e22a470f3e62cbad3b..664eaf1374de5380f78be3236d102379fe8b2497 100644
--- a/Control/door.c
+++ b/Control/door.c
@@ -1,5 +1,6 @@
 #include "door.h"
 #include "log.h"
+#include "cardreader_interface.h" //for (un)lock messages
 
 uint8_t door_read_pin_status(void);
 uint8_t door_update_status(uint8_t sensor_status);
@@ -20,17 +21,21 @@ const char* const status_names[] PROGMEM = {status_unlocked,
                                             status_unlocking,
                                             status_locking};
 
-volatile uint8_t door_status;
+uint8_t door_status;
 
-volatile uint8_t sensor_candidate_status;
-volatile uint8_t sensor_stability;
+uint8_t sensor_candidate_status;
+uint8_t sensor_stability;
 #define DOOR_PIN_NEEDED_STABILITY 4
 
-#define DOOR_COMMAND_PULSE_TIME 35 //350ms
-volatile uint8_t door_command_pulse_time = 0;
+#define DOOR_COMMAND_PULSE_TIME 45 //450ms
+uint8_t door_command_pulse_time = 0;
+
+#define DOOR_COMMAND_WAIT_TIMEOUT 900 //9s
+uint16_t door_command_wait_timeout = 0;
+
+uint8_t door_command_retry_count = 0;
+#define DOOR_COMMAND_MAX_RETRY 1
 
-#define DOOR_COMMAND_WAIT_TIMEOUT 1000 //10s
-volatile uint16_t door_command_wait_timeout = 0;
 
 void door_init(void){
 	DOOR_PORT &= ~(COMMAND_UNLOCK_PIN | COMMAND_LOCK_PIN); //commnd pins off
@@ -52,7 +57,9 @@ void door_init(void){
 void door_tick(void){
 	if (door_command_pulse_time != 0) {
 		door_command_pulse_time--;
-		if (door_command_pulse_time == 0) DOOR_PORT &= (uint8_t)~(COMMAND_LOCK_PIN|COMMAND_UNLOCK_PIN);
+		if (door_command_pulse_time == 0) {
+			DOOR_PORT &= (uint8_t)~(COMMAND_LOCK_PIN|COMMAND_UNLOCK_PIN);
+		}
 	}
 	
 	if (   ((door_status & DOOR_STATUS_UNLOCKING) && !(door_status & DOOR_STATUS_UNLOCKED))
@@ -60,12 +67,30 @@ void door_tick(void){
 		door_command_wait_timeout--;
 		if (door_command_wait_timeout == 0){
 			
-			printf_P(PSTR("Error: Door command timeout\n"));
 			log_append(LOG_EVENT_DOOR_COMMAND_TIMEOUT, 0);
 			
-			//TODO: Retry (and turn keymatic power on if currently off)
+			printf_P(PSTR("Error: Door command timeout!"));
 			
-			door_status &= (uint8_t)~(DOOR_STATUS_UNLOCKING | DOOR_STATUS_LOCKING); //clear activity flags
+			if (door_command_retry_count < DOOR_COMMAND_MAX_RETRY){
+				printf_P(PSTR(" Retry...\n"));
+				cardreader_display_show_door_retry();
+				uint8_t retry = door_command_retry_count;
+				
+				//TODO: turn keymatic power on if currently off?
+				if (door_status & DOOR_STATUS_UNLOCKING) unlock();
+				if (door_status & DOOR_STATUS_LOCKING  ) lock();
+				//lock/unlock resets the counter, restore it.
+				door_command_retry_count = retry + 1;
+				
+			} else {
+				
+				log_append(LOG_EVENT_DOOR_COMMAND_RETRY_FAIL, 0);
+				
+				printf_P(" Giving Up :((\n");
+				cardreader_display_show_door_result(0);
+				
+				door_status &= (uint8_t)~(DOOR_STATUS_UNLOCKING | DOOR_STATUS_LOCKING); //clear activity flags
+			}
 		}
 	}
 	
@@ -95,8 +120,15 @@ uint8_t door_read_pin_status(void){
 uint8_t door_update_status(uint8_t sensor_status){
 	uint8_t new_door_status = (sensor_status & DOOR_STATUS_HW_MASK) | (door_status & DOOR_STATUS_SW_MASK);
 
-	if (new_door_status & DOOR_STATUS_LOCKED)   new_door_status &= (uint8_t)~DOOR_STATUS_LOCKING;
-	if (new_door_status & DOOR_STATUS_UNLOCKED) new_door_status &= (uint8_t)~DOOR_STATUS_UNLOCKING;
+	if ((new_door_status & DOOR_STATUS_LOCKED) && (door_status & DOOR_STATUS_LOCKING)){
+		new_door_status &= (uint8_t)~DOOR_STATUS_LOCKING;
+		cardreader_display_show_door_result(1);
+	}
+		
+	if ((new_door_status & DOOR_STATUS_UNLOCKED) && (door_status & DOOR_STATUS_UNLOCKING)){
+		new_door_status &= (uint8_t)~DOOR_STATUS_UNLOCKING;
+		cardreader_display_show_door_result(1);
+	}
 	
 	if (is_alarm_status(new_door_status)) new_door_status |= DOOR_STATUS_ALARM;
 	
@@ -114,7 +146,7 @@ uint8_t is_alarm_status(uint8_t door_status){
 	
 	//NOTE: This condition is supposed to trigger, if the door is slammed open.
 	//      We can't use the LOCKED sensor, because the connection between lock bolt and frame will be interrupted by this.
-	//      This connection is what the sensor actually detects. TODO: Can we improove this?
+	//      This connection is what the sensor actually detects. TODO: Can we improve this?
 	//      The UNLOCKED sensor, however will be uneffected, leaving the lock sensors in an
 	//      undefined (neither locked nor unlocked) state. We trigger an alarm if this occurs when the door is open.
 	//      Unfortunately the UNLOCKED has shown failures in the past, possibly causing a false alarm.
@@ -136,6 +168,7 @@ uint8_t door_get_status(void){
 void unlock(void){
 	door_command_pulse_time = DOOR_COMMAND_PULSE_TIME;
 	door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT;
+	door_command_retry_count = 0;
 	
 	door_status = (door_status & (uint8_t)~DOOR_STATUS_LOCKING) | DOOR_STATUS_UNLOCKING;
 	DOOR_PORT   = (DOOR_PORT   & (uint8_t)~COMMAND_LOCK_PIN)    | COMMAND_UNLOCK_PIN;
@@ -144,6 +177,9 @@ void unlock(void){
 void lock(void){
 	door_command_pulse_time = DOOR_COMMAND_PULSE_TIME;
 	door_command_wait_timeout = DOOR_COMMAND_WAIT_TIMEOUT;
+	door_command_retry_count = 0;
+	
+// 	printf_P(PSTR("."));
 	
 	door_status = (door_status & (uint8_t)~DOOR_STATUS_UNLOCKING) | DOOR_STATUS_LOCKING;
 	DOOR_PORT   = (DOOR_PORT   & (uint8_t)~COMMAND_UNLOCK_PIN)    | COMMAND_LOCK_PIN;
@@ -158,34 +194,47 @@ uint8_t toggle_lock_unlock( void (*msg_target)(const char*) ){
 }
 
 uint8_t unlock_checked( void (*msg_target)(const char*) ){
+	uint8_t ok = 0;
+	const char* msg;
+	
 	if (door_status & DOOR_STATUS_UNLOCKED){
-		msg_target(PSTR("Already unlocked\n"));
+		msg = PSTR("Already unlocked\n");
 	} else if (door_status & DOOR_STATUS_LOCKING){
-		msg_target(PSTR("Can't unlock while locking\n"));
+		msg = PSTR("Can't unlock while locking\n");
 	} else {
 		unlock();
-		msg_target(PSTR("Unlocking...\n"));
-		return 1;
+		msg = PSTR("Unlocking...\n");
+		ok = 1;
 	}
-	return 0;
+	
+	printf_P(msg);
+	if (msg_target) msg_target(msg);
+	
+	return ok;
 }
 
 
 uint8_t lock_checked( void (*msg_target)(const char*) ){
+	uint8_t ok = 0;
+	const char* msg;
 	if (is_alarm_status(door_status)){
-		msg_target(PSTR("Can't lock in alarm state\n"));
+		msg = PSTR("Can't lock in alarm state\n");
 	} else if (door_status & DOOR_STATUS_UNLOCKING) {
-		msg_target(PSTR("Can't lock while unlocking\n"));
+		msg = PSTR("Can't lock while unlocking\n");
 	} else if (door_status & DOOR_STATUS_OPEN){
-		msg_target(PSTR("Can't lock while door open\n"));
+		msg = PSTR("Can't lock while door open\n");
 	} else if (door_status & DOOR_STATUS_LOCKED){
-		msg_target(PSTR("Already locked\n"));
+		msg = PSTR("Already locked\n");
 	} else {
 		lock();
-		msg_target(PSTR("Locking...\n"));
-		return 1;
+		msg = PSTR("Locking...\n");
+		ok = 1;
 	}
-	return 0;
+	
+	printf_P(msg);
+	if (msg_target) msg_target(msg);
+	
+	return ok;
 }
 
 uint8_t door_clear_alarm(void){
diff --git a/Control/log.c b/Control/log.c
index c2ce307ca0595b2253600904f1e760a05025c132..2158ae36a3f34f80c7d637fdd419dd42645924d9 100644
--- a/Control/log.c
+++ b/Control/log.c
@@ -5,16 +5,17 @@
 #include "door.h"
 #include "power_monitor.h"
 
-const char log_event_startup[]              PROGMEM = "== System Started ==";
-const char log_event_alarm_raised[]         PROGMEM = "Alarm Raised";
-const char log_event_alarm_changed[]        PROGMEM = "State change during Alarm";
-const char log_event_alarm_login[]          PROGMEM = "Login during Alarm";
-const char log_event_alarm_disabled[]       PROGMEM = "Alarm disabled";
-const char log_event_ac_fail[]              PROGMEM = "AC Power Fail";
-const char log_event_ac_return[]            PROGMEM = "AC Power Restored";
-const char log_event_main_battery_low[]     PROGMEM = "Main Battery Low";
-const char log_event_keymatic_battery_low[] PROGMEM = "Keymatic Battery Low";
-const char log_event_door_command_timeout[] PROGMEM = "Door command Timeout";
+const char log_event_startup[]                 PROGMEM = "== System Started ==";
+const char log_event_alarm_raised[]            PROGMEM = "Alarm Raised";
+const char log_event_alarm_changed[]           PROGMEM = "State change during Alarm";
+const char log_event_alarm_login[]             PROGMEM = "Login during Alarm";
+const char log_event_alarm_disabled[]          PROGMEM = "Alarm disabled";
+const char log_event_ac_fail[]                 PROGMEM = "AC Power Fail";
+const char log_event_ac_return[]               PROGMEM = "AC Power Restored";
+const char log_event_main_battery_low[]        PROGMEM = "Main Battery Low";
+const char log_event_keymatic_battery_low[]    PROGMEM = "Keymatic Battery Low";
+const char log_event_door_command_timeout[]    PROGMEM = "Door command Timeout";
+const char log_event_door_command_retry_fail[] PROGMEM = "Door command retry failed";
 
 const char* const event_names[] PROGMEM = {log_event_startup,
                                log_event_alarm_raised,
@@ -25,7 +26,8 @@ const char* const event_names[] PROGMEM = {log_event_startup,
                                log_event_ac_return,
                                log_event_main_battery_low,
                                log_event_keymatic_battery_low,
-                               log_event_door_command_timeout};
+                               log_event_door_command_timeout,
+                               log_event_door_command_retry_fail};
 
 uint8_t log_get_first_entry_index(void){
 	uint8_t l = eeprom_read_byte(LOG_START_POINTER_LOCATION);
diff --git a/Control/log.h b/Control/log.h
index 111d446ee20b1c978ef4fdb04d17f6019ee3b9a9..67825eb266c7b72df5abe86125eb9f87c58a82d4 100644
--- a/Control/log.h
+++ b/Control/log.h
@@ -20,16 +20,17 @@ struct log_entry_t{
 #define LOG_START_POINTER_LOCATION ((void*)(EEPROM_SIZE-1))
 #define LOG_END_POINTER_LOCATION   ((void*)(EEPROM_SIZE-2))
 
-#define LOG_EVENT_STARTUP              0x00
-#define LOG_EVENT_ALARM_RAISED         0x01
-#define LOG_EVENT_ALARM_CHANGED        0x02
-#define LOG_EVENT_ALARM_LOGIN          0x03
-#define LOG_EVENT_ALARM_DISABLED       0x04
-#define LOG_EVENT_AC_FAIL              0x05
-#define LOG_EVENT_AC_RETURN            0x06
-#define LOG_EVENT_MAIN_BATTERY_LOW     0x07
-#define LOG_EVENT_KEYMATIC_BATTERY_LOW 0x08
-#define LOG_EVENT_DOOR_COMMAND_TIMEOUT 0x09
+#define LOG_EVENT_STARTUP                 0x00
+#define LOG_EVENT_ALARM_RAISED            0x01
+#define LOG_EVENT_ALARM_CHANGED           0x02
+#define LOG_EVENT_ALARM_LOGIN             0x03
+#define LOG_EVENT_ALARM_DISABLED          0x04
+#define LOG_EVENT_AC_FAIL                 0x05
+#define LOG_EVENT_AC_RETURN               0x06
+#define LOG_EVENT_MAIN_BATTERY_LOW        0x07
+#define LOG_EVENT_KEYMATIC_BATTERY_LOW    0x08
+#define LOG_EVENT_DOOR_COMMAND_TIMEOUT    0x09
+#define LOG_EVENT_DOOR_COMMAND_RETRY_FAIL 0x0A
 
 #define LOG_EVENT_NONE                 0xFF
 
diff --git a/Control/shell/shell.c b/Control/shell/shell.c
index 15f840b439455cf3964be5181917156c9330c8cd..158f3540788fabc21e8fc91bec7d7d105b039127 100644
--- a/Control/shell/shell.c
+++ b/Control/shell/shell.c
@@ -302,14 +302,14 @@ void cmd_lock(readline_parsed_cmd_t* cmd){
 	if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){
 		lock();
 	} else {
-		lock_checked(print_P);
+		lock_checked(0);
 	}
 }
 void cmd_unlock(readline_parsed_cmd_t* cmd){
 	if ((cmd->num_args > 0) && (strcmp(cmd->args[0], "-f") == 0)){
 		unlock();
 	} else {
-		unlock_checked(print_P);
+		unlock_checked(0);
 	}
 }