From 46765e85c57e19b89754f4f9c26c8f18b35148e5 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sun, 21 Feb 2016 19:56:52 -0800 Subject: [PATCH] Adding dynamic USB power support - Each scan module now has a current change callback which passes the available current as a parameter - No longer attempts to use the max 500 mA immediately, starts with 100 mA then goes to 500 mA after enumeration - If enumeration fails due to bMaxPower of 500 mA, then attempt again at 100 mA (might also be possible to go even lower to 20 mA in certain cases) - Now working with the Apple Ipad (no over-power messages) - Fixed Wake-up behaviour on Apple Ipad (and likely other iOS devices) - More effecient set_feature/clear_feature handling (device handler) - Initial power handling via Interconnect (still needs work to get it more dynamic) --- Output/pjrcUSB/arm/usb_desc.c | 6 +- Output/pjrcUSB/arm/usb_desc.h | 4 +- Output/pjrcUSB/arm/usb_dev.c | 121 ++++++++++++++++++++++++++++++-- Output/pjrcUSB/arm/usb_dev.h | 1 + Output/pjrcUSB/output_com.c | 80 ++++++++++++++++++++- Output/pjrcUSB/output_com.h | 10 ++- Output/usbMuxUart/output_com.c | 80 ++++++++++++++++++++- Scan/ISSILed/led_scan.c | 30 +++++++- Scan/ISSILed/led_scan.h | 4 +- Scan/KType/scan_loop.c | 13 +++- Scan/KType/scan_loop.h | 8 ++- Scan/MD1.1/scan_loop.c | 12 +++- Scan/MD1.1/scan_loop.h | 4 +- Scan/MD1/scan_loop.c | 11 ++- Scan/MD1/scan_loop.h | 4 +- Scan/MDErgo1/scan_loop.c | 14 +++- Scan/MDErgo1/scan_loop.h | 8 ++- Scan/MatrixARM/matrix_scan.c | 25 ++++--- Scan/MatrixARM/matrix_scan.h | 4 +- Scan/STLcd/lcd_scan.c | 10 ++- Scan/STLcd/lcd_scan.h | 4 +- Scan/UARTConnect/connect_scan.c | 31 +++++++- Scan/UARTConnect/connect_scan.h | 4 +- Scan/WhiteFox/scan_loop.c | 12 +++- Scan/WhiteFox/scan_loop.h | 4 +- 25 files changed, 463 insertions(+), 41 deletions(-) diff --git a/Output/pjrcUSB/arm/usb_desc.c b/Output/pjrcUSB/arm/usb_desc.c index b7cb735..1d9a939 100644 --- a/Output/pjrcUSB/arm/usb_desc.c +++ b/Output/pjrcUSB/arm/usb_desc.c @@ -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 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { 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 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { SYS_CTRL_INTERVAL, // bInterval }; +uint8_t *usb_bMaxPower = &config_descriptor[8]; + // ----- String Descriptors ----- diff --git a/Output/pjrcUSB/arm/usb_desc.h b/Output/pjrcUSB/arm/usb_desc.h index 33c6589..0e769a1 100644 --- a/Output/pjrcUSB/arm/usb_desc.h +++ b/Output/pjrcUSB/arm/usb_desc.h @@ -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 uint8_t usb_endpoint_config_table[NUM_ENDPOINTS]; extern const usb_descriptor_list_t usb_descriptor_list[]; +extern uint8_t *usb_bMaxPower; + diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index 782f3ac..c0e4566 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -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 @@ volatile uint8_t usb_reboot_timer = 0; static uint8_t reply_buffer[8]; +static uint8_t power_neg_delay; +static uint32_t power_neg_time; + // ----- Functions ----- @@ -188,6 +191,34 @@ static void endpoint0_transmit( const void *data, uint32_t len ) 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 @@ static void usb_setup() 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 @@ static void usb_setup() 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 @@ static void usb_setup() 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 @@ static void usb_setup() 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 @@ static void usb_setup() { 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_rx_memory( usb_packet_t *packet ) 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 @@ restart: 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 @@ uint8_t usb_init() // 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; } diff --git a/Output/pjrcUSB/arm/usb_dev.h b/Output/pjrcUSB/arm/usb_dev.h index 0f445de..827f843 100644 --- a/Output/pjrcUSB/arm/usb_dev.h +++ b/Output/pjrcUSB/arm/usb_dev.h @@ -81,6 +81,7 @@ static inline uint32_t usb_rx_byte_count(uint32_t endpoint) } void usb_device_reload(); +void usb_device_check(); extern void usb_serial_flush_callback(); diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index 2e97e42..b18bbdb 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -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 @@ volatile uint8_t Output_Available = 0; // 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 @@ inline void Output_setup() // 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 @@ inline void Output_softReset() } +// 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 ) diff --git a/Output/pjrcUSB/output_com.h b/Output/pjrcUSB/output_com.h index c82ed98..2448683 100644 --- a/Output/pjrcUSB/output_com.h +++ b/Output/pjrcUSB/output_com.h @@ -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 volatile uint8_t Output_Available; // 0 - Output module not fully functi 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 @@ void Output_softReset(); // 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 ); diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 44c5b49..55c9553 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -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 @@ volatile uint8_t Output_Available = 0; // 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 @@ inline void Output_setup() // 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 @@ inline void Output_softReset() } +// 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 ) diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index 8a92b76..609f2d7 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -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 @@ inline void LED_setup() // 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 @@ inline uint8_t LED_scan() } +// 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 ----- diff --git a/Scan/ISSILed/led_scan.h b/Scan/ISSILed/led_scan.h index 71d8e80..545b8b9 100644 --- a/Scan/ISSILed/led_scan.h +++ b/Scan/ISSILed/led_scan.h @@ -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 ); + diff --git a/Scan/KType/scan_loop.c b/Scan/KType/scan_loop.c index 7999853..4e52706 100644 --- a/Scan/KType/scan_loop.c +++ b/Scan/KType/scan_loop.c @@ -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 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) 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 ); +} + diff --git a/Scan/KType/scan_loop.h b/Scan/KType/scan_loop.h index 17a06fc..b18a0ca 100644 --- a/Scan/KType/scan_loop.h +++ b/Scan/KType/scan_loop.h @@ -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 + diff --git a/Scan/MD1.1/scan_loop.c b/Scan/MD1.1/scan_loop.c index 74218a0..3b2bad1 100644 --- a/Scan/MD1.1/scan_loop.c +++ b/Scan/MD1.1/scan_loop.c @@ -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 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) } +// 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 ----- diff --git a/Scan/MD1.1/scan_loop.h b/Scan/MD1.1/scan_loop.h index 0c89838..339ede5 100644 --- a/Scan/MD1.1/scan_loop.h +++ b/Scan/MD1.1/scan_loop.h @@ -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 @@ uint8_t Scan_loop( void ); 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 ----- diff --git a/Scan/MD1/scan_loop.c b/Scan/MD1/scan_loop.c index 22d43c2..d9348e1 100644 --- a/Scan/MD1/scan_loop.c +++ b/Scan/MD1/scan_loop.c @@ -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 @@ void CustomAction_blockKey_capability( uint8_t state, uint8_t stateType, uint8_t } +// 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 ----- diff --git a/Scan/MD1/scan_loop.h b/Scan/MD1/scan_loop.h index 0c89838..339ede5 100644 --- a/Scan/MD1/scan_loop.h +++ b/Scan/MD1/scan_loop.h @@ -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 @@ uint8_t Scan_loop( void ); 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 ----- diff --git a/Scan/MDErgo1/scan_loop.c b/Scan/MDErgo1/scan_loop.c index d5e97e5..e80119b 100644 --- a/Scan/MDErgo1/scan_loop.c +++ b/Scan/MDErgo1/scan_loop.c @@ -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 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) 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 ); +} + diff --git a/Scan/MDErgo1/scan_loop.h b/Scan/MDErgo1/scan_loop.h index 17a06fc..b18a0ca 100644 --- a/Scan/MDErgo1/scan_loop.h +++ b/Scan/MDErgo1/scan_loop.h @@ -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 + diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 90343fe..017161d 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -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 @@ -428,7 +428,7 @@ void Matrix_scan( uint16_t scanNum ) // Matrix ghosting check and elimination - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #ifdef GHOSTING_MATRIX // strobe = column, sense = row @@ -465,7 +465,7 @@ void Matrix_scan( uint16_t scanNum ) 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 "); @@ -494,10 +494,10 @@ void Matrix_scan( uint16_t scanNum ) 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 ) @@ -505,9 +505,9 @@ void Matrix_scan( uint16_t scanNum ) // 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); //if (!st->cur && !st->prev) k = KeyState_Off; else @@ -518,7 +518,7 @@ void Matrix_scan( uint16_t scanNum ) } } #endif - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // State Table Output Debug @@ -567,6 +567,15 @@ void Matrix_scan( uint16_t scanNum ) } +// 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 ) diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h index 8b9cee7..3a8f0e2 100644 --- a/Scan/MatrixARM/matrix_scan.h +++ b/Scan/MatrixARM/matrix_scan.h @@ -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 @@ inline uint8_t keyOn(/*KeyPosition*/uint8_t st) void Matrix_setup(); void Matrix_scan( uint16_t scanNum ); +void Matrix_currentChange( unsigned int current ); + diff --git a/Scan/STLcd/lcd_scan.c b/Scan/STLcd/lcd_scan.c index c4bf080..1dd9126 100644 --- a/Scan/STLcd/lcd_scan.c +++ b/Scan/STLcd/lcd_scan.c @@ -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 @@ inline uint8_t LCD_scan() } +// Signal from parent Scan Module that available current has changed +// current - mA +void LCD_currentChange( unsigned int current ) +{ + // TODO - Power savings? +} + + // ----- Capabilities ----- diff --git a/Scan/STLcd/lcd_scan.h b/Scan/STLcd/lcd_scan.h index 36884a2..096107b 100644 --- a/Scan/STLcd/lcd_scan.h +++ b/Scan/STLcd/lcd_scan.h @@ -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 ); + diff --git a/Scan/UARTConnect/connect_scan.c b/Scan/UARTConnect/connect_scan.c index 55f6619..4c56c3c 100644 --- a/Scan/UARTConnect/connect_scan.c +++ b/Scan/UARTConnect/connect_scan.c @@ -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 @@ uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8 } 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 @@ uint8_t Connect_receive_CableCheck( uint8_t byte, uint16_t *pending_bytes, uint8 } 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 @@ uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint // 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 ) { @@ -1177,6 +1199,13 @@ void Connect_scan() } +// 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 ----- diff --git a/Scan/UARTConnect/connect_scan.h b/Scan/UARTConnect/connect_scan.h index cdd7ed0..1d87dfd 100644 --- a/Scan/UARTConnect/connect_scan.h +++ b/Scan/UARTConnect/connect_scan.h @@ -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_scan(); 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 ); + diff --git a/Scan/WhiteFox/scan_loop.c b/Scan/WhiteFox/scan_loop.c index 16cefa2..56fa995 100644 --- a/Scan/WhiteFox/scan_loop.c +++ b/Scan/WhiteFox/scan_loop.c @@ -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 @@ inline void Scan_finishedWithOutput( uint8_t sentKeys ) 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 ); +} + diff --git a/Scan/WhiteFox/scan_loop.h b/Scan/WhiteFox/scan_loop.h index 17a06fc..9e9a8f1 100644 --- a/Scan/WhiteFox/scan_loop.h +++ b/Scan/WhiteFox/scan_loop.h @@ -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 @@ uint8_t Scan_loop( void ); 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 + -- 2.39.2