changeset 424:0d1cc6ec4af7

Merge branch 'master' of github.com:kiibohd/controller
author CryHam <cryham@gmail.com>
date Tue, 01 Mar 2016 19:40:00 +0100
parents be6b57c5b438 (current diff) 23a1868b4ac2 (diff)
children 971e88d4420a
files Scan/MatrixARM/matrix_scan.c
diffstat 26 files changed, 466 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/Bootloader/dfu.desc.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Bootloader/dfu.desc.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,5 +1,5 @@
 // Originally Generated from MCHCK Toolkit
-/* Copyright (c) Jacob Alexander 2014-2015 <haata@kiibohd.com>
+/* Copyright (c) Jacob Alexander 2014-2016 <haata@kiibohd.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,7 +38,7 @@
 		.bConfigurationValue = 1,
 		.iConfiguration = 0,
 		.one = 1,
-		.bMaxPower = 100
+		.bMaxPower = 50
 	},
 	.usb_function_0 = {
 		.iface = {
--- a/Output/pjrcUSB/arm/usb_desc.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/arm/usb_desc.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,7 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
- * Modified by Jacob Alexander (2013-2015)
+ * Modified by Jacob Alexander (2013-2016)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -451,7 +451,7 @@
 	1,                                      // bConfigurationValue
 	0,                                      // iConfiguration
 	0xA0,                                   // bmAttributes
-	250,                                    // bMaxPower
+	250,                                    // bMaxPower - Entry Index 8
 
 // --- Keyboard HID --- Boot Mode Keyboard Interface
 // - 9 bytes -
@@ -695,6 +695,8 @@
 	SYS_CTRL_INTERVAL,                      // bInterval
 };
 
+uint8_t *usb_bMaxPower = &config_descriptor[8];
+
 
 
 // ----- String Descriptors -----
--- a/Output/pjrcUSB/arm/usb_desc.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/arm/usb_desc.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,7 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
- * Modified by Jacob Alexander (2013-2015)
+ * Modified by Jacob Alexander (2013-2016)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -137,3 +137,5 @@
 
 extern const usb_descriptor_list_t usb_descriptor_list[];
 
+extern uint8_t *usb_bMaxPower;
+
--- a/Output/pjrcUSB/arm/usb_dev.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/arm/usb_dev.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,7 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
- * Modifications by Jacob Alexander (2013-2015)
+ * Modifications by Jacob Alexander (2013-2016)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -168,6 +168,9 @@
 
 static uint8_t reply_buffer[8];
 
+static uint8_t power_neg_delay;
+static uint32_t power_neg_time;
+
 
 
 // ----- Functions -----
@@ -188,6 +191,34 @@
 	ep0_tx_bdt_bank ^= 1;
 }
 
+// Used to check any USB state changes that may not have a proper interrupt
+// Called once per scan loop, should take minimal processing time or it may affect other modules
+void usb_device_check()
+{
+	// Check to see if we're still waiting for the next USB request after Get Configuration Descriptor
+	// If still waiting, restart the USB initialization with a lower power requirement
+	if ( power_neg_delay )
+	{
+		// Check if 100 ms has elapsed
+		if ( systick_millis_count - power_neg_time > 100 )
+		{
+			// Update bMaxPower
+			// The value set is in increments of 2 mA
+			// So 50 * 2 mA = 100 mA
+			// XXX Currently only transitions to 100 mA
+			//     It may be possible to transition down again to 20 mA
+			*usb_bMaxPower = 50;
+
+			// Re-initialize USB
+			power_neg_delay = 0;
+			usb_configuration = 0; // Clear USB configuration if we have one
+			USB0_CONTROL = 0; // Disable D+ Pullup to simulate disconnect
+			delay(10); // Delay is necessary to simulate disconnect
+			usb_init();
+		}
+	}
+}
+
 static void usb_setup()
 {
 	const uint8_t *data = NULL;
@@ -199,6 +230,13 @@
 	const uint8_t *cfg;
 	int i;
 
+	// If another request is made, disable the power negotiation check
+	// See GET_DESCRIPTOR - Configuration
+	if ( power_neg_delay )
+	{
+		power_neg_delay = 0;
+	}
+
 	switch ( setup.wRequestAndType )
 	{
 	case 0x0500: // SET_ADDRESS
@@ -212,6 +250,10 @@
 		Output_Available = usb_configuration;
 		reg = &USB0_ENDPT1;
 		cfg = usb_endpoint_config_table;
+
+		// Now configured so we can utilize bMaxPower now
+		Output_update_usb_current( *usb_bMaxPower * 2 );
+
 		// clear all BDT entries, free any allocated memory...
 		for ( i = 4; i < ( NUM_ENDPOINTS + 1) * 4; i++ )
 		{
@@ -324,9 +366,27 @@
 		goto send;
 
 	case 0x0100: // CLEAR_FEATURE (device)
+		switch ( setup.wValue )
+		{
+		// CLEAR_FEATURE(DEVICE_REMOTE_WAKEUP)
+		// See SET_FEATURE(DEVICE_REMOTE_WAKEUP) for details
+		case 0x1:
+			goto send;
+		}
+
+		warn_msg("SET_FEATURE - Device wValue(");
+		printHex( setup.wValue );
+		print( ")" NL );
+		endpoint0_stall();
+		return;
+
 	case 0x0101: // CLEAR_FEATURE (interface)
 		// TODO: Currently ignoring, perhaps useful? -HaaTa
-		warn_print("CLEAR_FEATURE - Device/Interface");
+		warn_msg("CLEAR_FEATURE - Interface wValue(");
+		printHex( setup.wValue );
+		print(") wIndex(");
+		printHex( setup.wIndex );
+		print( ")" NL );
 		endpoint0_stall();
 		return;
 
@@ -342,9 +402,30 @@
 		goto send;
 
 	case 0x0300: // SET_FEATURE (device)
+		switch ( setup.wValue )
+		{
+		// SET_FEATURE(DEVICE_REMOTE_WAKEUP)
+		// XXX: Only used to confirm Remote Wake
+		//      Used on Mac OSX and Windows not on Linux
+		// Good post on the behaviour:
+		// http://community.silabs.com/t5/8-bit-MCU/Remote-wakeup-HID/m-p/74957#M30802
+		case 0x1:
+			goto send;
+		}
+
+		warn_msg("SET_FEATURE - Device wValue(");
+		printHex( setup.wValue );
+		print( ")" NL );
+		endpoint0_stall();
+		return;
+
 	case 0x0301: // SET_FEATURE (interface)
 		// TODO: Currently ignoring, perhaps useful? -HaaTa
-		warn_print("SET_FEATURE - Device/Interface");
+		warn_msg("SET_FEATURE - Interface wValue(");
+		printHex( setup.wValue );
+		print(") wIndex(");
+		printHex( setup.wIndex );
+		print( ")" NL );
 		endpoint0_stall();
 		return;
 
@@ -385,6 +466,27 @@
 				{
 					datalen = list->length;
 				}
+
+				// XXX Power negotiation hack -HaaTa
+				// Some devices such as the Apple Ipad do not support bMaxPower greater than 100 mA
+				// However, there is no provision in the basic USB 2.0 stack for power negotiation
+				// To get around this:
+				//  * Attempt to set bMaxPower to 500 mA first
+				//  * If more than 100 ms passes since retrieving a Get Configuration Descriptor
+				//    (Descriptor with bMaxPower in it)
+				//  * Change usb_bMaxPower to 50 (100 mA)
+				//  * Restart the USB init process
+				// According to notes online, it says that some Apple devices can only do 20 mA
+				// However, in my testing this hasn't been the case
+				// (you can also draw as much current as you want if you just lie in the descriptor :P)
+				// If this becomes an issue we can use this hack a second time to negotiate down to 20 mA
+				// (which should be fine for just the mcu)
+				if ( setup.wValue == 0x0200 && setup.wIndex == 0x0 )
+				{
+					power_neg_delay = 1;
+					power_neg_time = systick_millis_count;
+				}
+
 				#if UART_DEBUG
 				print("Desc found, ");
 				printHex32( (uint32_t)data );
@@ -862,6 +964,11 @@
 
 void usb_tx( uint32_t endpoint, usb_packet_t *packet )
 {
+	// Since we are transmitting data, USB will be brought out of sleep/suspend
+	// if it's in that state
+	// Use the currently set descriptor value
+	Output_update_usb_current( *usb_bMaxPower * 2 );
+
 	bdt_t *b = &table[ index( endpoint, TX, EVEN ) ];
 	uint8_t next;
 
@@ -1161,9 +1268,12 @@
 		USB0_ISTAT = USB_ISTAT_ERROR;
 	}
 
+	// USB Host signalling device to enter 'sleep' state
+	// The USB Module triggers this interrupt when it detects the bus has been idle for 3 ms
 	if ( (status & USB_ISTAT_SLEEP /* 10 */ ) )
 	{
-		//serial_print("sleep\n");
+		info_print("Host has requested USB sleep/suspend state");
+		Output_update_usb_current( 100 ); // Set to 100 mA
 		USB0_ISTAT = USB_ISTAT_SLEEP;
 	}
 }
