diff --git a/98-kiibohd.rules b/98-kiibohd.rules index 3dccd01..6986de4 100644 --- a/98-kiibohd.rules +++ b/98-kiibohd.rules @@ -4,7 +4,7 @@ ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", ENV{MTP_NO_PROBE}="1" SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", MODE:="0666" # Kiibohd Serial Interface -KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", SYMLINK+="kiibohd", MODE:="0666", +KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", SYMLINK+="kiibohd", MODE:="0666" KERNEL=="ttyACM*", ATTRS{idVendor}=="1c11", ATTRS{idProduct}=="b04d", SYMLINK+="kiibohd", MODE:="0666" KERNEL=="ttyACM*", ATTRS{idVendor}=="1c11", ATTRS{idProduct}=="f05c", SYMLINK+="kiibohd", MODE:="0666" diff --git a/Lib/mk20dx.h b/Lib/mk20dx.h index ae69dd4..ad7f0ef 100644 --- a/Lib/mk20dx.h +++ b/Lib/mk20dx.h @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modified by Jacob Alexander 2014-2015 + * Modified by Jacob Alexander 2014-2016 * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -1457,6 +1457,20 @@ typedef struct { #define I2C0_SLTH *(volatile uint8_t *)0x4006600A // I2C SCL Low Timeout Register High #define I2C0_SLTL *(volatile uint8_t *)0x4006600B // I2C SCL Low Timeout Register Low +#define I2C1_A1 *(volatile uint8_t *)0x40067000 // I2C Address Register 1 +#define I2C1_F *(volatile uint8_t *)0x40067001 // I2C Frequency Divider register +#define I2C1_C1 *(volatile uint8_t *)0x40067002 // I2C Control Register 1 +#define I2C1_S *(volatile uint8_t *)0x40067003 // I2C Status register +#define I2C1_D *(volatile uint8_t *)0x40067004 // I2C Data I/O register +#define I2C1_C2 *(volatile uint8_t *)0x40067005 // I2C Control Register 2 +#define I2C1_FLT *(volatile uint8_t *)0x40067006 // I2C Programmable Input Glitch Filter register +#define I2C1_RA *(volatile uint8_t *)0x40067007 // I2C Range Address register +#define I2C1_SMB *(volatile uint8_t *)0x40067008 // I2C SMBus Control and Status register +#define I2C1_A2 *(volatile uint8_t *)0x40067009 // I2C Address Register 2 +#define I2C1_SLTH *(volatile uint8_t *)0x4006700A // I2C SCL Low Timeout Register High +#define I2C1_SLTL *(volatile uint8_t *)0x4006700B // I2C SCL Low Timeout Register Low + + // Chapter 45: Universal Asynchronous Receiver/Transmitter (UART) #define UART0_BDH *(volatile uint8_t *)0x4006A000 // UART Baud Rate Registers: High #define UART0_BDL *(volatile uint8_t *)0x4006A001 // UART Baud Rate Registers: Low diff --git a/Macro/PixelMap/pixel.c b/Macro/PixelMap/pixel.c index 09243ae..4e77ea2 100644 --- a/Macro/PixelMap/pixel.c +++ b/Macro/PixelMap/pixel.c @@ -111,7 +111,7 @@ PixelBuf Pixel_Buffers[] = { // Pixel Mapping -#define Pixel_TotalPixels 128 // TODO Generate +#define Pixel_TotalPixels 127 // TODO Generate PixelElement Pixel_Mapping[] = { // Function Row (1-16) Pixel_RGBChannel(0,33,49), // 1 @@ -2593,7 +2593,8 @@ inline void Pixel_process() uint16_t ch; // Only update 50 positions at a time - for ( ch = Pixel_testPos; ch < Pixel_testPos + 50 && ch < Pixel_TotalChannels; ch++ ) + for ( ch = Pixel_testPos; ch < Pixel_TotalChannels; ch++ ) + //for ( ch = Pixel_testPos; ch < Pixel_testPos + 50 && ch < Pixel_TotalChannels; ch++ ) { // Toggle channel Pixel_channelToggle( ch ); diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 55c9553..6aa07e9 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -39,6 +39,9 @@ #include #endif +// KLL +#include + // Local Includes #include "output_com.h" @@ -117,15 +120,25 @@ uint8_t USBKeys_SentCLI = 0; // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana volatile uint8_t USBKeys_LEDs = 0; +// Currently pressed mouse buttons, bitmask, 0 represents no buttons pressed +volatile uint16_t USBMouse_Buttons = 0; + +// Relative mouse axis movement, stores pending movement +volatile uint16_t USBMouse_Relative_x = 0; +volatile uint16_t USBMouse_Relative_y = 0; + // Protocol setting from the host. // 0 - Boot Mode // 1 - NKRO Mode (Default, unless set by a BIOS or boot interface) -volatile uint8_t USBKeys_Protocol = 1; +volatile uint8_t USBKeys_Protocol = USBProtocol_define; // Indicate if USB should send update // OS only needs update if there has been a change in state USBKeyChangeState USBKeys_Changed = USBKeyChangeState_None; +// Indicate if USB should send update +USBMouseChangeState USBMouse_Changed = 0; + // the idle configuration, how often we send the report to the // host (ms * 4) even when it hasn't changed uint8_t USBKeys_Idle_Config = 125; @@ -511,6 +524,63 @@ void Output_flashMode_capability( uint8_t state, uint8_t stateType, uint8_t *arg Output_firmwareReload(); } +// Sends a mouse command over the USB Output buffer +// XXX This function *will* be changing in the future +// If you use it, be prepared that your .kll files will break in the future (post KLL 0.5) +// Argument #1: USB Mouse Button (16 bit) +// Argument #2: USB X Axis (16 bit) relative +// Argument #3: USB Y Axis (16 bit) relative +void Output_usbMouse_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("Output_usbMouse(mouseButton,relX,relY)"); + return; + } + + // Determine which mouse button was sent + // The USB spec defines up to a max of 0xFFFF buttons + // The usual are: + // 1 - Button 1 - (Primary) + // 2 - Button 2 - (Secondary) + // 3 - Button 3 - (Tertiary) + uint16_t mouse_button = *(uint16_t*)(&args[0]); + + // X/Y Relative Axis + uint16_t mouse_x = *(uint16_t*)(&args[2]); + uint16_t mouse_y = *(uint16_t*)(&args[4]); + + // Adjust for bit shift + uint16_t mouse_button_shift = mouse_button - 1; + + // Only send mouse button if in press or hold state + if ( stateType == 0x00 && state == 0x03 ) // Release state + { + // Release + if ( mouse_button ) + USBMouse_Buttons &= ~(1 << mouse_button_shift); + } + else + { + // Press or hold + if ( mouse_button ) + USBMouse_Buttons |= (1 << mouse_button_shift); + + if ( mouse_x ) + USBMouse_Relative_x = mouse_x; + if ( mouse_y ) + USBMouse_Relative_y = mouse_y; + } + + // Trigger updates + if ( mouse_button ) + USBMouse_Changed |= USBMouseChangeState_Buttons; + + if ( mouse_x || mouse_y ) + USBMouse_Changed |= USBMouseChangeState_Relative; +} + // ----- Functions ----- diff --git a/Scan/ISSILed/capabilities.kll b/Scan/ISSILed/capabilities.kll index fa39dec..01b39f0 100644 --- a/Scan/ISSILed/capabilities.kll +++ b/Scan/ISSILed/capabilities.kll @@ -1,6 +1,6 @@ Name = ISSILedCapabilities; Version = 0.2; -Author = "HaaTa (Jacob Alexander) 2015"; +Author = "HaaTa (Jacob Alexander) 2015-2016"; KLL = 0.3d; # Modified Date @@ -22,12 +22,35 @@ Date = 2015-10-09; # i.e. 23 then 144 ledControl => LED_control_capability( mode : 1, amount : 1, index : 2 ); + # Defines available to the ISSILed sub-module +# Driver Chip +# Selects which driver chip being used +# Set to 1 to enable +# Valid Chips +# 31FL3731 - http://www.issi.com/WW/pdf/31FL3731.pdf (31FL3731C has the same datasheet) +# 31FL3732 - http://www.issi.com/WW/pdf/31FL3732.pdf +ISSI_Chip_31FL3731 => ISSI_Chip_31FL3731_define; +ISSI_Chip_31FL3732 => ISSI_Chip_31FL3732_define; +ISSI_Chip_31FL3731 = 0; +ISSI_Chip_31FL3732 = 0; + +# Global Brightness +# 31FL3732 only +# 0 to 0xFF (255) +# See datasheet for current calculation, depends on Rext +ISSI_Global_Brightness => ISSI_Global_Brightness_define; +ISSI_Global_Brightness = 0xFF; + # Available ISSI Chips ISSI_Chips => ISSI_Chips_define; ISSI_Chips = 1; # 1 by default +# I2C Buses +ISSI_I2C_Buses => ISSI_I2C_Buses_define; +ISSI_I2C_Buses = 1; # 1 by default + # Default animation speed # Can be set from 0 to 63 (A) # Formula is TxA (T is approx 11ms) @@ -40,9 +63,9 @@ ISSI_Chips = 1; # 1 by default # For a 400 kHz I2C, with a single chip, updating all 144 channels, generally 30 fps is the max for continuous animations # Each additional chip consumes more bandwidth # 20 - 4.5 fps - Slow, but should always work without glitches -# See (http://www.issi.com/WW/pdf/31FL3731C.pdf) for details +# See chip datasheet (above) for details ISSI_AnimationSpeed => ISSI_AnimationSpeed_define; -ISSI_AnimationSpeed = 20; # 20 by default +ISSI_AnimationSpeed = 4; # 20 by default # LED Default Enable Mask # diff --git a/Scan/ISSILed/i2c.c b/Scan/ISSILed/i2c.c index f690e61..d234e3b 100644 --- a/Scan/ISSILed/i2c.c +++ b/Scan/ISSILed/i2c.c @@ -1,6 +1,6 @@ /* - * Copyright ( C ) 2014 Jan Rychter - * Modifications ( C ) 2015 Jacob Alexander + * Copyright (C) 2014 Jan Rychter + * Modifications (C) 2015-2016 Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files ( the "Software" ), to deal @@ -28,6 +28,7 @@ // Project Includes #include +#include // Local Includes #include "i2c.h" @@ -36,38 +37,78 @@ // ----- Variables ----- -volatile I2C_Channel i2c_channels[1]; +volatile I2C_Channel i2c_channels[ISSI_I2C_Buses_define]; + +uint32_t i2c_offset[] = { + 0x0, // Bus 0 + 0x1000, // Bus 1 +}; // ----- Functions ----- -inline void i2c_setup( ) +inline void i2c_setup() { - // Enable I2C internal clock - SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 + for ( uint8_t ch = 0; ch < ISSI_I2C_Buses_define; ch++ ) + { + volatile uint8_t *I2C_F = (uint8_t*)(&I2C0_F) + i2c_offset[ch]; + volatile uint8_t *I2C_FLT = (uint8_t*)(&I2C0_FLT) + i2c_offset[ch]; + volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; + volatile uint8_t *I2C_C2 = (uint8_t*)(&I2C0_C2) + i2c_offset[ch]; - // External pull-up resistor - PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); - PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + switch ( ch ) + { + case 0: + // Enable I2C internal clock + SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 - // SCL Frequency Divider - // 1.8 MBaud ( likely higher than spec ) - // 0x82 -> 36 MHz / (4 * 3) = 2.25 MBaud - // 0x80 => mul(4) - // 0x05 => ICL(5) - I2C0_F = 0x84; - I2C0_FLT = 4; - I2C0_C1 = I2C_C1_IICEN; - I2C0_C2 = I2C_C2_HDRS; // High drive select + // External pull-up resistor + PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); - // Enable I2C Interrupt - NVIC_ENABLE_IRQ( IRQ_I2C0 ); + break; + + case 1: + // Enable I2C internal clock + SIM_SCGC4 |= SIM_SCGC4_I2C1; // Bus 1 + + // External pull-up resistor + PORTC_PCR10 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + PORTC_PCR11 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); + + break; + } + + // SCL Frequency Divider + // 1.8 MBaud ( likely higher than spec ) + // 0x82 -> 36 MHz / (4 * 3) = 2.25 MBaud + // 0x80 => mul(4) + // 0x05 => ICL(5) + *I2C_F = 0x84; + *I2C_FLT = 4; + *I2C_C1 = I2C_C1_IICEN; + *I2C_C2 = I2C_C2_HDRS; // High drive select + + switch ( ch ) + { + case 0: + // Enable I2C Interrupt + NVIC_ENABLE_IRQ( IRQ_I2C0 ); + break; + + case 1: + + // Enable I2C Interrupt + NVIC_ENABLE_IRQ( IRQ_I2C1 ); + break; + } + } } -uint8_t i2c_busy() +uint8_t i2c_busy( uint8_t ch ) { - volatile I2C_Channel *channel = &( i2c_channels[0] ); + volatile I2C_Channel *channel = &( i2c_channels[ch] ); if ( channel->status == I2C_BUSY ) { return 1; @@ -76,19 +117,35 @@ uint8_t i2c_busy() return 0; } +uint8_t i2c_any_busy() +{ + for ( uint8_t ch = 0; ch < ISSI_I2C_Buses_define; ch++ ) + { + if ( i2c_busy( ch ) ) + return 1; + } + return 0; +} + // These are here for readability and correspond to bit 0 of the address byte. #define I2C_WRITING 0 #define I2C_READING 1 int32_t i2c_send_sequence( + uint8_t ch, uint16_t *sequence, uint32_t sequence_length, uint8_t *received_data, void ( *callback_fn )( void* ), void *user_data ) { - volatile I2C_Channel *channel = &( i2c_channels[0] ); + volatile I2C_Channel *channel = &( i2c_channels[ch] ); + + volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; + volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch]; + volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch]; + int32_t result = 0; uint8_t status; @@ -118,13 +175,13 @@ int32_t i2c_send_sequence( // reads_ahead does not need to be initialized // Acknowledge the interrupt request, just in case - I2C0_S |= I2C_S_IICIF; - I2C0_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE ); + *I2C_S |= I2C_S_IICIF; + *I2C_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE ); // Generate a start condition and prepare for transmitting. - I2C0_C1 |= ( I2C_C1_MST | I2C_C1_TX ); + *I2C_C1 |= ( I2C_C1_MST | I2C_C1_TX ); - status = I2C0_S; + status = *I2C_S; if ( status & I2C_S_ARBL ) { warn_print("Arbitration lost"); @@ -133,34 +190,42 @@ int32_t i2c_send_sequence( } // Write the first (address) byte. - I2C0_D = *channel->sequence++; + *I2C_D = *channel->sequence++; // Everything is OK. return result; i2c_send_sequence_cleanup: - I2C0_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX ); + *I2C_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX ); channel->status = I2C_ERROR; return result; } -void i2c0_isr() +void i2c_isr( uint8_t ch ) { - volatile I2C_Channel* channel = &i2c_channels[0]; + volatile I2C_Channel* channel = &i2c_channels[ch]; + + volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; + volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch]; + volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch]; + uint8_t element; uint8_t status; - status = I2C0_S; + status = *I2C_S; // Acknowledge the interrupt request - I2C0_S |= I2C_S_IICIF; + *I2C_S |= I2C_S_IICIF; // Arbitration problem if ( status & I2C_S_ARBL ) { - warn_print("Arbitration error"); - I2C0_S |= I2C_S_ARBL; + warn_msg("Arbitration error. Bus: "); + printHex( ch ); + print(NL); + + *I2C_S |= I2C_S_ARBL; goto i2c_isr_error; } @@ -174,17 +239,17 @@ void i2c0_isr() // switch to TX mode, either to generate a repeated start condition, or to avoid triggering another I2C read // when reading the contents of the data register. case 0: - I2C0_C1 |= I2C_C1_TX; + *I2C_C1 |= I2C_C1_TX; // Perform the final data register read now that it's safe to do so. - *channel->received_data++ = I2C0_D; + *channel->received_data++ = *I2C_D; // Do we have a repeated start? if ( ( channel->sequence < channel->sequence_end ) && ( *channel->sequence == I2C_RESTART ) ) { // Generate a repeated start condition. - I2C0_C1 |= I2C_C1_RSTA; + *I2C_C1 |= I2C_C1_RSTA; // A restart is processed immediately, so we need to get a new element from our sequence. This is safe, because // a sequence cannot end with a RESTART: there has to be something after it. Note that the only thing that can @@ -192,7 +257,7 @@ void i2c0_isr() channel->txrx = I2C_WRITING; channel->sequence++; element = *channel->sequence; - I2C0_D = element; + *I2C_D = element; } else { @@ -202,12 +267,12 @@ void i2c0_isr() case 1: // do not ACK the final read - I2C0_C1 |= I2C_C1_TXAK; - *channel->received_data++ = I2C0_D; + *I2C_C1 |= I2C_C1_TXAK; + *channel->received_data++ = *I2C_D; break; default: - *channel->received_data++ = I2C0_D; + *channel->received_data++ = *I2C_D; break; } @@ -234,7 +299,7 @@ void i2c0_isr() // Do we have a restart? If so, generate repeated start and make sure TX is on. if ( element == I2C_RESTART ) { - I2C0_C1 |= I2C_C1_RSTA | I2C_C1_TX; + *I2C_C1 |= I2C_C1_RSTA | I2C_C1_TX; // A restart is processed immediately, so we need to get a new element from our sequence. // This is safe, because a sequence cannot end with a RESTART: there has to be something after it. @@ -242,7 +307,7 @@ void i2c0_isr() element = *channel->sequence; // Note that the only thing that can come after a restart is a write. - I2C0_D = element; + *I2C_D = element; } else { @@ -260,29 +325,29 @@ void i2c0_isr() } // Switch to RX mode. - I2C0_C1 &= ~I2C_C1_TX; + *I2C_C1 &= ~I2C_C1_TX; // do not ACK the final read if ( channel->reads_ahead == 1 ) { - I2C0_C1 |= I2C_C1_TXAK; + *I2C_C1 |= I2C_C1_TXAK; } // ACK all but the final read else { - I2C0_C1 &= ~( I2C_C1_TXAK ); + *I2C_C1 &= ~( I2C_C1_TXAK ); } // Dummy read comes first, note that this is not valid data! // This only triggers a read, actual data will come in the next interrupt call and overwrite this. // This is why we do not increment the received_data pointer. - *channel->received_data = I2C0_D; + *channel->received_data = *I2C_D; channel->reads_ahead--; } // Not a restart, not a read, must be a write. else { - I2C0_D = element; + *I2C_D = element; } } } @@ -292,13 +357,14 @@ void i2c0_isr() i2c_isr_stop: // Generate STOP ( set MST=0 ), switch to RX mode, and disable further interrupts. - I2C0_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE | I2C_C1_TXAK ); + *I2C_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE | I2C_C1_TXAK ); channel->status = I2C_AVAILABLE; // Call the user-supplied callback function upon successful completion (if it exists). if ( channel->callback_fn ) { // Delay 10 microseconds before starting linked function + // TODO, is this chip dependent? -HaaTa delayMicroseconds(10); ( *channel->callback_fn )( channel->user_data ); } @@ -306,8 +372,18 @@ i2c_isr_stop: i2c_isr_error: // Generate STOP and disable further interrupts. - I2C0_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE ); + *I2C_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE ); channel->status = I2C_ERROR; return; } +void i2c0_isr() +{ + i2c_isr( 0 ); +} + +void i2c1_isr() +{ + i2c_isr( 1 ); +} + diff --git a/Scan/ISSILed/i2c.h b/Scan/ISSILed/i2c.h index 1a0ff07..aa27d00 100644 --- a/Scan/ISSILed/i2c.h +++ b/Scan/ISSILed/i2c.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 Jan Rychter - * Modifications (C) 2015 Jacob Alexander + * Modifications (C) 2015-2016 Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,16 +58,10 @@ typedef struct { -// ----- Variables ----- - -extern volatile I2C_Channel i2c_channels[1]; - - - // ----- Functions ----- /* - * I2C Module Setup - Channel 0 only + * I2C Module Setup */ void i2c_setup(); @@ -95,6 +89,7 @@ void i2c_setup(); */ int32_t i2c_send_sequence( + uint8_t ch, uint16_t *sequence, uint32_t sequence_length, uint8_t *received_data, @@ -105,11 +100,12 @@ int32_t i2c_send_sequence( /* * Convenience macros */ -#define i2c_send(seq, seq_len) i2c_send_sequence( seq, seq_len, 0, 0, 0 ) -#define i2c_read(seq, seq_len, rec) i2c_send_sequence( seq, seq_len, rec, 0, 0 ) +#define i2c_send(ch, seq, seq_len) i2c_send_sequence( ch, seq, seq_len, 0, 0, 0 ) +#define i2c_read(ch, seq, seq_len, rec) i2c_send_sequence( ch, seq, seq_len, rec, 0, 0 ) /* * Check if busy */ -uint8_t i2c_busy(); +uint8_t i2c_busy( uint8_t ch ); +uint8_t i2c_any_busy(); diff --git a/Scan/ISSILed/led_scan.c b/Scan/ISSILed/led_scan.c index ef7b716..69de687 100644 --- a/Scan/ISSILed/led_scan.c +++ b/Scan/ISSILed/led_scan.c @@ -52,34 +52,65 @@ // ISSI Addresses // IS31FL3731 (max 4 channels per bus) -#if 1 +#if ISSI_Chip_31FL3731_define == 1 #define ISSI_Ch1 0xE8 #define ISSI_Ch2 0xEA #define ISSI_Ch3 0xEC #define ISSI_Ch4 0xEE // IS31FL3732 (max 16 channels per bus) +#elif ISSI_Chip_31FL3732_define == 1 +#define ISSI_Ch1 0xA0 +#define ISSI_Ch2 0xA2 +#define ISSI_Ch3 0xA4 +#define ISSI_Ch4 0xA6 +#define ISSI_Ch5 0xA8 +#define ISSI_Ch6 0xAA +#define ISSI_Ch7 0xAC +#define ISSI_Ch8 0xAE +#define ISSI_Ch9 0xB0 +#define ISSI_Ch10 0xB2 +#define ISSI_Ch11 0xB4 +#define ISSI_Ch12 0xB6 +#define ISSI_Ch13 0xB8 +#define ISSI_Ch14 0xBA +#define ISSI_Ch15 0xBC +#define ISSI_Ch16 0xBE + #else -#define ISSI_Ch1 0xB0 -#define ISSI_Ch2 0xB2 -#define ISSI_Ch3 0xB4 -#define ISSI_Ch4 0xB6 +#error "ISSI Driver Chip not defined in Scan defaultMap.kll..." #endif +// TODO Generate in KLL +#define LED_MapCh1_Bus_define 0x0 +#define LED_MapCh1_Addr_define ISSI_Ch1 +#define LED_MapCh2_Bus_define 0x0 +#define LED_MapCh2_Addr_define ISSI_Ch2 +#define LED_MapCh3_Bus_define 0x1 +#define LED_MapCh3_Addr_define ISSI_Ch1 +#define LED_MapCh4_Bus_define 0x1 +#define LED_MapCh4_Addr_define ISSI_Ch2 + // ----- Macros ----- +#define LED_ChannelMapDefine(ch) \ + { \ + LED_MapCh##ch##_Bus_define, /* I2C bus number */ \ + LED_MapCh##ch##_Addr_define, /* I2C address */ \ + } + #define LED_MaskDefine(ch) \ { \ - ISSI_Ch##ch, /* I2C address */ \ + LED_MapCh##ch##_Addr_define, /* I2C address */ \ 0x00, /* Starting register address */ \ { ISSILedMask##ch##_define }, \ } #define LED_BrightnessDefine(ch) \ { \ - ISSI_Ch##ch, /* I2C address */ \ + LED_MapCh##ch##_Addr_define, /* I2C address */ \ 0x24, /* Starting register address */ \ { ISSILedBrightness##ch##_define }, \ } @@ -100,6 +131,11 @@ typedef struct LED_EnableBuffer { uint16_t buffer[LED_EnableBufferLength]; } LED_EnableBuffer; +typedef struct LED_ChannelMap { + uint8_t bus; + uint8_t addr; +} LED_ChannelMap; + // ----- Function Declarations ----- @@ -129,7 +165,7 @@ CLIDict_Def( ledCLIDict, "ISSI LED Module Commands" ) = { }; -volatile LED_Buffer LED_pageBuffer[ ISSI_Chips_define ]; +volatile LED_Buffer LED_pageBuffer[ISSI_Chips_define]; uint8_t LED_FrameBuffersReady; // Starts at maximum, reset on interrupt from ISSI volatile uint8_t LED_FrameBufferReset; // INTB interrupt received, reset available buffer count when ready @@ -138,6 +174,21 @@ volatile uint8_t LED_FrameBufferReset; // INTB interrupt received, reset availa uint8_t LED_displayFPS; // Display fps to cli +// TODO - Autogenerate for each keyboard +// ISSI Driver Channel to Bus:Address mapping +const LED_ChannelMap LED_ChannelMapping[ISSI_Chips_define] = { + LED_ChannelMapDefine( 1 ), +#if ISSI_Chips_define >= 2 + LED_ChannelMapDefine( 2 ), +#endif +#if ISSI_Chips_define >= 3 + LED_ChannelMapDefine( 3 ), +#endif +#if ISSI_Chips_define >= 4 + LED_ChannelMapDefine( 4 ), +#endif +}; + // Enable mask and default brightness for ISSI chip channel const LED_EnableBuffer LED_ledEnableMask[ISSI_Chips_define] = { LED_MaskDefine( 1 ), @@ -192,7 +243,7 @@ void portb_isr() // ----- Functions ----- -void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) +void LED_zeroPages( uint8_t bus, uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg ) { // Clear Page // Max length of a page + chip id + reg start @@ -207,20 +258,20 @@ void LED_zeroPages( uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t s uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Zero out page - while ( i2c_send( clearPage, 2 + endReg - startReg ) == -1 ) + while ( i2c_send( bus, clearPage, 2 + endReg - startReg ) == -1 ) delay(1); } // Wait until finished zero'ing - while ( i2c_busy() ) + while ( i2c_busy( bus ) ) delay(1); } -void LED_sendPage( uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page ) +void LED_sendPage( uint8_t bus, uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page ) { /* info_msg("I2C Send Page Addr: "); @@ -236,11 +287,11 @@ void LED_sendPage( uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page ) uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Write page to I2C Tx Buffer - while ( i2c_send( buffer, len ) == -1 ) + while ( i2c_send( bus, buffer, len ) == -1 ) delay(1); } @@ -253,9 +304,10 @@ void LED_syncReg( uint8_t reg, uint8_t val, uint8_t page ) // Setup each of the pages for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - pageSetup[0] = LED_pageBuffer[ ch ].i2c_addr; + pageSetup[0] = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); } @@ -265,20 +317,21 @@ void LED_syncReg( uint8_t reg, uint8_t val, uint8_t page ) // Write to all the registers for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - writeData[0] = LED_pageBuffer[ ch ].i2c_addr; + writeData[0] = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; // Delay very little to help with synchronization - while ( i2c_send( writeData, sizeof( writeData ) / 2 ) == -1 ) + while ( i2c_send( bus, writeData, sizeof( writeData ) / 2 ) == -1 ) delayMicroseconds(10); } // Delay until written - while ( i2c_busy() ) + while ( i2c_any_busy() ) delay(1); } // Write address -void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) +void LED_writeReg( uint8_t bus, uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) { // Page Setup uint16_t pageSetup[] = { addr, 0xFD, page }; @@ -287,37 +340,37 @@ void LED_writeReg( uint8_t addr, uint8_t reg, uint8_t val, uint8_t page ) uint16_t writeData[] = { addr, reg, val }; // Setup page - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Write register - while ( i2c_send( writeData, sizeof( writeData ) / 2 ) == -1 ) + while ( i2c_send( bus, writeData, sizeof( writeData ) / 2 ) == -1 ) delay(1); // Delay until written - while ( i2c_busy() ) + while ( i2c_busy( bus ) ) delay(1); } // Read address // TODO Not working? -uint8_t LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) +uint8_t LED_readReg( uint8_t bus, uint8_t addr, uint8_t reg, uint8_t page ) { // Software shutdown must be enabled to read registers - LED_writeReg( addr, 0x0A, 0x00, 0x0B ); + LED_writeReg( bus, addr, 0x0A, 0x00, 0x0B ); // Page Setup uint16_t pageSetup[] = { addr, 0xFD, page }; // Setup page - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); // Register Setup uint16_t regSetup[] = { addr, reg }; // Configure register - while ( i2c_send( regSetup, sizeof( regSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, regSetup, sizeof( regSetup ) / 2 ) == -1 ) delay(1); // Register Read Command @@ -325,11 +378,11 @@ uint8_t LED_readReg( uint8_t addr, uint8_t reg, uint8_t page ) uint8_t recv_data; // Request single register byte - while ( i2c_read( regReadCmd, sizeof( regReadCmd ) / 2, &recv_data ) == -1 ) + while ( i2c_read( bus, regReadCmd, sizeof( regReadCmd ) / 2, &recv_data ) == -1 ) delay(1); // Disable software shutdown - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + LED_writeReg( bus, addr, 0x0A, 0x01, 0x0B ); return recv_data; } @@ -352,13 +405,15 @@ void LED_reset() // Enable LEDs based upon mask for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_zeroPages( addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + LED_zeroPages( bus, addr, 0x00, 8, 0x00, 0xB4 ); // LED Registers // For each page for ( uint8_t pg = 0; pg < LED_FrameBuffersMax * 2; pg++ ) { LED_sendPage( + bus, addr, (uint16_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ) / 2, @@ -367,20 +422,33 @@ void LED_reset() } } + // Set global brightness control +#if ISSI_Chip_31FL3732_define == 1 + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + // See, 31FL3732 datasheet for details on calculation + // Depends on Rext + LED_writeReg( bus, addr, 0x04, ISSI_Global_Brightness_define, 0x0B ); + } +#endif + // Setup ISSI auto frame play, but do not start yet for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; // CNS 1 loop, FNS 4 frames - 0x14 - LED_writeReg( addr, 0x02, 0x14, 0x0B ); + LED_writeReg( bus, addr, 0x02, 0x14, 0x0B ); // Default refresh speed - TxA // T is typically 11ms // A is 1 to 64 (where 0 is 64) - LED_writeReg( addr, 0x03, ISSI_AnimationSpeed_define, 0x0B ); + LED_writeReg( bus, addr, 0x03, ISSI_AnimationSpeed_define, 0x0B ); // Set MODE to Auto Frame Play - LED_writeReg( addr, 0x00, 0x08, 0x0B ); + LED_writeReg( bus, addr, 0x00, 0x08, 0x0B ); } // Do not disable software shutdown of ISSI chip unless current is high enough @@ -391,8 +459,9 @@ void LED_reset() // Disable Software shutdown of ISSI chip for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + LED_writeReg( bus, addr, 0x0A, 0x01, 0x0B ); } } } @@ -407,18 +476,18 @@ inline void LED_setup() i2c_setup(); // Setup LED_pageBuffer addresses and brightness section - LED_pageBuffer[0].i2c_addr = ISSI_Ch1; + LED_pageBuffer[0].i2c_addr = LED_MapCh1_Addr_define; LED_pageBuffer[0].reg_addr = 0x24; #if ISSI_Chips_define >= 2 - LED_pageBuffer[1].i2c_addr = ISSI_Ch2; + LED_pageBuffer[1].i2c_addr = LED_MapCh2_Addr_define; LED_pageBuffer[1].reg_addr = 0x24; #endif #if ISSI_Chips_define >= 3 - LED_pageBuffer[2].i2c_addr = ISSI_Ch3; + LED_pageBuffer[2].i2c_addr = LED_MapCh3_Addr_define; LED_pageBuffer[2].reg_addr = 0x24; #endif #if ISSI_Chips_define >= 4 - LED_pageBuffer[3].i2c_addr = ISSI_Ch4; + LED_pageBuffer[3].i2c_addr = LED_MapCh4_Addr_define; LED_pageBuffer[3].reg_addr = 0x24; #endif @@ -431,8 +500,9 @@ inline void LED_setup() // This needs to be done before disabling the hardware shutdown (or the leds will do undefined things) for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_zeroPages( addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + LED_zeroPages( bus, addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers } // Disable Hardware shutdown of ISSI chip (pull high) @@ -455,6 +525,7 @@ inline void LED_setup() // LED Linked Send // Call-back for i2c write when updating led display +// TODO Optimize linked send for multiple i2c buses uint8_t LED_chipSend; void LED_linkedSend() { @@ -476,6 +547,9 @@ void LED_linkedSend() // Update ISSI Frame State Pixel_FrameState = FrameState_Sending; + // Lookup bus number + uint8_t bus = LED_ChannelMapping[ LED_chipSend ].bus; + // Debug /* dbug_msg("Linked Send: chip("); @@ -500,6 +574,7 @@ void LED_linkedSend() // Send, and recursively call this function when finished while ( i2c_send_sequence( + bus, (uint16_t*)&LED_pageBuffer[ LED_chipSend ], sizeof( LED_Buffer ) / 2, 0, @@ -527,8 +602,9 @@ inline void LED_scan() // Enable Software shutdown of ISSI chip for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x00, 0x0B ); + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + LED_writeReg( bus, addr, 0x0A, 0x00, 0x0B ); } } else @@ -536,8 +612,9 @@ inline void LED_scan() // Disable Software shutdown of ISSI chip for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; - LED_writeReg( addr, 0x0A, 0x01, 0x0B ); + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; + LED_writeReg( bus, addr, 0x0A, 0x01, 0x0B ); } } @@ -602,11 +679,12 @@ inline void LED_scan() for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { // Page Setup - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; uint16_t pageSetup[] = { addr, 0xFD, LED_FrameBufferPage }; // Send each update - while ( i2c_send( pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) + while ( i2c_send( bus, pageSetup, sizeof( pageSetup ) / 2 ) == -1 ) delay(1); } @@ -699,7 +777,12 @@ void LED_control( LedControl *control ) // TODO Support multiple frames for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - LED_sendPage( LED_pageBuffer[ ch ].i2c_addr, (uint16_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ) / 2, 0 ); + LED_sendPage( + LED_ChannelMapping[ ch ].bus, + LED_ChannelMapping[ ch ].addr, + (uint16_t*)&LED_pageBuffer[ ch ], + sizeof( LED_Buffer ) / 2, 0 + ); } } @@ -806,6 +889,7 @@ void LED_control_capability( uint8_t state, uint8_t stateType, uint8_t *args ) // TODO Currently not working correctly void cliFunc_i2cSend( char* args ) { + /* char* curArgs; char* arg1Ptr; char* arg2Ptr = args; @@ -850,6 +934,7 @@ void cliFunc_i2cSend( char* args ) print( NL ); i2c_send( buffer, bufferLen ); + */ } /* @@ -917,8 +1002,11 @@ void cliFunc_ledReset( char* args ) for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - LED_zeroPages( LED_ledEnableMask[ ch ].i2c_addr, 0x0B, 1, 0x00, 0x0C ); // Control Registers - + LED_zeroPages( + LED_ChannelMapping[ ch ].bus, + LED_ChannelMapping[ ch ].addr, + 0x0B, 1, 0x00, 0x0C + ); // Control Registers } // Clear buffers @@ -928,6 +1016,18 @@ void cliFunc_ledReset( char* args ) } LED_reset(); + + // TODO Remove me + /* + for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) + { + LED_sendPage( + LED_ChannelMapping[ ch ].bus, + LED_ChannelMapping[ ch ].addr, + 0x0B, 1, 0x00, 0x0C + ); // Control Registers + } + */ } void cliFunc_ledSpeed( char* args ) @@ -969,12 +1069,13 @@ void cliFunc_ledSpeed( char* args ) // Set refresh speed per ISSI chip for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; // Default refresh speed - TxA // T is typically 11ms // A is 1 to 64 (where 0 is 64) - LED_writeReg( addr, 0x03, speed, 0x0B ); + LED_writeReg( bus, addr, 0x03, speed, 0x0B ); } } @@ -1039,8 +1140,10 @@ void cliFunc_ledNFrame( char* args ) // XXX It is more efficient to only send positions that are used // However, this may actually have more addressing overhead // For simplicity, just sending the full 144 positions per ISSI chip - uint8_t addr = LED_pageBuffer[ ch ].i2c_addr; + uint8_t addr = LED_ChannelMapping[ ch ].addr; + uint8_t bus = LED_ChannelMapping[ ch ].bus; LED_sendPage( + bus, addr, (uint16_t*)&LED_pageBuffer[ ch ], sizeof( LED_Buffer ) / 2, diff --git a/Scan/KType/defaultMap.kll b/Scan/KType/defaultMap.kll index 2f95ca6..becd7d6 100644 --- a/Scan/KType/defaultMap.kll +++ b/Scan/KType/defaultMap.kll @@ -1,6 +1,6 @@ Name = KType; -Version = 0.1; -Author = "HaaTa (Jacob Alexander) 2015"; +Version = 0.2; +Author = "HaaTa (Jacob Alexander) 2015-2016"; KLL = 0.3c; # Modified Date @@ -115,11 +115,20 @@ S0x5D : U"Down"; S0x5E : U"Right"; +# Driver Chip +ISSI_Chip_31FL3732 = 1; + +# Global Brightness +ISSI_Global_Brightness = 0xFF; # 0xFF by default (max) + # Available ISSI Chips -ISSI_Chips = 4; # 1 by default +ISSI_Chips = 4; # 2 by default + +# I2C Buses +ISSI_I2C_Buses = 2; # 1 by default # Default animation speed -ISSI_AnimationSpeed = 14; # 20 by default +ISSI_AnimationSpeed = 6; # 20 by default # LED Default Enable Mask # @@ -175,19 +184,6 @@ ISSILedMask4 = " 0xFF, 0xFF, /* C9-1 -> C9-16 */ "; -# Disabled for now -#ISSILedMask4 = " -# 0x00, 0x00, /* C1-1 -> C1-16 */ -# 0x00, 0x00, /* C2-1 -> C2-16 */ -# 0x00, 0x00, /* C3-1 -> C3-16 */ -# 0x00, 0x00, /* C4-1 -> C4-16 */ -# 0x00, 0x00, /* C5-1 -> C5-16 */ -# 0x00, 0x00, /* C6-1 -> C6-16 */ -# 0x00, 0x00, /* C7-1 -> C7-16 */ -# 0x00, 0x00, /* C8-1 -> C8-16 */ -# 0x00, 0x00, /* C9-1 -> C9-16 */ -#"; - ISSILedBrightness1 = " 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* C1-1 -> C1-16 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* C2-1 -> C2-16 */ diff --git a/Scan/KType/matrix.h b/Scan/KType/matrix.h index 8835d5e..c408ca4 100644 --- a/Scan/KType/matrix.h +++ b/Scan/KType/matrix.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 by Jacob Alexander +/* Copyright (C) 2014-2016 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,8 +49,8 @@ // PTC1..5 // Define Rows (Sense) and Columns (Strobes) -GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(C,10), gpio(C,11), gpio(D,0) }; -GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2), gpio(C,3), gpio(C,4), gpio(C,5) }; +GPIO_Pin Matrix_cols[] = { gpio(B,2), gpio(B,3), gpio(B,18), gpio(B,19), gpio(C,0), gpio(C,8), gpio(C,9), gpio(D,0), gpio(D,1), gpio(D,4) }; +GPIO_Pin Matrix_rows[] = { gpio(D,5), gpio(D,6), gpio(D,7), gpio(C,1), gpio(C,2), gpio(C,3), gpio(C,4), gpio(C,5), gpio(C,6), gpio(C,7) }; // Define type of scan matrix Config Matrix_type = Config_Pulldown; diff --git a/Scan/KType/scan_loop.c b/Scan/KType/scan_loop.c index 898c1fe..74b8689 100644 --- a/Scan/KType/scan_loop.c +++ b/Scan/KType/scan_loop.c @@ -82,7 +82,7 @@ inline uint8_t Scan_loop() Port_scan(); // Scan Matrix - Matrix_scan( Scan_scanCount++ ); + //Matrix_scan( Scan_scanCount++ ); // Process any interconnect commands Connect_scan(); diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index cbb0e76..e599dc1 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -409,7 +409,15 @@ void Matrix_scan( uint16_t scanNum ) case KeyState_Invalid: default: - erro_print("Matrix scan bug!! Report me!"); + erro_msg("Matrix scan bug!! Report me! - "); + printHex( state->prevState ); + print(" Col: "); + printHex( strobe ); + print(" Row: "); + printHex( sense ); + print(" Key: "); + printHex( key ); + print( NL ); break; } diff --git a/Scan/PortSwap/capabilities.kll b/Scan/PortSwap/capabilities.kll index 347f39b..a4adf20 100644 --- a/Scan/PortSwap/capabilities.kll +++ b/Scan/PortSwap/capabilities.kll @@ -10,5 +10,8 @@ Date = 2015-10-23; portCross => Port_cross_capability(); # Capability to swap the USB port mapping -portSwap => Port_swap_capability(); +portSwapUSB => Port_usb_capability(); + +# Capability to swap the interconnect port mapping +portSwapInter => Port_uart_capability(); diff --git a/Scan/PortSwap/port_scan.c b/Scan/PortSwap/port_scan.c index cf5a69e..c3c7c41 100644 --- a/Scan/PortSwap/port_scan.c +++ b/Scan/PortSwap/port_scan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 by Jacob Alexander +/* Copyright (C) 2015-2016 by Jacob Alexander * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,7 +52,8 @@ // CLI Functions void cliFunc_portCross( char* args ); -void cliFunc_portSwap ( char* args ); +void cliFunc_portUART ( char* args ); +void cliFunc_portUSB ( char* args ); @@ -62,11 +63,13 @@ uint32_t Port_lastcheck_ms; // Scan Module command dictionary CLIDict_Entry( portCross, "Cross interconnect pins." ); -CLIDict_Entry( portSwap, "Swap USB ports manually, forces usb and interconnect to re-negotiate if necessary." ); +CLIDict_Entry( portUSB, "Swap USB ports manually, forces usb and interconnect to re-negotiate if necessary." ); +CLIDict_Entry( portUART, "Swap interconnect ports." ); CLIDict_Def( portCLIDict, "Port Swap Module Commands" ) = { CLIDict_Item( portCross ), - CLIDict_Item( portSwap ), + CLIDict_Item( portUART ), + CLIDict_Item( portUSB ), { 0, 0, 0 } // Null entry for dictionary end }; @@ -74,18 +77,26 @@ CLIDict_Def( portCLIDict, "Port Swap Module Commands" ) = { // ----- Functions ----- -void Port_swap() +void Port_usb_swap() { info_print("USB Port Swap"); - // PTA13 - USB Swap - GPIOA_PTOR |= (1<<13); + // PTA4 - USB Swap + GPIOA_PTOR |= (1<<4); // Re-initialize usb // Call usb_configured() to check if usb is ready usb_init(); } +void Port_uart_swap() +{ + info_print("Interconnect Line Swap"); + + // PTA13 - UART Swap + GPIOA_PTOR |= (1<<13); +} + void Port_cross() { info_print("Interconnect Line Cross"); @@ -103,13 +114,19 @@ inline void Port_setup() // Register Scan CLI dictionary CLI_registerDictionary( portCLIDict, portCLIDictName ); + // PTA4 - USB Swap + // Start, disabled + GPIOA_PDDR |= (1<<4); + PORTA_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + GPIOA_PCOR |= (1<<4); + // PTA12 - UART Tx/Rx cross-over // Start, disabled GPIOA_PDDR |= (1<<12); PORTA_PCR12 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); GPIOA_PCOR |= (1<<12); - // PTA13 - USB Swap + // PTA13 - UART Swap // Start, disabled GPIOA_PDDR |= (1<<13); PORTA_PCR13 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); @@ -136,7 +153,7 @@ inline uint8_t Port_scan() // USB not initialized, attempt to swap if ( !usb_configured() ) { - Port_swap(); + Port_usb_swap(); } } @@ -155,12 +172,12 @@ void Port_currentChange( unsigned int current ) // ----- Capabilities ----- -void Port_swap_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +void Port_uart_capability( uint8_t state, uint8_t stateType, uint8_t *args ) { // Display capability name if ( stateType == 0xFF && state == 0xFF ) { - print("Port_swap_capability()"); + print("Port_uart_capability()"); return; } @@ -169,7 +186,24 @@ void Port_swap_capability( uint8_t state, uint8_t stateType, uint8_t *args ) if ( state != 0x03 ) return; - Port_swap(); + Port_uart_swap(); +} + +void Port_usb_capability( uint8_t state, uint8_t stateType, uint8_t *args ) +{ + // Display capability name + if ( stateType == 0xFF && state == 0xFF ) + { + print("Port_usb_capability()"); + return; + } + + // Only only release + // TODO Analog + if ( state != 0x03 ) + return; + + Port_usb_swap(); } void Port_cross_capability( uint8_t state, uint8_t stateType, uint8_t *args ) @@ -193,10 +227,16 @@ void Port_cross_capability( uint8_t state, uint8_t stateType, uint8_t *args ) // ----- CLI Command Functions ----- -void cliFunc_portSwap( char* args ) +void cliFunc_portUART( char* args ) { print( NL ); - Port_swap(); + Port_uart_swap(); +} + +void cliFunc_portUSB( char* args ) +{ + print( NL ); + Port_usb_swap(); } void cliFunc_portCross( char* args ) diff --git a/Scan/UARTConnect/connect_scan.c b/Scan/UARTConnect/connect_scan.c index 4c56c3c..1b06379 100644 --- a/Scan/UARTConnect/connect_scan.c +++ b/Scan/UARTConnect/connect_scan.c @@ -1161,7 +1161,7 @@ void Connect_scan() } // Limit how often we do cable checks - //uint32_t time_compare = 0x007; // Used for debugging cables -HaaTa + //uint32_t time_compare = 0x007; // XXX Used for debugging cables -HaaTa uint32_t time_compare = 0x7FF; // Must be all 1's, 0x3FF is valid, 0x4FF is not uint32_t current_time = systick_millis_count; if ( Connect_lastCheck != current_time