Archived
1
0

Adding remote capability LED control

- Works for all nodes in chain
- Synchronized to 30 ms update rate (required for ISSI chip)
  * Interconnect cannot handle full update speed from Scan module
  * Though it should be able to handle quite a bit more than 30 ms updates
This commit is contained in:
Jacob Alexander 2015-10-16 10:02:01 -07:00
parent 7e68e81f47
commit a10afbcc6a
2 changed files with 125 additions and 55 deletions

View File

@ -25,6 +25,11 @@
#include <led.h>
#include <print.h>
// Interconnect module if compiled in
#if defined(ConnectEnabled_define)
#include <connect_scan.h>
#endif
// Local Includes
#include "led_scan.h"
@ -37,6 +42,10 @@
#define LED_BufferLength 144
// TODO Needs to be defined per keyboard
#define LED_TotalChannels 144
// ----- Structs -----
@ -656,28 +665,15 @@ typedef struct LedControl {
uint16_t index;
} LedControl;
uint8_t LED_control_timer = 0;
void LED_control( LedControl *control )
{
// Only send if we've completed all other transactions
/*
if ( I2C_TxBuffer.sequencePos > 0 )
return;
// XXX
// ISSI Chip locks up if we spam updates too quickly (might be an I2C bug on this side too -HaaTa)
// Make sure we only send an update every 30 milliseconds at most
// It may be possible to optimize speed even further, but will likely require serious time with a logic analyzer
uint8_t currentTime = (uint8_t)systick_millis_count;
int8_t compare = (int8_t)(currentTime - LED_control_timer) & 0x7F;
if ( compare < 30 )
{
return;
}
LED_control_timer = currentTime;
*/
// Configure based upon the given mode
// TODO Handle multiple issi chips per node
// TODO Perhaps do gamma adjustment?
switch ( control->mode )
{
@ -696,7 +692,7 @@ void LED_control( LedControl *control )
break;
case LedControlMode_brightness_decrease_all:
for ( uint8_t channel = 0; channel < LED_BufferLength; channel++ )
for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ )
{
// Don't worry about rolling over, the cycle is quick
LED_pageBuffer.buffer[ channel ] -= control->amount;
@ -704,7 +700,7 @@ void LED_control( LedControl *control )
break;
case LedControlMode_brightness_increase_all:
for ( uint8_t channel = 0; channel < LED_BufferLength; channel++ )
for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ )
{
// Don't worry about rolling over, the cycle is quick
LED_pageBuffer.buffer[ channel ] += control->amount;
@ -712,7 +708,7 @@ void LED_control( LedControl *control )
break;
case LedControlMode_brightness_set_all:
for ( uint8_t channel = 0; channel < LED_BufferLength; channel++ )
for ( uint8_t channel = 0; channel < LED_TotalChannels; channel++ )
{
LED_pageBuffer.buffer[ channel ] = control->amount;
}
@ -726,6 +722,7 @@ void LED_control( LedControl *control )
LED_sendPage( (uint8_t*)&LED_pageBuffer, sizeof( LED_Buffer ), 0 );
}
uint8_t LED_control_timer = 0;
void LED_control_capability( uint8_t state, uint8_t stateType, uint8_t *args )
{
// Display capability name
@ -740,10 +737,84 @@ void LED_control_capability( uint8_t state, uint8_t stateType, uint8_t *args )
if ( stateType == 0x00 && state == 0x03 ) // Not on release
return;
// XXX
// ISSI Chip locks up if we spam updates too quickly (might be an I2C bug on this side too -HaaTa)
// Make sure we only send an update every 30 milliseconds at most
// It may be possible to optimize speed even further, but will likely require serious time with a logic analyzer
uint8_t currentTime = (uint8_t)systick_millis_count;
int8_t compare = (int8_t)(currentTime - LED_control_timer) & 0x7F;
if ( compare < 30 )
{
return;
}
LED_control_timer = currentTime;
// Set the input structure
LedControl *control = (LedControl*)args;
// TODO broadcast to rest of interconnect nodes if necessary
// Interconnect broadcasting
#if defined(ConnectEnabled_define)
uint8_t send_packet = 0;
uint8_t ignore_node = 0;
// By default send to the *next* node, which will determine where to go next
extern uint8_t Connect_id; // connect_scan.c
uint8_t addr = Connect_id + 1;
switch ( control->mode )
{
// Calculate the led address to send
// If greater than the Total hannels
// Set address - Total channels
// Otherwise, ignore
case LedControlMode_brightness_decrease:
case LedControlMode_brightness_increase:
case LedControlMode_brightness_set:
// Ignore if led is on this node
if ( control->index < LED_TotalChannels )
break;
// Calculate new led index
control->index -= LED_TotalChannels;
ignore_node = 1;
send_packet = 1;
break;
// Broadcast to all nodes
// XXX Do not set broadcasting address
// Will send command twice
case LedControlMode_brightness_decrease_all:
case LedControlMode_brightness_increase_all:
case LedControlMode_brightness_set_all:
send_packet = 1;
break;
}
// Only send interconnect remote capability packet if necessary
if ( send_packet )
{
// generatedKeymap.h
extern const Capability CapabilitiesList[];
// Broadcast layerStackExact remote capability (0xFF is the broadcast id)
Connect_send_RemoteCapability(
addr,
LED_control_capability_index,
state,
stateType,
CapabilitiesList[ LED_control_capability_index ].argCount,
args
);
}
// If there is nothing to do on this node, ignore
if ( ignore_node )
return;
#endif
// Modify led state of this node
LED_control( control );
}

View File

@ -42,34 +42,6 @@
// ----- Macros -----
// Macro for adding to each uart Tx ring buffer
#define uart_addTxBuffer( uartNum ) \
case uartNum: \
/* Delay UART copy until there's some space left */ \
while ( uart_tx_buf[ uartNum ].items + count > UART_Buffer_Size ) \
{ \
warn_msg("Too much data to send on UART0, waiting..."); \
delay( 1 ); \
} \
/* Append data to ring buffer */ \
for ( uint8_t c = 0; c < count; c++ ) \
{ \
if ( Connect_debug ) \
{ \
printHex( buffer[ c ] ); \
print( " +" #uartNum NL ); \
} \
uart_tx_buf[ uartNum ].buffer[ uart_tx_buf[ uartNum ].tail++ ] = buffer[ c ]; \
uart_tx_buf[ uartNum ].items++; \
if ( uart_tx_buf[ uartNum ].tail >= UART_Buffer_Size ) \
uart_tx_buf[ uartNum ].tail = 0; \
if ( uart_tx_buf[ uartNum ].head == uart_tx_buf[ uartNum ].tail ) \
uart_tx_buf[ uartNum ].head++; \
if ( uart_tx_buf[ uartNum ].head >= UART_Buffer_Size ) \
uart_tx_buf[ uartNum ].head = 0; \
} \
break
// Macro for popping from Tx ring buffer
#define uart_fillTxFifo( uartNum ) \
{ \
@ -233,14 +205,41 @@ void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
return;
}
// Choose the uart
switch ( uart )
// Invalid UART
if ( uart >= UART_Num_Interfaces )
{
uart_addTxBuffer( UART_Master );
uart_addTxBuffer( UART_Slave );
default:
erro_msg("Invalid UART to send from...");
break;
erro_print("Invalid UART to send from...");
return;
}
// Delay UART copy until there's some space left
while ( uart_tx_buf[ uart ].items + count > UART_Buffer_Size )
{
warn_msg("Too much data to send on UART");
printInt8( uart );
print( ", waiting..." NL );
delay( 1 );
}
// Append data to ring buffer
for ( uint8_t c = 0; c < count; c++ )
{
if ( Connect_debug )
{
printHex( buffer[ c ] );
print(" +");
printInt8( uart );
print( NL );
}
uart_tx_buf[ uart ].buffer[ uart_tx_buf[ uart ].tail++ ] = buffer[ c ];
uart_tx_buf[ uart ].items++;
if ( uart_tx_buf[ uart ].tail >= UART_Buffer_Size )
uart_tx_buf[ uart ].tail = 0;
if ( uart_tx_buf[ uart ].head == uart_tx_buf[ uart ].tail )
uart_tx_buf[ uart ].head++;
if ( uart_tx_buf[ uart ].head >= UART_Buffer_Size )
uart_tx_buf[ uart ].head = 0;
}
}
@ -718,7 +717,7 @@ uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_
}
// - Remote Capability Variables -
#define Connect_receive_RemoteCapabilityMaxArgs 5 // XXX Calculate the max using kll
#define Connect_receive_RemoteCapabilityMaxArgs 25 // XXX Calculate the max using kll
RemoteCapabilityCommand Connect_receive_RemoteCapabilityBuffer;
uint8_t Connect_receive_RemoteCapabilityArgs[Connect_receive_RemoteCapabilityMaxArgs];