Adding basic remote capabilities + UART Rx DMA buffers
- Rx buffers weren't fast enough, had to use DMA :D - Basic LCD remote capabilities are working, single node - Multi-node broadcast seems to have a bug still - DMA ring buffer allowed for significant processing simplification * There is an overrun risk, but the buffer is large and generally there isn't too much data being sent (just very quickly) - Split out LCD layer stack capability into itself and an "exact" version used for updating remote nodes
This commit is contained in:
parent
44a9803cab
commit
7e68e81f47
@ -277,7 +277,7 @@ if ( CTAGS_EXECUTABLE )
|
||||
endforeach ()
|
||||
|
||||
# Generate the ctags
|
||||
execute_process ( COMMAND ctags ${CTAG_PATHS}
|
||||
execute_process ( COMMAND ctags --fields=+l ${CTAG_PATHS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
endif ()
|
||||
|
28
Lib/mk20dx.h
28
Lib/mk20dx.h
@ -511,11 +511,37 @@
|
||||
#define DMA_ERQ_ERQ1 ((uint32_t)1<<1) // Enable DMA Request 1
|
||||
#define DMA_ERQ_ERQ2 ((uint32_t)1<<2) // Enable DMA Request 2
|
||||
#define DMA_ERQ_ERQ3 ((uint32_t)1<<3) // Enable DMA Request 3
|
||||
#define DMA_ERQ_ERQ4 ((uint32_t)1<<4) // Enable DMA Request 4
|
||||
#define DMA_ERQ_ERQ5 ((uint32_t)1<<5) // Enable DMA Request 5
|
||||
#define DMA_ERQ_ERQ6 ((uint32_t)1<<6) // Enable DMA Request 6
|
||||
#define DMA_ERQ_ERQ7 ((uint32_t)1<<7) // Enable DMA Request 7
|
||||
#define DMA_ERQ_ERQ8 ((uint32_t)1<<8) // Enable DMA Request 8
|
||||
#define DMA_ERQ_ERQ9 ((uint32_t)1<<9) // Enable DMA Request 9
|
||||
#define DMA_ERQ_ERQ10 ((uint32_t)1<<10) // Enable DMA Request 10
|
||||
#define DMA_ERQ_ERQ11 ((uint32_t)1<<11) // Enable DMA Request 11
|
||||
#define DMA_ERQ_ERQ12 ((uint32_t)1<<12) // Enable DMA Request 12
|
||||
#define DMA_ERQ_ERQ13 ((uint32_t)1<<13) // Enable DMA Request 13
|
||||
#define DMA_ERQ_ERQ14 ((uint32_t)1<<14) // Enable DMA Request 14
|
||||
#define DMA_ERQ_ERQ15 ((uint32_t)1<<15) // Enable DMA Request 15
|
||||
#define DMA_ERQ_ERQ16 ((uint32_t)1<<16) // Enable DMA Request 16
|
||||
#define DMA_EEI *(volatile uint32_t *)0x40008014 // Enable Error Interrupt Register
|
||||
#define DMA_EEI_EEI0 ((uint32_t)1<<0) // Enable Error Interrupt 0
|
||||
#define DMA_EEI_EEI1 ((uint32_t)1<<1) // Enable Error Interrupt 1
|
||||
#define DMA_EEI_EEI2 ((uint32_t)1<<2) // Enable Error Interrupt 2
|
||||
#define DMA_EEI_EEI3 ((uint32_t)1<<3) // Enable Error Interrupt 3
|
||||
#define DMA_EEI_EEI4 ((uint32_t)1<<4) // Enable Error Interrupt 4
|
||||
#define DMA_EEI_EEI5 ((uint32_t)1<<5) // Enable Error Interrupt 5
|
||||
#define DMA_EEI_EEI6 ((uint32_t)1<<6) // Enable Error Interrupt 6
|
||||
#define DMA_EEI_EEI7 ((uint32_t)1<<7) // Enable Error Interrupt 7
|
||||
#define DMA_EEI_EEI8 ((uint32_t)1<<8) // Enable Error Interrupt 8
|
||||
#define DMA_EEI_EEI9 ((uint32_t)1<<9) // Enable Error Interrupt 9
|
||||
#define DMA_EEI_EEI10 ((uint32_t)1<<10) // Enable Error Interrupt 10
|
||||
#define DMA_EEI_EEI11 ((uint32_t)1<<11) // Enable Error Interrupt 11
|
||||
#define DMA_EEI_EEI12 ((uint32_t)1<<12) // Enable Error Interrupt 12
|
||||
#define DMA_EEI_EEI13 ((uint32_t)1<<13) // Enable Error Interrupt 13
|
||||
#define DMA_EEI_EEI14 ((uint32_t)1<<14) // Enable Error Interrupt 14
|
||||
#define DMA_EEI_EEI15 ((uint32_t)1<<15) // Enable Error Interrupt 15
|
||||
#define DMA_EEI_EEI16 ((uint32_t)1<<16) // Enable Error Interrupt 16
|
||||
#define DMA_CEEI *(volatile uint8_t *)0x40008018 // Clear Enable Error Interrupt Register
|
||||
#define DMA_CEEI_CEEI(n) ((uint8_t)(n & 3)<<0) // Clear Enable Error Interrupt
|
||||
#define DMA_CEEI_CAEE ((uint8_t)1<<6) // Clear All Enable Error Interrupts
|
||||
@ -1468,6 +1494,8 @@ typedef struct {
|
||||
#define UART0_MA2 *(volatile uint8_t *)0x4006A009 // UART Match Address Registers 2
|
||||
#define UART0_C4 *(volatile uint8_t *)0x4006A00A // UART Control Register 4
|
||||
#define UART0_C5 *(volatile uint8_t *)0x4006A00B // UART Control Register 5
|
||||
#define UART_C5_TDMAS 0x80
|
||||
#define UART_C5_RDMAS 0x20
|
||||
#define UART0_ED *(volatile uint8_t *)0x4006A00C // UART Extended Data Register
|
||||
#define UART0_MODEM *(volatile uint8_t *)0x4006A00D // UART Modem Register
|
||||
#define UART0_IR *(volatile uint8_t *)0x4006A00E // UART Infrared Register
|
||||
|
@ -97,7 +97,7 @@ static uint8_t usb_debug_descriptor[] = {
|
||||
|
||||
|
||||
|
||||
// ----- USB HID Report Descriptsors -----
|
||||
// ----- USB HID Report Descriptors -----
|
||||
|
||||
// Each HID interface needs a special report descriptor that tells
|
||||
// the meaning and format of the data.
|
||||
|
@ -196,6 +196,7 @@ void Matrix_setup()
|
||||
print( NL );
|
||||
info_msg("Max Keys: ");
|
||||
printHex( Matrix_maxKeys );
|
||||
print( NL );
|
||||
|
||||
// Clear out Debounce Array
|
||||
for ( uint8_t item = 0; item < Matrix_maxKeys; item++ )
|
||||
|
@ -66,7 +66,8 @@ STLcdDefaultImage = "
|
||||
|
||||
# Layer Status Display
|
||||
|
||||
LCDLayerDisplay => LCD_layerStack_capability();
|
||||
LCDLayerDisplay => LCD_layerStack_capability();
|
||||
LCDLayerDisplayExact => LCD_layerStackExact_capability( display : 1, stack1 : 2, stack2 : 2, stack3 : 2, stack4 : 2 );
|
||||
|
||||
|
||||
# LCD Module Enabled
|
||||
|
@ -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 "lcd_scan.h"
|
||||
|
||||
@ -344,29 +349,26 @@ inline uint8_t LCD_scan()
|
||||
|
||||
// ----- Capabilities -----
|
||||
|
||||
uint16_t LCD_layerStack_prevSize = 0;
|
||||
uint16_t LCD_layerStack_prevTop = 0;
|
||||
void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args )
|
||||
// Takes 1 8 bit length and 4 16 bit arguments, each corresponding to a layer index
|
||||
// Ordered from top to bottom
|
||||
// The first argument indicates how many numbers to display (max 4), set to 0 to load default image
|
||||
uint16_t LCD_layerStackExact[4];
|
||||
uint8_t LCD_layerStackExact_size = 0;
|
||||
typedef struct LCD_layerStackExact_args {
|
||||
uint8_t numArgs;
|
||||
uint16_t layers[4];
|
||||
} LCD_layerStackExact_args;
|
||||
void LCD_layerStackExact_capability( uint8_t state, uint8_t stateType, uint8_t *args )
|
||||
{
|
||||
// Display capability name
|
||||
if ( stateType == 0xFF && state == 0xFF )
|
||||
{
|
||||
print("LCD_layerStack_capability");
|
||||
print("LCD_layerStackExact_capability(num,layer1,layer2,layer3,layer4)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the layer stack, top to bottom
|
||||
extern uint16_t macroLayerIndexStack[];
|
||||
extern uint16_t macroLayerIndexStackSize;
|
||||
|
||||
// Ignore if the stack size hasn't changed and the top of the stack is the same
|
||||
if ( macroLayerIndexStackSize == LCD_layerStack_prevSize
|
||||
&& macroLayerIndexStack[macroLayerIndexStackSize - 1] == LCD_layerStack_prevTop )
|
||||
{
|
||||
return;
|
||||
}
|
||||
LCD_layerStack_prevSize = macroLayerIndexStackSize;
|
||||
LCD_layerStack_prevTop = macroLayerIndexStack[macroLayerIndexStackSize - 1];
|
||||
// Read arguments
|
||||
LCD_layerStackExact_args *stack_args = (LCD_layerStackExact_args*)args;
|
||||
|
||||
// Number data for LCD
|
||||
const uint8_t numbers[10][128] = {
|
||||
@ -397,10 +399,10 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args
|
||||
};
|
||||
|
||||
// Only display if there are layers active
|
||||
if ( macroLayerIndexStackSize > 0 )
|
||||
if ( stack_args->numArgs > 0 )
|
||||
{
|
||||
// Set the color according to the "top-of-stack" layer
|
||||
uint16_t layerIndex = macroLayerIndexStack[ macroLayerIndexStackSize - 1 ];
|
||||
uint16_t layerIndex = stack_args->layers[0];
|
||||
FTM0_C0V = colors[ layerIndex ][0];
|
||||
FTM0_C1V = colors[ layerIndex ][1];
|
||||
FTM0_C2V = colors[ layerIndex ][2];
|
||||
@ -418,9 +420,9 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args
|
||||
LCD_writeControlReg( 0x00 );
|
||||
|
||||
// Write data
|
||||
for ( uint16_t layer = 1; layer <= macroLayerIndexStackSize; layer++ )
|
||||
for ( uint16_t layer = 0; layer < stack_args->numArgs; layer++ )
|
||||
{
|
||||
layerIndex = macroLayerIndexStack[ macroLayerIndexStackSize - layer ];
|
||||
layerIndex = stack_args->layers[ layer ];
|
||||
|
||||
// Default to 0, if over 9
|
||||
if ( layerIndex > 9 )
|
||||
@ -434,7 +436,7 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args
|
||||
|
||||
// Blank out rest of display
|
||||
uint8_t data = 0;
|
||||
for ( uint8_t c = 0; c < 4 - macroLayerIndexStackSize; c++ )
|
||||
for ( uint8_t c = 0; c < 4 - stack_args->numArgs; c++ )
|
||||
{
|
||||
for ( uint8_t byte = 0; byte < 32; byte++ )
|
||||
{
|
||||
@ -456,6 +458,65 @@ void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args
|
||||
}
|
||||
}
|
||||
|
||||
// Determines the current layer stack, and sets the LCD output accordingly
|
||||
// Will only work on a master node when using the interconnect (use LCD_layerStackExact_capability instead)
|
||||
uint16_t LCD_layerStack_prevSize = 0;
|
||||
uint16_t LCD_layerStack_prevTop = 0;
|
||||
void LCD_layerStack_capability( uint8_t state, uint8_t stateType, uint8_t *args )
|
||||
{
|
||||
// Display capability name
|
||||
if ( stateType == 0xFF && state == 0xFF )
|
||||
{
|
||||
print("LCD_layerStack_capability()");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the layer stack, top to bottom
|
||||
extern uint16_t macroLayerIndexStack[];
|
||||
extern uint16_t macroLayerIndexStackSize;
|
||||
|
||||
// Ignore if the stack size hasn't changed and the top of the stack is the same
|
||||
if ( macroLayerIndexStackSize == LCD_layerStack_prevSize
|
||||
&& macroLayerIndexStack[macroLayerIndexStackSize - 1] == LCD_layerStack_prevTop )
|
||||
{
|
||||
return;
|
||||
}
|
||||
LCD_layerStack_prevSize = macroLayerIndexStackSize;
|
||||
LCD_layerStack_prevTop = macroLayerIndexStack[macroLayerIndexStackSize - 1];
|
||||
|
||||
LCD_layerStackExact_args stack_args;
|
||||
memset( stack_args.layers, 0, sizeof( stack_args.layers ) );
|
||||
|
||||
// Use the LCD_layerStackExact_capability to set the LCD using the determined stack
|
||||
// Construct argument set for capability
|
||||
stack_args.numArgs = macroLayerIndexStackSize;
|
||||
for ( uint16_t layer = 1; layer <= macroLayerIndexStackSize; layer++ )
|
||||
{
|
||||
stack_args.layers[ layer - 1 ] = macroLayerIndexStack[ macroLayerIndexStackSize - layer ];
|
||||
}
|
||||
|
||||
// Only deal with the interconnect if it has been compiled in
|
||||
#if defined(ConnectEnabled_define)
|
||||
if ( Connect_master )
|
||||
{
|
||||
// generatedKeymap.h
|
||||
extern const Capability CapabilitiesList[];
|
||||
|
||||
// Broadcast layerStackExact remote capability (0xFF is the broadcast id)
|
||||
Connect_send_RemoteCapability(
|
||||
0xFF,
|
||||
LCD_layerStackExact_capability_index,
|
||||
state,
|
||||
stateType,
|
||||
CapabilitiesList[ LCD_layerStackExact_capability_index ].argCount,
|
||||
(uint8_t*)&stack_args
|
||||
);
|
||||
}
|
||||
#endif
|
||||
// Call LCD_layerStackExact directly
|
||||
LCD_layerStackExact_capability( state, stateType, (uint8_t*)&stack_args );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----- CLI Command Functions -----
|
||||
|
@ -26,9 +26,11 @@ UARTConnectBaudFine => UARTConnectBaudFine_define;
|
||||
# Thus baud setting = 26
|
||||
# NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
|
||||
# Baud fine setting = 0x02
|
||||
UARTConnectBaud = 1; # 4.5 Mbps @ 72 MHz
|
||||
UARTConnectBaud = 1; # 4.5 Mbpsa @ 72 MHz
|
||||
UARTConnectBaudFine = 0x0;
|
||||
|
||||
#UARTConnectBaud = 39; # 115385 bps @ 72 MHz (close to 115200)
|
||||
|
||||
# Cable Check Command Length
|
||||
# This defines the length of the cable command
|
||||
# 0xD2 11010010 is used for each check byte
|
||||
|
@ -31,22 +31,22 @@
|
||||
|
||||
|
||||
|
||||
// ----- Macros -----
|
||||
// ----- Defines -----
|
||||
|
||||
#define UART_Num_Interfaces 2
|
||||
#define UART_Master 1
|
||||
#define UART_Slave 0
|
||||
#define uart_lock_m( uartNum ) uart##uartNum##_lock
|
||||
#define uart_buffer_items_m( uartNum ) uart##uartNum##_buffer_items
|
||||
#define uart_buffer_m( uartNum ) uart##uartNum##_buffer
|
||||
#define uart_buffer_head_m( uartNum ) uart##uartNum##_buffer_head
|
||||
#define uart_buffer_tail_m( uartNum ) uart##uartNum##_buffer_tail
|
||||
#define uart_tx_status_m( uartNum ) uart##uartNum##_tx_status
|
||||
#define UART_Buffer_Size UARTConnectBufSize_define
|
||||
|
||||
|
||||
|
||||
// ----- 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_buffer_items_m( uartNum ) + count > uart_buffer_size ) \
|
||||
while ( uart_tx_buf[ uartNum ].items + count > UART_Buffer_Size ) \
|
||||
{ \
|
||||
warn_msg("Too much data to send on UART0, waiting..."); \
|
||||
delay( 1 ); \
|
||||
@ -59,14 +59,14 @@ case uartNum: \
|
||||
printHex( buffer[ c ] ); \
|
||||
print( " +" #uartNum NL ); \
|
||||
} \
|
||||
uart_buffer_m( uartNum )[ uart_buffer_tail_m( uartNum )++ ] = buffer[ c ]; \
|
||||
uart_buffer_items_m( uartNum )++; \
|
||||
if ( uart_buffer_tail_m( uartNum ) >= uart_buffer_size ) \
|
||||
uart_buffer_tail_m( uartNum ) = 0; \
|
||||
if ( uart_buffer_head_m( uartNum ) == uart_buffer_tail_m( uartNum ) ) \
|
||||
uart_buffer_head_m( uartNum )++; \
|
||||
if ( uart_buffer_head_m( uartNum ) >= uart_buffer_size ) \
|
||||
uart_buffer_head_m( uartNum ) = 0; \
|
||||
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
|
||||
|
||||
@ -83,7 +83,7 @@ case uartNum: \
|
||||
print("/"); \
|
||||
printHex( UART##uartNum##_TCFIFO ); \
|
||||
print("/"); \
|
||||
printHex( uart##uartNum##_buffer_items ); \
|
||||
printHex( uart_tx_buf[ uartNum ].items ); \
|
||||
print( NL ); \
|
||||
} \
|
||||
/* XXX Doesn't work well */ \
|
||||
@ -92,138 +92,12 @@ case uartNum: \
|
||||
fifoSize -= UART##uartNum##_TCFIFO; \
|
||||
while ( fifoSize-- != 0 ) \
|
||||
{ \
|
||||
if ( uart##uartNum##_buffer_items == 0 ) \
|
||||
if ( uart_tx_buf[ uartNum ].items == 0 ) \
|
||||
break; \
|
||||
UART##uartNum##_D = uart##uartNum##_buffer[ uart##uartNum##_buffer_head++ ]; \
|
||||
uart##uartNum##_buffer_items--; \
|
||||
if ( uart##uartNum##_buffer_head >= uart_buffer_size ) \
|
||||
uart##uartNum##_buffer_head = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Macro for processing UART Rx
|
||||
#define uart_processRx( uartNum ) \
|
||||
{ \
|
||||
if ( !( UART##uartNum##_S1 & UART_S1_RDRF ) ) \
|
||||
return; \
|
||||
uint8_t available = UART##uartNum##_RCFIFO; \
|
||||
if ( available == 0 ) \
|
||||
{ \
|
||||
available = UART##uartNum##_D; \
|
||||
UART##uartNum##_CFIFO = UART_CFIFO_RXFLUSH; \
|
||||
return; \
|
||||
} \
|
||||
/* Process each byte in the UART buffer */ \
|
||||
while ( available-- > 0 ) \
|
||||
{ \
|
||||
/* First check if there was noise or Parity issues with current byte */ \
|
||||
uint8_t err_status = UART##uartNum##_ED; \
|
||||
/* Read byte from Rx FIFO */ \
|
||||
uint8_t byteRead = UART##uartNum##_D; \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
printHex( byteRead ); \
|
||||
print("("); \
|
||||
printInt8( available ); \
|
||||
print(") <-"); \
|
||||
} \
|
||||
/* Check error status */ \
|
||||
if ( err_status & 0x80 ) \
|
||||
{ \
|
||||
print(" NOISY "); \
|
||||
} \
|
||||
if ( err_status & 0x40 ) \
|
||||
{ \
|
||||
print(" PARITY ERR "); \
|
||||
} \
|
||||
/* Ignore current byte if there was an error */ \
|
||||
if ( err_status ) \
|
||||
{ \
|
||||
uart##uartNum##_rx_status = UARTStatus_Wait; \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print( NL ); \
|
||||
} \
|
||||
continue; \
|
||||
} \
|
||||
switch ( uart##uartNum##_rx_status ) \
|
||||
{ \
|
||||
case UARTStatus_Wait: \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print(" Wait "); \
|
||||
} \
|
||||
uart##uartNum##_rx_status = byteRead == 0x16 ? UARTStatus_SYN : UARTStatus_Wait; \
|
||||
break; \
|
||||
case UARTStatus_SYN: \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print(" SYN "); \
|
||||
} \
|
||||
uart##uartNum##_rx_status = byteRead == 0x01 ? UARTStatus_SOH : UARTStatus_Wait; \
|
||||
break; \
|
||||
case UARTStatus_SOH: \
|
||||
{ \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print(" SOH "); \
|
||||
} \
|
||||
/* Check if this is actually a reserved CMD 0x16 */ \
|
||||
if ( byteRead == Command_SYN ) \
|
||||
{ \
|
||||
uart##uartNum##_rx_status = UARTStatus_SYN; \
|
||||
break; \
|
||||
} \
|
||||
/* Otherwise process the command */ \
|
||||
uint8_t byte = byteRead; \
|
||||
if ( byte < Command_TOP ) \
|
||||
{ \
|
||||
uart##uartNum##_rx_status = UARTStatus_Command; \
|
||||
uart##uartNum##_rx_command = byte; \
|
||||
uart##uartNum##_rx_bytes_waiting = 0xFFFF; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
uart##uartNum##_rx_status = UARTStatus_Wait; \
|
||||
} \
|
||||
switch ( uart##uartNum##_rx_command ) \
|
||||
{ \
|
||||
case IdRequest: \
|
||||
Connect_receive_IdRequest( 0, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ); \
|
||||
uart##uartNum##_rx_status = UARTStatus_Wait; \
|
||||
break; \
|
||||
default: \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print(" ### "); \
|
||||
printHex( uart##uartNum##_rx_command ); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
case UARTStatus_Command: \
|
||||
{ \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print(" CMD "); \
|
||||
} \
|
||||
/* Call specific UARTConnect command receive function */ \
|
||||
uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart##uartNum##_rx_command ]); \
|
||||
if ( rcvFunc( byteRead, (uint16_t*)&uart##uartNum##_rx_bytes_waiting, uartNum ) ) \
|
||||
uart##uartNum##_rx_status = UARTStatus_Wait; \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
erro_msg("Invalid UARTStatus..."); \
|
||||
uart##uartNum##_rx_status = UARTStatus_Wait; \
|
||||
available++; \
|
||||
continue; \
|
||||
} \
|
||||
if ( Connect_debug ) \
|
||||
{ \
|
||||
print( NL ); \
|
||||
} \
|
||||
UART##uartNum##_D = uart_tx_buf[ uartNum ].buffer[ uart_tx_buf[ uartNum ].head++ ]; \
|
||||
uart_tx_buf[ uartNum ].items--; \
|
||||
if ( uart_tx_buf[ uartNum ].head >= UART_Buffer_Size ) \
|
||||
uart_tx_buf[ uartNum ].head = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -231,31 +105,31 @@ case uartNum: \
|
||||
#define uart_lockTx( uartNum ) \
|
||||
{ \
|
||||
/* First, secure place in line for the resource */ \
|
||||
while ( uart_lock_m( uartNum ) ); \
|
||||
uart_lock_m( uartNum ) = 1; \
|
||||
while ( uart_tx_status[ uartNum ].lock ); \
|
||||
uart_tx_status[ uartNum ].lock = 1; \
|
||||
/* Next, wait unit the UART is ready */ \
|
||||
while ( uart_tx_status_m( uartNum ) != UARTStatus_Ready ); \
|
||||
uart_tx_status_m( uartNum ) = UARTStatus_Wait; \
|
||||
while ( uart_tx_status[ uartNum ].status != UARTStatus_Ready ); \
|
||||
uart_tx_status[ uartNum ].status = UARTStatus_Wait; \
|
||||
}
|
||||
|
||||
#define uart_lockBothTx( uartNum1, uartNum2 ) \
|
||||
{ \
|
||||
/* First, secure place in line for the resource */ \
|
||||
while ( uart_lock_m( uartNum1 ) || uart_lock_m( uartNum2 ) ); \
|
||||
uart_lock_m( uartNum1 ) = 1; \
|
||||
uart_lock_m( uartNum2 ) = 1; \
|
||||
while ( uart_tx_status[ uartNum1 ].lock || uart_tx_status[ uartNum2 ].lock ); \
|
||||
uart_tx_status[ uartNum1 ].lock = 1; \
|
||||
uart_tx_status[ uartNum2 ].lock = 1; \
|
||||
/* Next, wait unit the UARTs are ready */ \
|
||||
while ( uart_tx_status_m( uartNum1 ) != UARTStatus_Ready || uart_tx_status_m( uartNum2 ) != UARTStatus_Ready ); \
|
||||
uart_tx_status_m( uartNum1 ) = UARTStatus_Wait; \
|
||||
uart_tx_status_m( uartNum2 ) = UARTStatus_Wait; \
|
||||
while ( uart_tx_status[ uartNum1 ].status != UARTStatus_Ready || uart_tx_status[ uartNum2 ].status != UARTStatus_Ready ); \
|
||||
uart_tx_status[ uartNum1 ].status = UARTStatus_Wait; \
|
||||
uart_tx_status[ uartNum2 ].status = UARTStatus_Wait; \
|
||||
}
|
||||
|
||||
#define uart_unlockTx( uartNum ) \
|
||||
{ \
|
||||
/* Ready the UART */ \
|
||||
uart_tx_status_m( uartNum ) = UARTStatus_Ready; \
|
||||
uart_tx_status[ uartNum ].status = UARTStatus_Ready; \
|
||||
/* Unlock the resource */ \
|
||||
uart_lock_m( uartNum ) = 0; \
|
||||
uart_tx_status[ uartNum ].lock = 0; \
|
||||
}
|
||||
|
||||
|
||||
@ -273,6 +147,33 @@ void cliFunc_connectSts ( char *args );
|
||||
|
||||
|
||||
|
||||
// ----- Structs -----
|
||||
|
||||
typedef struct UARTRingBuf {
|
||||
uint8_t head;
|
||||
uint8_t tail;
|
||||
uint8_t items;
|
||||
uint8_t buffer[UART_Buffer_Size];
|
||||
} UARTRingBuf;
|
||||
|
||||
typedef struct UARTDMABuf {
|
||||
uint8_t buffer[UART_Buffer_Size];
|
||||
uint16_t last_read;
|
||||
} UARTDMABuf;
|
||||
|
||||
typedef struct UARTStatusRx {
|
||||
UARTStatus status;
|
||||
Command command;
|
||||
uint16_t bytes_waiting;
|
||||
} UARTStatusRx;
|
||||
|
||||
typedef struct UARTStatusTx {
|
||||
UARTStatus status;
|
||||
uint8_t lock;
|
||||
} UARTStatusTx;
|
||||
|
||||
|
||||
|
||||
// ----- Variables -----
|
||||
|
||||
// Connect Module command dictionary
|
||||
@ -306,46 +207,27 @@ uint32_t Connect_lastCheck = 0; // Cable Check scheduler
|
||||
uint8_t Connect_debug = 0; // Set 1 for debug
|
||||
uint8_t Connect_override = 0; // Prevents master from automatically being set
|
||||
|
||||
|
||||
// -- Rx Status Variables --
|
||||
|
||||
volatile UARTStatus uart0_rx_status;
|
||||
volatile UARTStatus uart1_rx_status;
|
||||
volatile uint16_t uart0_rx_bytes_waiting;
|
||||
volatile uint16_t uart1_rx_bytes_waiting;
|
||||
volatile Command uart0_rx_command;
|
||||
volatile Command uart1_rx_command;
|
||||
volatile uint8_t uart0_lock;
|
||||
volatile uint8_t uart1_lock;
|
||||
|
||||
|
||||
// -- Tx Status Variables --
|
||||
|
||||
volatile UARTStatus uart0_tx_status;
|
||||
volatile UARTStatus uart1_tx_status;
|
||||
|
||||
|
||||
// -- Ring Buffer Variables --
|
||||
|
||||
#define uart_buffer_size UARTConnectBufSize_define
|
||||
volatile uint8_t uart0_buffer_head;
|
||||
volatile uint8_t uart0_buffer_tail;
|
||||
volatile uint8_t uart0_buffer_items;
|
||||
volatile uint8_t uart0_buffer[uart_buffer_size];
|
||||
volatile uint8_t uart1_buffer_head;
|
||||
volatile uint8_t uart1_buffer_tail;
|
||||
volatile uint8_t uart1_buffer_items;
|
||||
volatile uint8_t uart1_buffer[uart_buffer_size];
|
||||
|
||||
volatile uint8_t uarts_configured = 0;
|
||||
|
||||
|
||||
// -- Rx Variables --
|
||||
|
||||
volatile UARTDMABuf uart_rx_buf[UART_Num_Interfaces];
|
||||
volatile UARTStatusRx uart_rx_status[UART_Num_Interfaces];
|
||||
|
||||
|
||||
// -- Tx Variables --
|
||||
|
||||
UARTRingBuf uart_tx_buf [UART_Num_Interfaces];
|
||||
UARTStatusTx uart_tx_status[UART_Num_Interfaces];
|
||||
|
||||
|
||||
// -- Ring Buffer Convenience Functions --
|
||||
|
||||
void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
|
||||
{
|
||||
// Too big to fit into buffer
|
||||
if ( count > uart_buffer_size )
|
||||
if ( count > UART_Buffer_Size )
|
||||
{
|
||||
erro_msg("Too big of a command to fit into the buffer...");
|
||||
return;
|
||||
@ -480,6 +362,51 @@ void Connect_send_Animation( uint8_t id, uint8_t *paramList, uint8_t numParams )
|
||||
uart_unlockTx( UART_Slave );
|
||||
}
|
||||
|
||||
// Send a remote capability command using capability index
|
||||
// This may not be what's expected (especially if the firmware is not the same on each node)
|
||||
// To broadcast to all slave nodes, set id to 255 instead of a specific id
|
||||
void Connect_send_RemoteCapability( uint8_t id, uint8_t capabilityIndex, uint8_t state, uint8_t stateType, uint8_t numArgs, uint8_t *args )
|
||||
{
|
||||
// Prepare header
|
||||
uint8_t header[] = { 0x16, 0x01, RemoteCapability, id, capabilityIndex, state, stateType, numArgs };
|
||||
|
||||
// Ignore current id
|
||||
if ( id == Connect_id )
|
||||
return;
|
||||
|
||||
// Send towards slave node
|
||||
if ( id > Connect_id )
|
||||
{
|
||||
// Lock slave bound Tx
|
||||
uart_lockTx( UART_Slave );
|
||||
|
||||
// Send header
|
||||
Connect_addBytes( header, sizeof( header ), UART_Slave );
|
||||
|
||||
// Send arguments
|
||||
Connect_addBytes( args, numArgs, UART_Slave );
|
||||
|
||||
// Unlock Tx
|
||||
uart_unlockTx( UART_Slave );
|
||||
}
|
||||
|
||||
// Send towards master node
|
||||
if ( id < Connect_id || id == 255 )
|
||||
{
|
||||
// Lock slave bound Tx
|
||||
uart_lockTx( UART_Master );
|
||||
|
||||
// Send header
|
||||
Connect_addBytes( header, sizeof( header ), UART_Master );
|
||||
|
||||
// Send arguments
|
||||
Connect_addBytes( args, numArgs, UART_Master );
|
||||
|
||||
// Unlock Tx
|
||||
uart_unlockTx( UART_Master );
|
||||
}
|
||||
}
|
||||
|
||||
void Connect_send_Idle( uint8_t num )
|
||||
{
|
||||
// Wait until the Tx buffers are ready, then lock them
|
||||
@ -745,6 +672,8 @@ uint8_t Connect_receive_ScanCode( uint8_t byte, uint16_t *pending_bytes, uint8_t
|
||||
break;
|
||||
}
|
||||
// Propagate ScanCode packet
|
||||
// XXX It would be safer to buffer the scancodes first, before transmitting the packet -Jacob
|
||||
// The current method is the more efficient/aggressive, but could cause issues if there were errors during transmission
|
||||
else switch ( (*pending_bytes)-- )
|
||||
{
|
||||
// Byte count always starts at 0xFFFF
|
||||
@ -788,6 +717,103 @@ uint8_t Connect_receive_Animation( uint8_t byte, uint16_t *pending_bytes, uint8_
|
||||
return 1;
|
||||
}
|
||||
|
||||
// - Remote Capability Variables -
|
||||
#define Connect_receive_RemoteCapabilityMaxArgs 5 // XXX Calculate the max using kll
|
||||
RemoteCapabilityCommand Connect_receive_RemoteCapabilityBuffer;
|
||||
uint8_t Connect_receive_RemoteCapabilityArgs[Connect_receive_RemoteCapabilityMaxArgs];
|
||||
|
||||
uint8_t Connect_receive_RemoteCapability( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num )
|
||||
{
|
||||
// Check which byte in the packet we are at
|
||||
switch ( (*pending_bytes)-- )
|
||||
{
|
||||
// Byte count always starts at 0xFFFF
|
||||
case 0xFFFF: // Device Id
|
||||
Connect_receive_RemoteCapabilityBuffer.id = byte;
|
||||
break;
|
||||
|
||||
case 0xFFFE: // Capability Index
|
||||
Connect_receive_RemoteCapabilityBuffer.capabilityIndex = byte;
|
||||
break;
|
||||
|
||||
case 0xFFFD: // State
|
||||
Connect_receive_RemoteCapabilityBuffer.state = byte;
|
||||
break;
|
||||
|
||||
case 0xFFFC: // StateType
|
||||
Connect_receive_RemoteCapabilityBuffer.stateType = byte;
|
||||
break;
|
||||
|
||||
case 0xFFFB: // Number of args
|
||||
Connect_receive_RemoteCapabilityBuffer.numArgs = byte;
|
||||
*pending_bytes = byte;
|
||||
break;
|
||||
|
||||
default: // Args (# defined by previous byte)
|
||||
Connect_receive_RemoteCapabilityArgs[
|
||||
Connect_receive_RemoteCapabilityBuffer.numArgs - *pending_bytes + 1
|
||||
] = byte;
|
||||
|
||||
// If entire packet has been fully received
|
||||
if ( *pending_bytes == 0 )
|
||||
{
|
||||
// Determine if this is the node to run the capability on
|
||||
// Conditions: Matches or broadcast (0xFF)
|
||||
if ( Connect_receive_RemoteCapabilityBuffer.id == 0xFF
|
||||
|| Connect_receive_RemoteCapabilityBuffer.id == Connect_id )
|
||||
{
|
||||
extern const Capability CapabilitiesList[]; // See generatedKeymap.h
|
||||
void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(
|
||||
CapabilitiesList[ Connect_receive_RemoteCapabilityBuffer.capabilityIndex ].func
|
||||
);
|
||||
capability(
|
||||
Connect_receive_RemoteCapabilityBuffer.state,
|
||||
Connect_receive_RemoteCapabilityBuffer.stateType,
|
||||
&Connect_receive_RemoteCapabilityArgs[2]
|
||||
);
|
||||
}
|
||||
|
||||
// If this is not the correct node, keep sending it in the same direction (doesn't matter if more nodes exist)
|
||||
// or if this is a broadcast
|
||||
if ( Connect_receive_RemoteCapabilityBuffer.id == 0xFF
|
||||
|| Connect_receive_RemoteCapabilityBuffer.id != Connect_id )
|
||||
{
|
||||
// Prepare outgoing packet
|
||||
Connect_receive_RemoteCapabilityBuffer.command = RemoteCapability;
|
||||
|
||||
// Send to the other UART (not the one receiving the packet from
|
||||
uint8_t uart_direction = uart_num == UART_Master ? UART_Slave : UART_Master;
|
||||
|
||||
// Lock Tx UART
|
||||
switch ( uart_direction )
|
||||
{
|
||||
case UART_Master: uart_lockTx( UART_Master ); break;
|
||||
case UART_Slave: uart_lockTx( UART_Slave ); break;
|
||||
}
|
||||
|
||||
// Send header
|
||||
uint8_t header[] = { 0x16, 0x01 };
|
||||
Connect_addBytes( header, sizeof( header ), uart_direction );
|
||||
|
||||
// Send Remote Capability and arguments
|
||||
Connect_addBytes( (uint8_t*)&Connect_receive_RemoteCapabilityBuffer, sizeof( RemoteCapabilityCommand ), uart_direction );
|
||||
Connect_addBytes( Connect_receive_RemoteCapabilityArgs, Connect_receive_RemoteCapabilityBuffer.numArgs, uart_direction );
|
||||
|
||||
// Unlock Tx UART
|
||||
switch ( uart_direction )
|
||||
{
|
||||
case UART_Master: uart_unlockTx( UART_Master ); break;
|
||||
case UART_Slave: uart_unlockTx( UART_Slave ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check whether the scan codes have finished sending
|
||||
return *pending_bytes == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
// Baud Rate
|
||||
// NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
|
||||
@ -802,52 +828,29 @@ void *Connect_receiveFunctions[] = {
|
||||
Connect_receive_IdReport,
|
||||
Connect_receive_ScanCode,
|
||||
Connect_receive_Animation,
|
||||
Connect_receive_RemoteCapability,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ----- Interrupt Functions -----
|
||||
|
||||
// Master / UART0 ISR
|
||||
void uart0_status_isr()
|
||||
{
|
||||
// Process Rx buffer
|
||||
uart_processRx( 0 );
|
||||
}
|
||||
|
||||
// Slave / UART1 ISR
|
||||
void uart1_status_isr()
|
||||
{
|
||||
// Process Rx buffer
|
||||
uart_processRx( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----- Functions -----
|
||||
|
||||
// Resets the state of the UART buffers and state variables
|
||||
void Connect_reset()
|
||||
{
|
||||
// Rx Status Variables
|
||||
uart0_rx_status = UARTStatus_Wait;
|
||||
uart1_rx_status = UARTStatus_Wait;
|
||||
uart0_rx_bytes_waiting = 0;
|
||||
uart1_rx_bytes_waiting = 0;
|
||||
uart0_lock = 0;
|
||||
uart1_lock = 0;
|
||||
// Reset Rx
|
||||
memset( (void*)uart_rx_status, 0, sizeof( UARTStatusRx ) * UART_Num_Interfaces );
|
||||
|
||||
// Tx Status Variables
|
||||
uart0_tx_status = UARTStatus_Ready;
|
||||
uart1_tx_status = UARTStatus_Ready;
|
||||
// Reset Tx
|
||||
memset( (void*)uart_tx_buf, 0, sizeof( UARTRingBuf ) * UART_Num_Interfaces );
|
||||
memset( (void*)uart_tx_status, 0, sizeof( UARTStatusTx ) * UART_Num_Interfaces );
|
||||
|
||||
// Ring Buffer Variables
|
||||
uart0_buffer_head = 0;
|
||||
uart0_buffer_tail = 0;
|
||||
uart0_buffer_items = 0;
|
||||
uart1_buffer_head = 0;
|
||||
uart1_buffer_tail = 0;
|
||||
uart1_buffer_items = 0;
|
||||
// Set Rx/Tx buffers as ready
|
||||
for ( uint8_t inter = 0; inter < UART_Num_Interfaces; inter++ )
|
||||
{
|
||||
uart_tx_status[ inter ].status = UARTStatus_Ready;
|
||||
uart_rx_buf[ inter ].last_read = UART_Buffer_Size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -868,8 +871,8 @@ void Connect_setup( uint8_t master )
|
||||
if ( Connect_master )
|
||||
Connect_id = 0; // 0x00 is always the master Id
|
||||
|
||||
// Master / UART0 setup
|
||||
// Slave / UART1 setup
|
||||
// UART0 setup
|
||||
// UART1 setup
|
||||
// Setup the the UART interface for keyboard data input
|
||||
SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
|
||||
SIM_SCGC4 |= SIM_SCGC4_UART1; // Disable clock gating
|
||||
@ -895,30 +898,81 @@ void Connect_setup( uint8_t master )
|
||||
UART0_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
|
||||
UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
|
||||
|
||||
// Number of bytes in FIFO before TX Interrupt
|
||||
UART0_TWFIFO = 1;
|
||||
UART1_TWFIFO = 1;
|
||||
// Only using Tx Fifos
|
||||
UART0_PFIFO = UART_PFIFO_TXFE;
|
||||
UART1_PFIFO = UART_PFIFO_TXFE;
|
||||
|
||||
// Number of bytes in FIFO before RX Interrupt
|
||||
UART0_RWFIFO = 1;
|
||||
UART1_RWFIFO = 1;
|
||||
// Setup DMA clocks
|
||||
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
|
||||
SIM_SCGC7 |= SIM_SCGC7_DMA;
|
||||
|
||||
// Enable TX and RX FIFOs
|
||||
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
|
||||
UART1_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
|
||||
// Start with channels disabled first
|
||||
DMAMUX0_CHCFG0 = 0;
|
||||
DMAMUX0_CHCFG1 = 0;
|
||||
|
||||
// Reciever Inversion Disabled, LSBF
|
||||
// UART_S2_RXINV UART_S2_MSBF
|
||||
UART0_S2 |= 0x00;
|
||||
UART1_S2 |= 0x00;
|
||||
// Configure DMA channels
|
||||
//DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK; // TODO What's this?
|
||||
DMA_TCD0_CSR = 0;
|
||||
DMA_TCD1_CSR = 0;
|
||||
|
||||
// Transmit Inversion Disabled
|
||||
// UART_C3_TXINV
|
||||
UART0_C3 |= 0x00;
|
||||
UART1_C3 |= 0x00;
|
||||
// Default control register
|
||||
DMA_CR = 0;
|
||||
|
||||
// DMA Priority
|
||||
DMA_DCHPRI0 = 0; // Ch 0, priority 0
|
||||
DMA_DCHPRI1 = 1; // ch 1, priority 1
|
||||
|
||||
// Clear error interrupts
|
||||
DMA_EEI = 0;
|
||||
|
||||
// Setup TCD
|
||||
DMA_TCD0_SADDR = (uint32_t*)&UART0_D;
|
||||
DMA_TCD1_SADDR = (uint32_t*)&UART1_D;
|
||||
DMA_TCD0_SOFF = 0;
|
||||
DMA_TCD1_SOFF = 0;
|
||||
|
||||
// No modulo, 8-bit transfer size
|
||||
DMA_TCD0_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);
|
||||
DMA_TCD1_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);
|
||||
|
||||
// One byte transferred at a time
|
||||
DMA_TCD0_NBYTES_MLNO = 1;
|
||||
DMA_TCD1_NBYTES_MLNO = 1;
|
||||
|
||||
// Source address does not change
|
||||
DMA_TCD0_SLAST = 0;
|
||||
DMA_TCD1_SLAST = 0;
|
||||
|
||||
// Destination buffer
|
||||
DMA_TCD0_DADDR = (uint32_t*)uart_rx_buf[0].buffer;
|
||||
DMA_TCD1_DADDR = (uint32_t*)uart_rx_buf[1].buffer;
|
||||
|
||||
// Incoming byte, increment by 1 in the rx buffer
|
||||
DMA_TCD0_DOFF = 1;
|
||||
DMA_TCD1_DOFF = 1;
|
||||
|
||||
// Single major loop, must be the same value
|
||||
DMA_TCD0_CITER_ELINKNO = UART_Buffer_Size;
|
||||
DMA_TCD1_CITER_ELINKNO = UART_Buffer_Size;
|
||||
DMA_TCD0_BITER_ELINKNO = UART_Buffer_Size;
|
||||
DMA_TCD1_BITER_ELINKNO = UART_Buffer_Size;
|
||||
|
||||
// Reset buffer when full
|
||||
DMA_TCD0_DLASTSGA = -( UART_Buffer_Size );
|
||||
DMA_TCD1_DLASTSGA = -( UART_Buffer_Size );
|
||||
|
||||
// Enable DMA channels
|
||||
DMA_ERQ |= DMA_ERQ_ERQ0 | DMA_ERQ_ERQ1;
|
||||
|
||||
// Setup DMA channel routing
|
||||
DMAMUX0_CHCFG0 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART0_RX;
|
||||
DMAMUX0_CHCFG1 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART1_RX;
|
||||
|
||||
// Enable DMA requests (requires Rx interrupts)
|
||||
UART0_C5 = UART_C5_RDMAS;
|
||||
UART1_C5 = UART_C5_RDMAS;
|
||||
|
||||
// TX Enabled, RX Enabled, RX Interrupt Enabled
|
||||
// UART_C2_TE UART_C2_RE UART_C2_RIE
|
||||
UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
|
||||
UART1_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
|
||||
|
||||
@ -934,6 +988,143 @@ void Connect_setup( uint8_t master )
|
||||
}
|
||||
|
||||
|
||||
#define DMA_BUF_POS( x, pos ) \
|
||||
case x: \
|
||||
pos = DMA_TCD##x##_CITER_ELINKNO; \
|
||||
break
|
||||
void Connect_rx_process( uint8_t uartNum )
|
||||
{
|
||||
// Determine current position to read until
|
||||
uint16_t bufpos = 0;
|
||||
switch ( uartNum )
|
||||
{
|
||||
DMA_BUF_POS( 0, bufpos );
|
||||
DMA_BUF_POS( 1, bufpos );
|
||||
}
|
||||
|
||||
// Process each of the new bytes
|
||||
// Even if we receive more bytes during processing, wait until the next check so we don't starve other tasks
|
||||
while ( bufpos != uart_rx_buf[ uartNum ].last_read )
|
||||
{
|
||||
// If the last_read byte is at the buffer edge, roll back to beginning
|
||||
if ( uart_rx_buf[ uartNum ].last_read == 0 )
|
||||
{
|
||||
uart_rx_buf[ uartNum ].last_read = UART_Buffer_Size;
|
||||
|
||||
// Check to see if we're at the boundary
|
||||
if ( bufpos == UART_Buffer_Size )
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the byte out of Rx DMA buffer
|
||||
uint8_t byte = uart_rx_buf[ uartNum ].buffer[ UART_Buffer_Size - uart_rx_buf[ uartNum ].last_read-- ];
|
||||
|
||||
if ( Connect_debug )
|
||||
{
|
||||
printHex( byte );
|
||||
print(" ");
|
||||
}
|
||||
|
||||
// Process UART byte
|
||||
switch ( uart_rx_status[ uartNum ].status )
|
||||
{
|
||||
// Every packet must start with a SYN / 0x16
|
||||
case UARTStatus_Wait:
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print(" Wait ");
|
||||
}
|
||||
uart_rx_status[ uartNum ].status = byte == 0x16 ? UARTStatus_SYN : UARTStatus_Wait;
|
||||
break;
|
||||
|
||||
// After a SYN, there must be a SOH / 0x01
|
||||
case UARTStatus_SYN:
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print(" SYN ");
|
||||
}
|
||||
uart_rx_status[ uartNum ].status = byte == 0x01 ? UARTStatus_SOH : UARTStatus_Wait;
|
||||
break;
|
||||
|
||||
// After a SOH the packet structure may diverge a bit
|
||||
// This is the packet type field (refer to the Command enum)
|
||||
// For very small packets (e.g. IdRequest) this is all that's required to take action
|
||||
case UARTStatus_SOH:
|
||||
{
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print(" SOH ");
|
||||
}
|
||||
|
||||
// Check if this is actually a reserved CMD 0x16 (Error condition)
|
||||
if ( byte == Command_SYN )
|
||||
{
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_SYN;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise process the command
|
||||
if ( byte < Command_TOP )
|
||||
{
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_Command;
|
||||
uart_rx_status[ uartNum ].command = byte;
|
||||
uart_rx_status[ uartNum ].bytes_waiting = 0xFFFF;
|
||||
}
|
||||
// Invalid packet type, ignore
|
||||
else
|
||||
{
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_Wait;
|
||||
}
|
||||
|
||||
// Check if this is a very short packet
|
||||
switch ( uart_rx_status[ uartNum ].command )
|
||||
{
|
||||
case IdRequest:
|
||||
Connect_receive_IdRequest( 0, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum );
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_Wait;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print(" ### ");
|
||||
printHex( uart_rx_status[ uartNum ].command );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// After the packet type has been deciphered do Command specific processing
|
||||
// Until the Command has received all the bytes it requires the UART buffer stays in this state
|
||||
case UARTStatus_Command:
|
||||
{
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print(" CMD ");
|
||||
}
|
||||
/* Call specific UARTConnect command receive function */
|
||||
uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart_rx_status[ uartNum ].command ]);
|
||||
if ( rcvFunc( byte, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum ) )
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_Wait;
|
||||
break;
|
||||
}
|
||||
|
||||
// Unknown status, should never get here
|
||||
default:
|
||||
erro_msg("Invalid UARTStatus...");
|
||||
uart_rx_status[ uartNum ].status = UARTStatus_Wait;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( Connect_debug )
|
||||
{
|
||||
print( NL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Scan for updates in the master/slave
|
||||
// - Interrupts will deal with most input functions
|
||||
// - Used to send queries
|
||||
@ -974,10 +1165,14 @@ void Connect_scan()
|
||||
{
|
||||
// Check if Tx Buffers are empty and the Tx Ring buffers have data to send
|
||||
// This happens if there was previously nothing to send
|
||||
if ( uart0_buffer_items > 0 && UART0_TCFIFO == 0 )
|
||||
if ( uart_tx_buf[ 0 ].items > 0 && UART0_TCFIFO == 0 )
|
||||
uart_fillTxFifo( 0 );
|
||||
if ( uart1_buffer_items > 0 && UART1_TCFIFO == 0 )
|
||||
if ( uart_tx_buf[ 1 ].items > 0 && UART1_TCFIFO == 0 )
|
||||
uart_fillTxFifo( 1 );
|
||||
|
||||
// Process Rx Buffers
|
||||
Connect_rx_process( 0 );
|
||||
Connect_rx_process( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1153,9 +1348,9 @@ void cliFunc_connectSts( char* args )
|
||||
print("/");
|
||||
printHex32( Connect_cableChecksMaster );
|
||||
print( NL "\tRx:\t");
|
||||
printHex( uart1_rx_status );
|
||||
printHex( uart_rx_status[UART_Master].status );
|
||||
print( NL "\tTx:\t");
|
||||
printHex( uart1_tx_status );
|
||||
printHex( uart_tx_status[UART_Master].status );
|
||||
print( NL "Slave <=" NL "\tStatus:\t");
|
||||
printHex( Connect_cableOkSlave );
|
||||
print( NL "\tFaults:\t");
|
||||
@ -1163,8 +1358,8 @@ void cliFunc_connectSts( char* args )
|
||||
print("/");
|
||||
printHex32( Connect_cableChecksSlave );
|
||||
print( NL "\tRx:\t");
|
||||
printHex( uart0_rx_status );
|
||||
printHex( uart_rx_status[UART_Slave].status );
|
||||
print( NL "\tTx:\t");
|
||||
printHex( uart0_tx_status );
|
||||
printHex( uart_tx_status[UART_Slave].status );
|
||||
}
|
||||
|
||||
|
@ -119,11 +119,14 @@ typedef struct AnimationCommand {
|
||||
// Remote Capability Command
|
||||
// Initiated by the master to trigger a capability on a given node
|
||||
// RemoteOutput is enabled while capability is activated
|
||||
// Set id to 255 if command should be sent in all directions
|
||||
typedef struct RemoteCapabilityCommand {
|
||||
Command command;
|
||||
uint8_t id;
|
||||
Capability capability;
|
||||
uint8_t numArgs;
|
||||
uint8_t capabilityIndex;
|
||||
uint8_t state;
|
||||
uint8_t stateType;
|
||||
uint8_t numArgs; // # of bytes, args may be larger than 1 byte
|
||||
uint8_t firstArg[0];
|
||||
} RemoteCapabilityCommand;
|
||||
|
||||
@ -162,4 +165,5 @@ void Connect_setup( uint8_t master );
|
||||
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 );
|
||||
|
||||
|
Reference in New Issue
Block a user