@@ -1220,6 +1330,9 @@
 	// enable d+ pullup
 	USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
 
+	// Do not check for power negotiation delay until Get Configuration Descriptor
+	power_neg_delay = 0;
+
 	return 1;
 }
 
--- a/Output/pjrcUSB/arm/usb_dev.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/arm/usb_dev.h	Tue Mar 01 19:40:00 2016 +0100
@@ -81,6 +81,7 @@
 }
 
 void usb_device_reload();
+void usb_device_check();
 
 extern void usb_serial_flush_callback();
 
--- a/Output/pjrcUSB/output_com.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/output_com.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2015 by Jacob Alexander
+/* Copyright (C) 2011-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -137,6 +137,14 @@
 // 1 - Debug enabled
 uint8_t  Output_DebugMode = 0;
 
+// mA - Set by outside module if not using USB (i.e. Interconnect)
+// Generally set to 100 mA (low power) or 500 mA (high power)
+uint16_t Output_ExtCurrent_Available = 0;
+
+// mA - Set by USB module (if exists)
+// Initially 100 mA, but may be negotiated higher (e.g. 500 mA)
+uint16_t Output_USBCurrent_Available = 0;
+
 
 
 // ----- Capabilities -----
@@ -535,6 +543,10 @@
 // USB Data Send
 inline void Output_send()
 {
+	// USB status checks
+	// Non-standard USB state manipulation, usually does nothing
+	usb_device_check();
+
 	// Boot Mode Only, unset stale keys
 	if ( USBKeys_Protocol == 0 )
 		for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ )
@@ -614,6 +626,72 @@
 }
 
 
+// Update USB current (mA)
+// Triggers power change event
+void Output_update_usb_current( unsigned int current )
+{
+	// Only signal if changed
+	if ( current == Output_USBCurrent_Available )
+		return;
+
+	// Update USB current
+	Output_USBCurrent_Available = current;
+
+	unsigned int total_current = Output_current_available();
+	info_msg("USB Available Current Changed. Total Available: ");
+	printInt32( total_current );
+	print(" mA" NL);
+
+	// Send new total current to the Scan Modules
+	Scan_currentChange( Output_current_available() );
+}
+
+
+// Update external current (mA)
+// Triggers power change event
+void Output_update_external_current( unsigned int current )
+{
+	// Only signal if changed
+	if ( current == Output_ExtCurrent_Available )
+		return;
+
+	// Update external current
+	Output_ExtCurrent_Available = current;
+
+	unsigned int total_current = Output_current_available();
+	info_msg("External Available Current Changed. Total Available: ");
+	printInt32( total_current );
+	print(" mA" NL);
+
+	// Send new total current to the Scan Modules
+	Scan_currentChange( Output_current_available() );
+}
+
+
+// Power/Current Available
+unsigned int Output_current_available()
+{
+	unsigned int total_current = 0;
+
+	// Check for USB current source
+	total_current += Output_USBCurrent_Available;
+
+	// Check for external current source
+	total_current += Output_ExtCurrent_Available;
+
+	// XXX If the total available current is still 0
+	// Set to 100 mA, which is generally a safe assumption at startup
+	// before we've been able to determine actual available current
+	if ( total_current == 0 )
+	{
+		total_current = 100;
+	}
+
+	return total_current;
+}
+
+
+
 // ----- CLI Command Functions -----
 
 void cliFunc_kbdProtocol( char* args )
--- a/Output/pjrcUSB/output_com.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/pjrcUSB/output_com.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2015 by Jacob Alexander
+/* Copyright (C) 2013-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -82,6 +82,8 @@
 
 extern          uint8_t  Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled
 
+extern          uint16_t Output_ExtCurrent_Available; // mA - Set by outside module if not using USB (i.e. Interconnect)
+
 
 
 // ----- Functions -----
@@ -97,6 +99,12 @@
 // Relies on USB serial module
 unsigned int Output_availablechar();
 
+// Returns the total mA available (total, if used in a chain, each device will have to use a slice of it)
+unsigned int Output_current_available();
+
+void Output_update_external_current( unsigned int current );
+void Output_update_usb_current( unsigned int current );
+
 int Output_getchar();
 int Output_putchar( char c );
 int Output_putstr( char* str );
--- a/Output/usbMuxUart/output_com.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Output/usbMuxUart/output_com.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -143,6 +143,14 @@
 // 1 - Debug enabled
 uint8_t  Output_DebugMode = 0;
 
+// mA - Set by outside module if not using USB (i.e. Interconnect)
+// Generally set to 100 mA (low power) or 500 mA (high power)
+uint16_t Output_ExtCurrent_Available = 0;
+
+// mA - Set by USB module (if exists)
+// Initially 100 mA, but may be negotiated higher (e.g. 500 mA)
+uint16_t Output_USBCurrent_Available = 0;
+
 
 
 // ----- Capabilities -----
@@ -544,6 +552,10 @@
 // USB Data Send
 inline void Output_send()
 {
+	// USB status checks
+	// Non-standard USB state manipulation, usually does nothing
+	usb_device_check();
+
 	// Boot Mode Only, unset stale keys
 	if ( USBKeys_Protocol == 0 )
 		for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ )
@@ -641,6 +653,72 @@
 }
 
 
+// Update USB current (mA)
+// Triggers power change event
+void Output_update_usb_current( unsigned int current )
+{
+	// Only signal if changed
+	if ( current == Output_USBCurrent_Available )
+		return;
+
+	// Update USB current
+	Output_USBCurrent_Available = current;
+
+	unsigned int total_current = Output_current_available();
+	info_msg("USB Available Current Changed. Total Available: ");
+	printInt32( total_current );
+	print(" mA" NL);
+
+	// Send new total current to the Scan Modules
+	Scan_currentChange( Output_current_available() );
+}
+
+
+// Update external current (mA)
+// Triggers power change event
+void Output_update_external_current( unsigned int current )
+{
+	// Only signal if changed
+	if ( current == Output_ExtCurrent_Available )
+		return;
+
+	// Update external current
+	Output_ExtCurrent_Available = current;
+
+	unsigned int total_current = Output_current_available();
+	info_msg("External Available Current Changed. Total Available: ");
+	printInt32( total_current );
+	print(" mA" NL);
+
+	// Send new total current to the Scan Modules
+	Scan_currentChange( Output_current_available() );
+}
+
+
+// Power/Current Available
+unsigned int Output_current_available()
+{
+	unsigned int total_current = 0;
+
+	// Check for USB current source
+	total_current += Output_USBCurrent_Available;
+
+	// Check for external current source
+	total_current += Output_ExtCurrent_Available;
+
+	// XXX If the total available current is still 0
+	// Set to 100 mA, which is generally a safe assumption at startup
+	// before we've been able to determine actual available current
+	if ( total_current == 0 )
+	{
+		total_current = 100;
+	}
+
+	return total_current;
+}
+
+
+
 // ----- CLI Command Functions -----
 
 void cliFunc_kbdProtocol( char* args )
--- a/Scan/ISSILed/led_scan.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/ISSILed/led_scan.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -406,8 +406,14 @@
 	// Set default brightness
 	LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 );
 
-	// Disable Software shutdown of ISSI chip
-	LED_writeReg( 0x0A, 0x01, 0x0B );
+	// Do not disable software shutdown of ISSI chip unless current is high enough
+	// Require at least 150 mA
+	// May be enabled/disabled at a later time
+	if ( Output_current_available() >= 150 )
+	{
+		// Disable Software shutdown of ISSI chip
+		LED_writeReg( 0x0A, 0x01, 0x0B );
+	}
 }
 
 
@@ -644,6 +650,24 @@
 }
 
 
+// Called by parent Scan Module whenver the available current has changed
+// current - mA
+void LED_currentChange( unsigned int current )
+{
+	// TODO dim LEDs in low power mode instead of shutting off
+	if ( current < 150 )
+	{
+		// Enabled Software shutdown of ISSI chip
+		LED_writeReg( 0x0A, 0x00, 0x0B );
+	}
+	else
+	{
+		// Disable Software shutdown of ISSI chip
+		LED_writeReg( 0x0A, 0x01, 0x0B );
+	}
+}
+
+
 
 // ----- Capabilities -----
 
--- a/Scan/ISSILed/led_scan.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/ISSILed/led_scan.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,3 +28,5 @@
 void LED_setup();
 uint8_t LED_scan();
 
+void LED_currentChange( unsigned int current );
+
--- a/Scan/KType/scan_loop.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/KType/scan_loop.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -97,3 +97,14 @@
 	Scan_scanCount = 0;
 }
 
+
+// Signal from the Output Module that the available current has changed
+// current - mA
+void Scan_currentChange( unsigned int current )
+{
+	// Indicate to all submodules current change
+	Connect_currentChange( current );
+	Matrix_currentChange( current );
+	LED_currentChange( current );
+}
+
--- a/Scan/KType/scan_loop.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/KType/scan_loop.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -31,10 +31,12 @@
 // ----- Functions -----
 
 // Functions to be called by main.c
-void Scan_setup( void );
-uint8_t Scan_loop( void );
+void Scan_setup();
+uint8_t Scan_loop();
 
 // Call-backs
 void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
 void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
 
+void Scan_currentChange( unsigned int current ); // Called by Output Module
+
--- a/Scan/MD1.1/scan_loop.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MD1.1/scan_loop.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014,2016 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -90,6 +90,16 @@
 }
 
 
+// Signal from the Output Module that the available current has changed
+// current - mA
+void Scan_currentChange( unsigned int current )
+{
+	// Indicate to all submodules current change
+	Matrix_currentChange( current );
+	LED_currentChange( current );
+}
+
+
 
 // ----- Capabilities -----
 
--- a/Scan/MD1.1/scan_loop.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MD1.1/scan_loop.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -38,6 +38,8 @@
 void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
 void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
 
+void Scan_currentChange( unsigned int current ); // Called by Output Module
+
 
 // ----- Capabilities -----
 
--- a/Scan/MD1/scan_loop.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MD1/scan_loop.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -175,6 +175,15 @@
 }
 
 
+// Signal from the Output Module that the available current has changed
+// current - mA
+void Scan_currentChange( unsigned int current )
+{
+	// Indicate to all submodules current change
+	Matrix_currentChange( current );
+}
+
+
 
 // ----- CLI Command Functions -----
 
--- a/Scan/MD1/scan_loop.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MD1/scan_loop.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -38,6 +38,8 @@
 void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
 void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
 
+void Scan_currentChange( unsigned int current ); // Called by Output Module
+
 
 // ----- Capabilities -----
 
--- a/Scan/MDErgo1/scan_loop.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MDErgo1/scan_loop.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -102,3 +102,15 @@
 	Scan_scanCount = 0;
 }
 
+
+// Signal from the Output Module that the available current has changed
+// current - mA
+void Scan_currentChange( unsigned int current )
+{
+	// Indicate to all submodules current change
+	Connect_currentChange( current );
+	Matrix_currentChange( current );
+	LED_currentChange( current );
+	LCD_currentChange( current );
+}
+
--- a/Scan/MDErgo1/scan_loop.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MDErgo1/scan_loop.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -31,10 +31,12 @@
 // ----- Functions -----
 
 // Functions to be called by main.c
-void Scan_setup( void );
-uint8_t Scan_loop( void );
+void Scan_setup();
+uint8_t Scan_loop();
 
 // Call-backs
 void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
 void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
 
+void Scan_currentChange( unsigned int current ); // Called by Output Module
+
--- a/Scan/MatrixARM/matrix_scan.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MatrixARM/matrix_scan.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -452,7 +452,7 @@
 
 
 	// Matrix ghosting check and elimination
-	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
+	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 #ifdef GHOSTING_MATRIX
 	// strobe = column, sense = row
 
@@ -489,7 +489,7 @@
 		row_use[row] = used;
 		row_ghost[row] = 0;  // clear
 	}
-	
+
 	// Check if matrix has ghost
 	// Happens when key is pressed and some other key is pressed in same row and another in same column
 	//print("  G ");
@@ -518,10 +518,10 @@
 			uint8_t key = Matrix_colsNum * row + col;
 			KeyState *state = &Matrix_scanArray[ key ];
 			KeyGhost *st = &Matrix_ghostArray[ key ];
-			
+
 			// col or row is ghosting (crossed)
 			uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0;
-			
+
 			st->prev = st->cur;  // previous
 			// save state if no ghost or outside ghosted area
 			if ( ghost == 0 )
@@ -529,16 +529,16 @@
 			// final
 			// use saved state if ghosting, or current if not
 			st->cur = ghost > 0 ? st->saved : state->curState;
-			
+
 			//  Send keystate to macro module
-			KeyPosition k = !st->cur 
+			KeyPosition k = !st->cur
 				? (!st->prev ? KeyState_Off : KeyState_Release)
 				: ( st->prev ? KeyState_Hold : KeyState_Press);
 			Macro_keyState( key, k );
 		}
 	}
 #endif
-	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
+	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 
 
 	// State Table Output Debug
@@ -587,6 +587,15 @@
 }
 
 
+// Called by parent scan module whenever the available current changes
+// current - mA
+void Matrix_currentChange( unsigned int current )
+{
+	// TODO - Any potential power savings?
+}
+
+
+
 // ----- CLI Command Functions -----
 
 void cliFunc_matrixDebug ( char* args )
--- a/Scan/MatrixARM/matrix_scan.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/MatrixARM/matrix_scan.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -158,3 +158,5 @@
 void Matrix_setup();
 void Matrix_scan( uint16_t scanNum );
 
+void Matrix_currentChange( unsigned int current );
+
--- a/Scan/STLcd/lcd_scan.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/STLcd/lcd_scan.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015 by Jacob Alexander
+/* Copyright (C) 2015-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -346,6 +346,14 @@
 }
 
 
+// Signal from parent Scan Module that available current has changed
+// current - mA
+void LCD_currentChange( unsigned int current )
+{
+	// TODO - Power savings?
+}
+
+
 
 // ----- Capabilities -----
 
--- a/Scan/STLcd/lcd_scan.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/STLcd/lcd_scan.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015 by Jacob Alexander
+/* Copyright (C) 2015-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,3 +28,5 @@
 void LCD_setup();
 uint8_t LCD_scan();
 
+void LCD_currentChange( unsigned int current );
+
--- a/Scan/UARTConnect/connect_scan.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/UARTConnect/connect_scan.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -470,6 +470,14 @@
 			}
 			else
 			{
+				// Lower current requirement during errors
+				// USB minimum
+				// Only if this is not the master node
+				if ( Connect_id != 0 )
+				{
+					Output_update_external_current( 100 );
+				}
+
 				Connect_cableFaultsMaster++;
 				Connect_cableOkMaster = 0;
 				print(" Master ");
@@ -489,6 +497,12 @@
 			}
 			else
 			{
+				// If we already have an Id, then set max current again
+				if ( Connect_id != 255 && Connect_id != 0 )
+				{
+					// TODO reset to original negotiated current
+					Output_update_external_current( 500 );
+				}
 				Connect_cableChecksMaster++;
 			}
 		}
@@ -560,6 +574,14 @@
 	// Send reponse back to master
 	Connect_send_IdReport( id );
 
+	// Node now enumerated, set external power to USB Max
+	// Only set if this is not the master node
+	// TODO Determine power slice for each node as part of protocol
+	if ( Connect_id != 0 )
+	{
+		Output_update_external_current( 500 );
+	}
+
 	// Propogate next Id if the connection is ok
 	if ( Connect_cableOkSlave )
 	{
@@ -1139,6 +1161,7 @@
 	}
 
 	// Limit how often we do cable checks
+	//uint32_t time_compare = 0x007; // Used for debugging cables -HaaTa
 	uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not
 	uint32_t current_time = systick_millis_count;
 	if ( Connect_lastCheck != current_time
@@ -1176,6 +1199,13 @@
 }
 
 
+// Called by parent Scan module whenever the available current changes
+void Connect_currentChange( unsigned int current )
+{
+	// TODO - Any potential power saving here?
+}
+
+
 
 // ----- CLI Command Functions -----
 
--- a/Scan/UARTConnect/connect_scan.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/UARTConnect/connect_scan.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -167,3 +167,5 @@
 void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes );
 void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args );
 
+void Connect_currentChange( unsigned int current );
+
--- a/Scan/WhiteFox/scan_loop.c	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/WhiteFox/scan_loop.c	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -90,3 +90,13 @@
 	Scan_scanCount = 0;
 }
 
+
+// Signal from the Output Module that the available current has changed
+// current - mA
+void Scan_currentChange( unsigned int current )
+{
+	// Indicate to all submodules current change
+	Matrix_currentChange( current );
+	LED_currentChange( current );
+}
+
--- a/Scan/WhiteFox/scan_loop.h	Tue Mar 01 19:38:43 2016 +0100
+++ b/Scan/WhiteFox/scan_loop.h	Tue Mar 01 19:40:00 2016 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014-2015 by Jacob Alexander
+/* Copyright (C) 2014-2016 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -38,3 +38,5 @@
 void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
 void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
 
+void Scan_currentChange( unsigned int current ); // Called by Output Module
+