- 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)capsense
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * 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 | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
1, // bConfigurationValue | 1, // bConfigurationValue | ||||
0, // iConfiguration | 0, // iConfiguration | ||||
0xA0, // bmAttributes | 0xA0, // bmAttributes | ||||
250, // bMaxPower | |||||
250, // bMaxPower - Entry Index 8 | |||||
// --- Keyboard HID --- Boot Mode Keyboard Interface | // --- Keyboard HID --- Boot Mode Keyboard Interface | ||||
// - 9 bytes - | // - 9 bytes - | ||||
SYS_CTRL_INTERVAL, // bInterval | SYS_CTRL_INTERVAL, // bInterval | ||||
}; | }; | ||||
uint8_t *usb_bMaxPower = &config_descriptor[8]; | |||||
// ----- String Descriptors ----- | // ----- String Descriptors ----- |
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * 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 | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
extern const usb_descriptor_list_t usb_descriptor_list[]; | extern const usb_descriptor_list_t usb_descriptor_list[]; | ||||
extern uint8_t *usb_bMaxPower; | |||||
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * 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 | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
static uint8_t reply_buffer[8]; | static uint8_t reply_buffer[8]; | ||||
static uint8_t power_neg_delay; | |||||
static uint32_t power_neg_time; | |||||
// ----- Functions ----- | // ----- Functions ----- | ||||
ep0_tx_bdt_bank ^= 1; | 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() | static void usb_setup() | ||||
{ | { | ||||
const uint8_t *data = NULL; | const uint8_t *data = NULL; | ||||
const uint8_t *cfg; | const uint8_t *cfg; | ||||
int i; | 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 ) | switch ( setup.wRequestAndType ) | ||||
{ | { | ||||
case 0x0500: // SET_ADDRESS | case 0x0500: // SET_ADDRESS | ||||
Output_Available = usb_configuration; | Output_Available = usb_configuration; | ||||
reg = &USB0_ENDPT1; | reg = &USB0_ENDPT1; | ||||
cfg = usb_endpoint_config_table; | 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... | // clear all BDT entries, free any allocated memory... | ||||
for ( i = 4; i < ( NUM_ENDPOINTS + 1) * 4; i++ ) | for ( i = 4; i < ( NUM_ENDPOINTS + 1) * 4; i++ ) | ||||
{ | { | ||||
goto send; | goto send; | ||||
case 0x0100: // CLEAR_FEATURE (device) | 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) | case 0x0101: // CLEAR_FEATURE (interface) | ||||
// TODO: Currently ignoring, perhaps useful? -HaaTa | // 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(); | endpoint0_stall(); | ||||
return; | return; | ||||
goto send; | goto send; | ||||
case 0x0300: // SET_FEATURE (device) | 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) | case 0x0301: // SET_FEATURE (interface) | ||||
// TODO: Currently ignoring, perhaps useful? -HaaTa | // 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(); | endpoint0_stall(); | ||||
return; | return; | ||||
{ | { | ||||
datalen = list->length; | 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 | #if UART_DEBUG | ||||
print("Desc found, "); | print("Desc found, "); | ||||
printHex32( (uint32_t)data ); | printHex32( (uint32_t)data ); | ||||
void usb_tx( uint32_t endpoint, 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 ) ]; | bdt_t *b = &table[ index( endpoint, TX, EVEN ) ]; | ||||
uint8_t next; | uint8_t next; | ||||
USB0_ISTAT = USB_ISTAT_ERROR; | 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 */ ) ) | 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; | USB0_ISTAT = USB_ISTAT_SLEEP; | ||||
} | } | ||||
} | } | ||||
// enable d+ pullup | // enable d+ pullup | ||||
USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | ||||
// Do not check for power negotiation delay until Get Configuration Descriptor | |||||
power_neg_delay = 0; | |||||
return 1; | return 1; | ||||
} | } | ||||
} | } | ||||
void usb_device_reload(); | void usb_device_reload(); | ||||
void usb_device_check(); | |||||
extern void usb_serial_flush_callback(); | extern void usb_serial_flush_callback(); | ||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// 1 - Debug enabled | // 1 - Debug enabled | ||||
uint8_t Output_DebugMode = 0; | 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 ----- | // ----- Capabilities ----- | ||||
// USB Data Send | // USB Data Send | ||||
inline void Output_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 | // Boot Mode Only, unset stale keys | ||||
if ( USBKeys_Protocol == 0 ) | if ( USBKeys_Protocol == 0 ) | ||||
for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | ||||
} | } | ||||
// 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 ----- | // ----- CLI Command Functions ----- | ||||
void cliFunc_kbdProtocol( char* args ) | void cliFunc_kbdProtocol( char* args ) |
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
extern uint8_t Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled | 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 ----- | // ----- Functions ----- | ||||
// Relies on USB serial module | // Relies on USB serial module | ||||
unsigned int Output_availablechar(); | 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_getchar(); | ||||
int Output_putchar( char c ); | int Output_putchar( char c ); | ||||
int Output_putstr( char* str ); | int Output_putstr( char* str ); |
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// 1 - Debug enabled | // 1 - Debug enabled | ||||
uint8_t Output_DebugMode = 0; | 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 ----- | // ----- Capabilities ----- | ||||
// USB Data Send | // USB Data Send | ||||
inline void Output_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 | // Boot Mode Only, unset stale keys | ||||
if ( USBKeys_Protocol == 0 ) | if ( USBKeys_Protocol == 0 ) | ||||
for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | ||||
} | } | ||||
// 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 ----- | // ----- CLI Command Functions ----- | ||||
void cliFunc_kbdProtocol( char* args ) | void cliFunc_kbdProtocol( char* args ) |
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
// Set default brightness | // Set default brightness | ||||
LED_sendPage( (uint8_t*)LED_defaultBrightness1, sizeof( LED_defaultBrightness1 ), 0 ); | 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 ); | |||||
} | |||||
} | } | ||||
} | } | ||||
// 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 ----- | // ----- Capabilities ----- | ||||
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
void LED_setup(); | void LED_setup(); | ||||
uint8_t LED_scan(); | uint8_t LED_scan(); | ||||
void LED_currentChange( unsigned int current ); | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
Scan_scanCount = 0; | 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 ); | |||||
} | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// ----- Functions ----- | // ----- Functions ----- | ||||
// Functions to be called by main.c | // 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 | // Call-backs | ||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | ||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | ||||
void Scan_currentChange( unsigned int current ); // Called by Output Module | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
} | } | ||||
// 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 ----- | // ----- Capabilities ----- | ||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | ||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | ||||
void Scan_currentChange( unsigned int current ); // Called by Output Module | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- | ||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
} | } | ||||
// 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 ----- | // ----- CLI Command Functions ----- | ||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | ||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | ||||
void Scan_currentChange( unsigned int current ); // Called by Output Module | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- | ||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
Scan_scanCount = 0; | 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 ); | |||||
} | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// ----- Functions ----- | // ----- Functions ----- | ||||
// Functions to be called by main.c | // 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 | // Call-backs | ||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | ||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | ||||
void Scan_currentChange( unsigned int current ); // Called by Output Module | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// Matrix ghosting check and elimination | // Matrix ghosting check and elimination | ||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |||||
#ifdef GHOSTING_MATRIX | #ifdef GHOSTING_MATRIX | ||||
// strobe = column, sense = row | // strobe = column, sense = row | ||||
row_use[row] = used; | row_use[row] = used; | ||||
row_ghost[row] = 0; // clear | row_ghost[row] = 0; // clear | ||||
} | } | ||||
// Check if matrix has ghost | // Check if matrix has ghost | ||||
// Happens when key is pressed and some other key is pressed in same row and another in same column | // Happens when key is pressed and some other key is pressed in same row and another in same column | ||||
//print(" G "); | //print(" G "); | ||||
uint8_t key = Matrix_colsNum * row + col; | uint8_t key = Matrix_colsNum * row + col; | ||||
KeyState *state = &Matrix_scanArray[ key ]; | KeyState *state = &Matrix_scanArray[ key ]; | ||||
KeyGhost *st = &Matrix_ghostArray[ key ]; | KeyGhost *st = &Matrix_ghostArray[ key ]; | ||||
// col or row is ghosting (crossed) | // col or row is ghosting (crossed) | ||||
uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0; | uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0; | ||||
st->prev = st->cur; // previous | st->prev = st->cur; // previous | ||||
// save state if no ghost or outside ghosted area | // save state if no ghost or outside ghosted area | ||||
if ( ghost == 0 ) | if ( ghost == 0 ) | ||||
// final | // final | ||||
// use saved state if ghosting, or current if not | // use saved state if ghosting, or current if not | ||||
st->cur = ghost > 0 ? st->saved : state->curState; | st->cur = ghost > 0 ? st->saved : state->curState; | ||||
// Send keystate to macro module | // Send keystate to macro module | ||||
KeyPosition k = !st->cur | |||||
KeyPosition k = !st->cur | |||||
? (!st->prev ? KeyState_Off : KeyState_Release) | ? (!st->prev ? KeyState_Off : KeyState_Release) | ||||
: ( st->prev ? KeyState_Hold : KeyState_Press); | : ( st->prev ? KeyState_Hold : KeyState_Press); | ||||
//if (!st->cur && !st->prev) k = KeyState_Off; else | //if (!st->cur && !st->prev) k = KeyState_Off; else | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | |||||
// State Table Output Debug | // State Table Output Debug | ||||
} | } | ||||
// 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 ----- | // ----- CLI Command Functions ----- | ||||
void cliFunc_matrixDebug ( char* args ) | void cliFunc_matrixDebug ( char* args ) |
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
void Matrix_setup(); | void Matrix_setup(); | ||||
void Matrix_scan( uint16_t scanNum ); | void Matrix_scan( uint16_t scanNum ); | ||||
void Matrix_currentChange( unsigned int current ); | |||||
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
} | } | ||||
// Signal from parent Scan Module that available current has changed | |||||
// current - mA | |||||
void LCD_currentChange( unsigned int current ) | |||||
{ | |||||
// TODO - Power savings? | |||||
} | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- | ||||
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
void LCD_setup(); | void LCD_setup(); | ||||
uint8_t LCD_scan(); | uint8_t LCD_scan(); | ||||
void LCD_currentChange( unsigned int current ); | |||||
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
} | } | ||||
else | 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_cableFaultsMaster++; | ||||
Connect_cableOkMaster = 0; | Connect_cableOkMaster = 0; | ||||
print(" Master "); | print(" Master "); | ||||
} | } | ||||
else | 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++; | Connect_cableChecksMaster++; | ||||
} | } | ||||
} | } | ||||
// Send reponse back to master | // Send reponse back to master | ||||
Connect_send_IdReport( id ); | 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 | // Propogate next Id if the connection is ok | ||||
if ( Connect_cableOkSlave ) | if ( Connect_cableOkSlave ) | ||||
{ | { | ||||
} | } | ||||
// 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 ----- | // ----- CLI Command Functions ----- | ||||
/* 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 | * 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 | * it under the terms of the GNU General Public License as published by | ||||
void Connect_send_ScanCode( uint8_t id, TriggerGuide *scanCodeStateList, uint8_t numScanCodes ); | 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_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 ); | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
Scan_scanCount = 0; | 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 ); | |||||
} | |||||
/* 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | ||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | ||||
void Scan_currentChange( unsigned int current ); // Called by Output Module | |||||