Browse Source

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
capsense
Jacob Alexander 8 years ago
parent
commit
a10afbcc6a
2 changed files with 125 additions and 55 deletions
  1. 90
    19
      Scan/ISSILed/led_scan.c
  2. 35
    36
      Scan/UARTConnect/connect_scan.c

+ 90
- 19
Scan/ISSILed/led_scan.c 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 );
}


+ 35
- 36
Scan/UARTConnect/connect_scan.c 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];