diff options
31 files changed, 580 insertions, 233 deletions
| diff --git a/keyboards/crkbd/config.h b/keyboards/crkbd/config.h index c910d8f24..64fee7545 100644 --- a/keyboards/crkbd/config.h +++ b/keyboards/crkbd/config.h @@ -16,9 +16,16 @@ You should have received a copy of the GNU General Public License  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ -#ifndef CONFIG_H -#define CONFIG_H +#pragma once  #include "config_common.h" +#include <serial_config.h> -#endif +#ifdef USE_Link_Time_Optimization +  // LTO has issues with macros (action_get_macro) and "functions" (fn_actions), +  //  so just disable them +  #define NO_ACTION_MACRO +  #define NO_ACTION_FUNCTION + +  #define DISABLE_LEADER +#endif // USE_Link_Time_Optimization diff --git a/keyboards/crkbd/crkbd.h b/keyboards/crkbd/crkbd.h index 889bcb9ae..73f2a3f07 100644 --- a/keyboards/crkbd/crkbd.h +++ b/keyboards/crkbd/crkbd.h @@ -1,8 +1,5 @@ -#ifndef CRKBD_H -#define CRKBD_H +#pragma once  #ifdef KEYBOARD_crkbd_rev1    #include "rev1.h"  #endif - -#endif diff --git a/keyboards/crkbd/i2c.c b/keyboards/crkbd/i2c.c index 084c890c4..4bee5c639 100644 --- a/keyboards/crkbd/i2c.c +++ b/keyboards/crkbd/i2c.c @@ -34,7 +34,7 @@ void i2c_delay(void) {    // _delay_us(100);  } -// Setup twi to run at 100kHz +// Setup twi to run at 100kHz or 400kHz (see ./i2c.h SCL_CLOCK)  void i2c_master_init(void) {    // no prescaler    TWSR = 0; diff --git a/keyboards/crkbd/i2c.h b/keyboards/crkbd/i2c.h index c15b6bc50..710662c7a 100644 --- a/keyboards/crkbd/i2c.h +++ b/keyboards/crkbd/i2c.h @@ -1,5 +1,4 @@ -#ifndef I2C_H -#define I2C_H +#pragma once  #include <stdint.h> @@ -15,7 +14,7 @@  #define SLAVE_BUFFER_SIZE 0x10 -// i2c SCL clock frequency +// i2c SCL clock frequency 400kHz  #define SCL_CLOCK  400000L  extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; @@ -45,5 +44,3 @@ extern unsigned char i2c_readNak(void);  extern unsigned char i2c_read(unsigned char ack);  #define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); - -#endif diff --git a/keyboards/crkbd/keymaps/default/keymap.c b/keyboards/crkbd/keymaps/default/keymap.c index 87661d345..e92fbdebf 100644 --- a/keyboards/crkbd/keymaps/default/keymap.c +++ b/keyboards/crkbd/keymaps/default/keymap.c @@ -5,7 +5,6 @@    #include "split_util.h"  #endif  #ifdef SSD1306OLED -  #include "LUFA/Drivers/Peripheral/TWI.h"    #include "ssd1306.h"  #endif @@ -130,7 +129,6 @@ void matrix_init_user(void) {      #endif      //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h      #ifdef SSD1306OLED -        TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 800000));          iota_gfx_init(!has_usb());   // turns on the display      #endif  } diff --git a/keyboards/crkbd/keymaps/default/rules.mk b/keyboards/crkbd/keymaps/default/rules.mk index 6570e2f5c..0edf1181f 100644 --- a/keyboards/crkbd/keymaps/default/rules.mk +++ b/keyboards/crkbd/keymaps/default/rules.mk @@ -21,10 +21,10 @@ SWAP_HANDS_ENABLE = no        # Enable one-hand typing  SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend  # If you want to change the display of OLED, you need to change here -SRC +=  ../lib/rgb_state_reader.c \ -        ../lib/layer_state_reader.c \ -        ../lib/logo_reader.c \ -        ../lib/keylogger.c \ -        # ../lib/mode_icon_reader.c \ -        # ../lib/host_led_state_reader.c \ -        # ../lib/timelogger.c \ +SRC +=  ./lib/rgb_state_reader.c \ +        ./lib/layer_state_reader.c \ +        ./lib/logo_reader.c \ +        ./lib/keylogger.c \ +        # ./lib/mode_icon_reader.c \ +        # ./lib/host_led_state_reader.c \ +        # ./lib/timelogger.c \ diff --git a/keyboards/crkbd/keymaps/like_jis/keymap.c b/keyboards/crkbd/keymaps/like_jis/keymap.c index 31b5230b1..90e5b7ec1 100644 --- a/keyboards/crkbd/keymaps/like_jis/keymap.c +++ b/keyboards/crkbd/keymaps/like_jis/keymap.c @@ -5,7 +5,6 @@    #include "split_util.h"  #endif  #ifdef SSD1306OLED -  #include "LUFA/Drivers/Peripheral/TWI.h"    #include "ssd1306.h"  #endif @@ -124,7 +123,6 @@ void matrix_init_user(void) {      #endif      //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h      #ifdef SSD1306OLED -        TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 800000));          iota_gfx_init(!has_usb());   // turns on the display      #endif  } diff --git a/keyboards/crkbd/keymaps/like_jis/rules.mk b/keyboards/crkbd/keymaps/like_jis/rules.mk index 6570e2f5c..0edf1181f 100644 --- a/keyboards/crkbd/keymaps/like_jis/rules.mk +++ b/keyboards/crkbd/keymaps/like_jis/rules.mk @@ -21,10 +21,10 @@ SWAP_HANDS_ENABLE = no        # Enable one-hand typing  SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend  # If you want to change the display of OLED, you need to change here -SRC +=  ../lib/rgb_state_reader.c \ -        ../lib/layer_state_reader.c \ -        ../lib/logo_reader.c \ -        ../lib/keylogger.c \ -        # ../lib/mode_icon_reader.c \ -        # ../lib/host_led_state_reader.c \ -        # ../lib/timelogger.c \ +SRC +=  ./lib/rgb_state_reader.c \ +        ./lib/layer_state_reader.c \ +        ./lib/logo_reader.c \ +        ./lib/keylogger.c \ +        # ./lib/mode_icon_reader.c \ +        # ./lib/host_led_state_reader.c \ +        # ./lib/timelogger.c \ diff --git a/keyboards/crkbd/keymaps/lib/host_led_state_reader.c b/keyboards/crkbd/lib/host_led_state_reader.c index 41ac55dc2..41ac55dc2 100644 --- a/keyboards/crkbd/keymaps/lib/host_led_state_reader.c +++ b/keyboards/crkbd/lib/host_led_state_reader.c diff --git a/keyboards/crkbd/keymaps/lib/keylogger.c b/keyboards/crkbd/lib/keylogger.c index 8f2a8ce3c..8f2a8ce3c 100644 --- a/keyboards/crkbd/keymaps/lib/keylogger.c +++ b/keyboards/crkbd/lib/keylogger.c diff --git a/keyboards/crkbd/keymaps/lib/layer_state_reader.c b/keyboards/crkbd/lib/layer_state_reader.c index eddb71337..eddb71337 100644 --- a/keyboards/crkbd/keymaps/lib/layer_state_reader.c +++ b/keyboards/crkbd/lib/layer_state_reader.c diff --git a/keyboards/crkbd/keymaps/lib/logo_reader.c b/keyboards/crkbd/lib/logo_reader.c index 1bc1503a6..1bc1503a6 100644 --- a/keyboards/crkbd/keymaps/lib/logo_reader.c +++ b/keyboards/crkbd/lib/logo_reader.c diff --git a/keyboards/crkbd/keymaps/lib/mode_icon_reader.c b/keyboards/crkbd/lib/mode_icon_reader.c index 04c226506..04c226506 100644 --- a/keyboards/crkbd/keymaps/lib/mode_icon_reader.c +++ b/keyboards/crkbd/lib/mode_icon_reader.c diff --git a/keyboards/crkbd/keymaps/lib/rgb_state_reader.c b/keyboards/crkbd/lib/rgb_state_reader.c index e0efe2e52..e0efe2e52 100644 --- a/keyboards/crkbd/keymaps/lib/rgb_state_reader.c +++ b/keyboards/crkbd/lib/rgb_state_reader.c diff --git a/keyboards/crkbd/keymaps/lib/timelogger.c b/keyboards/crkbd/lib/timelogger.c index 69828a3a0..69828a3a0 100644 --- a/keyboards/crkbd/keymaps/lib/timelogger.c +++ b/keyboards/crkbd/lib/timelogger.c diff --git a/keyboards/crkbd/pro_micro.h b/keyboards/crkbd/pro_micro.h index f9e7ed75d..366633372 100644 --- a/keyboards/crkbd/pro_micro.h +++ b/keyboards/crkbd/pro_micro.h @@ -21,9 +21,7 @@    $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $  */ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h +#pragma once  #include <avr/pgmspace.h> @@ -358,5 +356,3 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {  #define SERIAL_PORT_USBVIRTUAL     Serial  #define SERIAL_PORT_HARDWARE       Serial1  #define SERIAL_PORT_HARDWARE_OPEN  Serial1 - -#endif /* Pins_Arduino_h */ diff --git a/keyboards/crkbd/rev1/config.h b/keyboards/crkbd/rev1/config.h index 6321136a7..efce13a49 100644 --- a/keyboards/crkbd/rev1/config.h +++ b/keyboards/crkbd/rev1/config.h @@ -16,10 +16,7 @@ You should have received a copy of the GNU General Public License  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ -#ifndef REV1_CONFIG_H -#define REV1_CONFIG_H - -#include "../config.h" +#pragma once  /* USB Device descriptor parameter */  #define VENDOR_ID       0xFEED @@ -82,6 +79,3 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  //#define NO_ACTION_ONESHOT  //#define NO_ACTION_MACRO  //#define NO_ACTION_FUNCTION - - -#endif diff --git a/keyboards/crkbd/rev1/matrix.c b/keyboards/crkbd/rev1/matrix.c index 117ff8d37..718cc5744 100644 --- a/keyboards/crkbd/rev1/matrix.c +++ b/keyboards/crkbd/rev1/matrix.c @@ -20,6 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include <stdint.h>  #include <stdbool.h> +#include <string.h>  #include <avr/io.h>  #include <avr/wdt.h>  #include <avr/interrupt.h> @@ -30,12 +31,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "matrix.h"  #include "split_util.h"  #include "pro_micro.h" -#include "config.h"  #ifdef USE_MATRIX_I2C  #  include "i2c.h"  #else // USE_SERIAL -#  include "serial.h" +#  include "split_scomm.h"  #endif  #ifndef DEBOUNCE @@ -103,6 +103,8 @@ void matrix_init(void)      init_cols();      TX_RX_LED_INIT; +    TXLED0; +    RXLED0;      // initialize matrix state: all keys off      for (uint8_t i=0; i < MATRIX_ROWS; i++) { @@ -179,17 +181,20 @@ i2c_error: // the cable is disconnceted, or something else went wrong  #else // USE_SERIAL -int serial_transaction(void) { +int serial_transaction(int master_changed) {      int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; +#ifdef SERIAL_USE_MULTI_TRANSACTION +    int ret=serial_update_buffers(master_changed); +#else      int ret=serial_update_buffers(); +#endif      if (ret ) { -        if(ret==2)RXLED1; +        if(ret==2) RXLED1;          return 1;      } -RXLED0; -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        matrix[slaveOffset+i] = serial_slave_buffer[i]; -    } +    RXLED0; +    memcpy(&matrix[slaveOffset], +        (void *)serial_slave_buffer, SERIAL_SLAVE_BUFFER_LENGTH);      return 0;  }  #endif @@ -200,19 +205,9 @@ uint8_t matrix_scan(void)          matrix_master_scan();      }else{          matrix_slave_scan(); - -//        if(serial_slave_DATA_CORRUPT()){ -//          TXLED0; -          int offset = (isLeftHand) ? ROWS_PER_HAND : 0; - -          for (int i = 0; i < ROWS_PER_HAND; ++i) { -              matrix[offset+i] = serial_master_buffer[i]; -          } - -//        }else{ -//          TXLED1; -//        } - +        int offset = (isLeftHand) ? ROWS_PER_HAND : 0; +        memcpy(&matrix[offset], +               (void *)serial_master_buffer, SERIAL_MASTER_BUFFER_LENGTH);          matrix_scan_quantum();      }      return 1; @@ -222,6 +217,7 @@ uint8_t matrix_scan(void)  uint8_t matrix_master_scan(void) {      int ret = _matrix_scan(); +    int mchanged = 1;      int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; @@ -231,15 +227,18 @@ uint8_t matrix_master_scan(void) {  //        i2c_slave_buffer[i] = matrix[offset+i];  //    }  #else // USE_SERIAL -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        serial_master_buffer[i] = matrix[offset+i]; -    } +  #ifdef SERIAL_USE_MULTI_TRANSACTION +    mchanged = memcmp((void *)serial_master_buffer, +		      &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH); +  #endif +    memcpy((void *)serial_master_buffer, +	   &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH);  #endif  #ifdef USE_MATRIX_I2C      if( i2c_transaction() ) {  #else // USE_SERIAL -    if( serial_transaction() ) { +    if( serial_transaction(mchanged) ) {  #endif          // turn on the indicator led when halves are disconnected          TXLED1; @@ -273,9 +272,19 @@ void matrix_slave_scan(void) {          i2c_slave_buffer[i] = matrix[offset+i];      }  #else // USE_SERIAL +  #ifdef SERIAL_USE_MULTI_TRANSACTION +    int change = 0; +  #endif      for (int i = 0; i < ROWS_PER_HAND; ++i) { +  #ifdef SERIAL_USE_MULTI_TRANSACTION +        if( serial_slave_buffer[i] != matrix[offset+i] ) +	    change = 1; +  #endif          serial_slave_buffer[i] = matrix[offset+i];      } +  #ifdef SERIAL_USE_MULTI_TRANSACTION +    slave_buffer_change_count += change; +  #endif  #endif  } diff --git a/keyboards/crkbd/rev1/rev1.h b/keyboards/crkbd/rev1/rev1.h index d02c51f30..cdd61d2bf 100644 --- a/keyboards/crkbd/rev1/rev1.h +++ b/keyboards/crkbd/rev1/rev1.h @@ -1,5 +1,4 @@ -#ifndef REV1_H -#define REV1_CONFIG_H +#pragma once  #include "../crkbd.h" @@ -49,5 +48,3 @@      KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25,                     KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \                                              KC_##L30, KC_##L31, KC_##L32, KC_##R30, KC_##R31, KC_##R32 \    ) - -#endif diff --git a/keyboards/crkbd/rev1/rules.mk b/keyboards/crkbd/rev1/rules.mk index 7af7ffdb8..6028b5a5b 100644 --- a/keyboards/crkbd/rev1/rules.mk +++ b/keyboards/crkbd/rev1/rules.mk @@ -1,2 +1,3 @@ -SRC += rev1/matrix.c \ -	   ws2812.c +SRC += rev1/matrix.c +SRC += rev1/split_util.c +SRC += rev1/split_scomm.c diff --git a/keyboards/crkbd/rev1/serial_config.h b/keyboards/crkbd/rev1/serial_config.h new file mode 100644 index 000000000..671ed821d --- /dev/null +++ b/keyboards/crkbd/rev1/serial_config.h @@ -0,0 +1,10 @@ +#pragma once + +/* Soft Serial defines */ +#define SERIAL_PIN_DDR DDRD +#define SERIAL_PIN_PORT PORTD +#define SERIAL_PIN_INPUT PIND +#define SERIAL_PIN_MASK _BV(PD2) +#define SERIAL_PIN_INTERRUPT INT2_vect + +#define SERIAL_USE_MULTI_TRANSACTION diff --git a/keyboards/crkbd/rev1/serial_config_simpleapi.h b/keyboards/crkbd/rev1/serial_config_simpleapi.h new file mode 100644 index 000000000..0e1dd9e4a --- /dev/null +++ b/keyboards/crkbd/rev1/serial_config_simpleapi.h @@ -0,0 +1,5 @@ +#pragma once + +#undef SERIAL_USE_MULTI_TRANSACTION +#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 +#define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2 diff --git a/keyboards/crkbd/rev1/split_scomm.c b/keyboards/crkbd/rev1/split_scomm.c new file mode 100644 index 000000000..9719eb22e --- /dev/null +++ b/keyboards/crkbd/rev1/split_scomm.c @@ -0,0 +1,73 @@ +#ifdef USE_SERIAL +#ifdef SERIAL_USE_MULTI_TRANSACTION +/* --- USE flexible API (using multi-type transaction function) --- */ + +#include <stdbool.h> +#include <stdint.h> +#include <stddef.h> +#include <split_scomm.h> +#include "serial.h" +#ifdef SERIAL_DEBUG_MODE +#include <avr/io.h> +#endif + +uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; +uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; +uint8_t volatile status_com = 0; +uint8_t volatile status1 = 0; +uint8_t slave_buffer_change_count = 0; +uint8_t s_change_old = 0xff; + +SSTD_t transactions[] = { +#define GET_SLAVE_STATUS 0 +    /* master buffer not changed, only recive slave_buffer_change_count */ +    { (uint8_t *)&status_com, +      0, NULL, +      sizeof(slave_buffer_change_count), &slave_buffer_change_count, +    }, +#define PUT_MASTER_GET_SLAVE_STATUS 1 +    /* master buffer changed need send, and recive slave_buffer_change_count  */ +    { (uint8_t *)&status_com, +      sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer, +      sizeof(slave_buffer_change_count), &slave_buffer_change_count, +    }, +#define GET_SLAVE_BUFFER 2 +    /* recive serial_slave_buffer */ +    { (uint8_t *)&status1, +      0, NULL, +      sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer +    } +}; + +void serial_master_init(void) +{ +    soft_serial_initiator_init(transactions); +} + +void serial_slave_init(void) +{ +    soft_serial_target_init(transactions); +} + +// 0 => no error +// 1 => slave did not respond +// 2 => checksum error +int serial_update_buffers(int master_update) +{ +    int status; +    static int need_retry = 0; +    if( s_change_old != slave_buffer_change_count ) { +	status = soft_serial_transaction(GET_SLAVE_BUFFER); +	if( status == TRANSACTION_END ) +	    s_change_old = slave_buffer_change_count; +    } +    if( !master_update && !need_retry) +	status = soft_serial_transaction(GET_SLAVE_STATUS); +    else +	status = soft_serial_transaction(PUT_MASTER_GET_SLAVE_STATUS); +    need_retry = ( status == TRANSACTION_END ) ? 0 : 1; +    return status; +} + +#endif // SERIAL_USE_MULTI_TRANSACTION +#endif /* USE_SERIAL */ diff --git a/keyboards/crkbd/rev1/split_scomm.h b/keyboards/crkbd/rev1/split_scomm.h new file mode 100644 index 000000000..16887eb74 --- /dev/null +++ b/keyboards/crkbd/rev1/split_scomm.h @@ -0,0 +1,21 @@ +#pragma once + +#ifndef SERIAL_USE_MULTI_TRANSACTION +/* --- USE Simple API (OLD API, compatible with let's split serial.c) --- */ +#include "serial.h" + +#else +/* --- USE flexible API (using multi-type transaction function) --- */ +// Buffers for master - slave communication +#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 +#define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2 + +extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH]; +extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH]; +extern uint8_t slave_buffer_change_count; + +void serial_master_init(void); +void serial_slave_init(void); +int serial_update_buffers(int master_changed); + +#endif diff --git a/keyboards/crkbd/split_util.c b/keyboards/crkbd/rev1/split_util.c index 8bc064174..e1ff8b437 100644 --- a/keyboards/crkbd/split_util.c +++ b/keyboards/crkbd/rev1/split_util.c @@ -7,12 +7,11 @@  #include "split_util.h"  #include "matrix.h"  #include "keyboard.h" -#include "config.h"  #ifdef USE_MATRIX_I2C  #  include "i2c.h"  #else -#  include "serial.h" +#  include "split_scomm.h"  #endif  volatile bool isLeftHand = true; diff --git a/keyboards/crkbd/split_util.h b/keyboards/crkbd/rev1/split_util.h index 687ca19bd..f59304756 100644 --- a/keyboards/crkbd/split_util.h +++ b/keyboards/crkbd/rev1/split_util.h @@ -1,5 +1,4 @@ -#ifndef SPLIT_KEYBOARD_UTIL_H -#define SPLIT_KEYBOARD_UTIL_H +#pragma once  #include <stdbool.h>  #include "eeconfig.h" @@ -15,5 +14,3 @@ void split_keyboard_setup(void);  bool has_usb(void);  void matrix_master_OLED_init (void); - -#endif diff --git a/keyboards/crkbd/rules.mk b/keyboards/crkbd/rules.mk index d88daebf3..6396b115d 100644 --- a/keyboards/crkbd/rules.mk +++ b/keyboards/crkbd/rules.mk @@ -1,7 +1,9 @@ -SRC += i2c.c \ -	   serial.c \ -	   split_util.c \ -	   ssd1306.c +SRC += i2c.c +SRC += serial.c +SRC += ssd1306.c + +# if firmware size over limit, try this option +# CFLAGS += -flto  # MCU name  #MCU = at90usb1287 diff --git a/keyboards/crkbd/serial.c b/keyboards/crkbd/serial.c index e918ab6ee..11ceff0b3 100644 --- a/keyboards/crkbd/serial.c +++ b/keyboards/crkbd/serial.c @@ -9,36 +9,128 @@  #include <avr/io.h>  #include <avr/interrupt.h>  #include <util/delay.h> +#include <stddef.h>  #include <stdbool.h>  #include "serial.h" +//#include <pro_micro.h>  #ifdef USE_SERIAL -// Serial pulse period in microseconds. Its probably a bad idea to lower this -// value. -#define SERIAL_DELAY 24 +#ifndef SERIAL_USE_MULTI_TRANSACTION +/* --- USE Simple API (OLD API, compatible with let's split serial.c) */ +  #if SERIAL_SLAVE_BUFFER_LENGTH > 0 +  uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; +  #endif +  #if SERIAL_MASTER_BUFFER_LENGTH > 0 +  uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; +  #endif +  uint8_t volatile status0 = 0; + +SSTD_t transactions[] = { +    { (uint8_t *)&status0, +  #if SERIAL_MASTER_BUFFER_LENGTH > 0 +      sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer, +  #else +      0, (uint8_t *)NULL, +  #endif +  #if SERIAL_SLAVE_BUFFER_LENGTH > 0 +      sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer +  #else +      0, (uint8_t *)NULL, +  #endif +  } +}; + +void serial_master_init(void) +{ soft_serial_initiator_init(transactions); } -uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; -uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; +void serial_slave_init(void) +{ soft_serial_target_init(transactions); } -#define SLAVE_DATA_CORRUPT (1<<0) -volatile uint8_t status = 0; +// 0 => no error +// 1 => slave did not respond +// 2 => checksum error +int serial_update_buffers() +{ return soft_serial_transaction(); } + +#endif // Simple API (OLD API, compatible with let's split serial.c) + +#define ALWAYS_INLINE __attribute__((always_inline)) +#define NO_INLINE __attribute__((noinline)) +#define _delay_sub_us(x)    __builtin_avr_delay_cycles(x) + +// Serial pulse period in microseconds. +#define TID_SEND_ADJUST 14 + +#define SELECT_SERIAL_SPEED 1 +#if SELECT_SERIAL_SPEED == 0 +  // Very High speed +  #define SERIAL_DELAY 4             // micro sec +  #define READ_WRITE_START_ADJUST 33 // cycles +  #define READ_WRITE_WIDTH_ADJUST 3 // cycles +#elif SELECT_SERIAL_SPEED == 1 +  // High speed +  #define SERIAL_DELAY 6             // micro sec +  #define READ_WRITE_START_ADJUST 30 // cycles +  #define READ_WRITE_WIDTH_ADJUST 3 // cycles +#elif SELECT_SERIAL_SPEED == 2 +  // Middle speed +  #define SERIAL_DELAY 12            // micro sec +  #define READ_WRITE_START_ADJUST 30 // cycles +  #define READ_WRITE_WIDTH_ADJUST 3 // cycles +#elif SELECT_SERIAL_SPEED == 3 +  // Low speed +  #define SERIAL_DELAY 24            // micro sec +  #define READ_WRITE_START_ADJUST 30 // cycles +  #define READ_WRITE_WIDTH_ADJUST 3 // cycles +#elif SELECT_SERIAL_SPEED == 4 +  // Very Low speed +  #define SERIAL_DELAY 50            // micro sec +  #define READ_WRITE_START_ADJUST 30 // cycles +  #define READ_WRITE_WIDTH_ADJUST 3 // cycles +#else +#error Illegal Serial Speed +#endif + + +#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2) +#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2) + +#define SLAVE_INT_WIDTH_US 1 +#ifndef SERIAL_USE_MULTI_TRANSACTION +  #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY +#else +  #define SLAVE_INT_ACK_WIDTH_UNIT 2 +  #define SLAVE_INT_ACK_WIDTH 4 +#endif + +static SSTD_t *Transaction_table = NULL;  inline static  void serial_delay(void) {    _delay_us(SERIAL_DELAY);  } -void serial_delay_short(void) { -  _delay_us(SERIAL_DELAY-1); + +inline static +void serial_delay_half1(void) { +  _delay_us(SERIAL_DELAY_HALF1); +} + +inline static +void serial_delay_half2(void) { +  _delay_us(SERIAL_DELAY_HALF2);  } + +inline static void serial_output(void) ALWAYS_INLINE;  inline static  void serial_output(void) {    SERIAL_PIN_DDR |= SERIAL_PIN_MASK;  }  // make the serial pin an input with pull-up resistor +inline static void serial_input_with_pullup(void) ALWAYS_INLINE;  inline static -void serial_input(void) { +void serial_input_with_pullup(void) {    SERIAL_PIN_DDR  &= ~SERIAL_PIN_MASK;    SERIAL_PIN_PORT |= SERIAL_PIN_MASK;  } @@ -48,191 +140,305 @@ uint8_t serial_read_pin(void) {    return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);  } +inline static void serial_low(void) ALWAYS_INLINE;  inline static  void serial_low(void) {    SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;  } +inline static void serial_high(void) ALWAYS_INLINE;  inline static  void serial_high(void) {    SERIAL_PIN_PORT |= SERIAL_PIN_MASK;  } -void serial_master_init(void) { -  serial_output(); -  serial_high(); +void soft_serial_initiator_init(SSTD_t *sstd_table) +{ +    Transaction_table = sstd_table; +    serial_output(); +    serial_high();  } -void serial_slave_init(void) { -  serial_input(); - -#ifndef USE_SERIAL_PD2 -  // Enable INT0 -  EIMSK |= _BV(INT0); -  // Trigger on falling edge of INT0 -  EICRA &= ~(_BV(ISC00) | _BV(ISC01)); +void soft_serial_target_init(SSTD_t *sstd_table) +{ +    Transaction_table = sstd_table; +    serial_input_with_pullup(); + +#if SERIAL_PIN_MASK == _BV(PD0) +    // Enable INT0 +    EIMSK |= _BV(INT0); +    // Trigger on falling edge of INT0 +    EICRA &= ~(_BV(ISC00) | _BV(ISC01)); +#elif SERIAL_PIN_MASK == _BV(PD2) +    // Enable INT2 +    EIMSK |= _BV(INT2); +    // Trigger on falling edge of INT2 +    EICRA &= ~(_BV(ISC20) | _BV(ISC21));  #else -  // Enable INT2 -  EIMSK |= _BV(INT2); -  // Trigger on falling edge of INT2 -  EICRA &= ~(_BV(ISC20) | _BV(ISC21)); + #error unknown SERIAL_PIN_MASK value  #endif  } -// Used by the master to synchronize timing with the slave. +// Used by the sender to synchronize timing with the reciver. +static void sync_recv(void) NO_INLINE;  static  void sync_recv(void) { -  serial_input(); -  // This shouldn't hang if the slave disconnects because the -  // serial line will float to high if the slave does disconnect. +  for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) { +  } +  // This shouldn't hang if the target disconnects because the +  // serial line will float to high if the target does disconnect.    while (!serial_read_pin()); -  //serial_delay(); -  _delay_us(SERIAL_DELAY-5);  } -// Used by the slave to send a synchronization signal to the master. +// Used by the reciver to send a synchronization signal to the sender. +static void sync_send(void)NO_INLINE;  static  void sync_send(void) { -  serial_output(); -    serial_low();    serial_delay(); -    serial_high();  }  // Reads a byte from the serial line -static -uint8_t serial_read_byte(void) { -  uint8_t byte = 0; -  serial_input(); -  for ( uint8_t i = 0; i < 8; ++i) { -    byte = (byte << 1) | serial_read_pin(); -    serial_delay(); -    _delay_us(1); +static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE; +static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) { +    uint8_t byte, i, p, pb; + +  _delay_sub_us(READ_WRITE_START_ADJUST); +  for( i = 0, byte = 0, p = 0; i < bit; i++ ) { +      serial_delay_half1();   // read the middle of pulses +      if( serial_read_pin() ) { +	  byte = (byte << 1) | 1; p ^= 1; +      } else { +	  byte = (byte << 1) | 0; p ^= 0; +      } +      _delay_sub_us(READ_WRITE_WIDTH_ADJUST); +      serial_delay_half2();    } +  /* recive parity bit */ +  serial_delay_half1();   // read the middle of pulses +  pb = serial_read_pin(); +  _delay_sub_us(READ_WRITE_WIDTH_ADJUST); +  serial_delay_half2(); + +  *pterrcount += (p != pb)? 1 : 0;    return byte;  }  // Sends a byte with MSB ordering -static -void serial_write_byte(uint8_t data) { -  uint8_t b = 8; -  serial_output(); -  while( b-- ) { -    if(data & (1 << b)) { -      serial_high(); -    } else { -      serial_low(); +void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE; +void serial_write_chunk(uint8_t data, uint8_t bit) { +    uint8_t b, p; +    for( p = 0, b = 1<<(bit-1); b ; b >>= 1) { +	if(data & b) { +	    serial_high(); p ^= 1; +	} else { +	    serial_low();  p ^= 0; +	} +	serial_delay();      } +    /* send parity bit */ +    if(p & 1) { serial_high(); } +    else      { serial_low(); }      serial_delay(); -  } -} -// interrupt handle to be used by the slave device -ISR(SERIAL_PIN_INTERRUPT) { -  sync_send(); +    serial_low(); // sync_send() / senc_recv() need raise edge +} -  uint8_t checksum = 0; -  for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) { -    serial_write_byte(serial_slave_buffer[i]); +static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE; +static +void serial_send_packet(uint8_t *buffer, uint8_t size) { +  for (uint8_t i = 0; i < size; ++i) { +    uint8_t data; +    data = buffer[i];      sync_send(); -    checksum += serial_slave_buffer[i]; +    serial_write_chunk(data,8);    } -  serial_write_byte(checksum); -  sync_send(); +} -  // wait for the sync to finish sending -  serial_delay(); +static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE; +static +uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { +  uint8_t pecount = 0; +  for (uint8_t i = 0; i < size; ++i) { +    uint8_t data; +    sync_recv(); +    data = serial_read_chunk(&pecount, 8); +    buffer[i] = data; +  } +  return pecount == 0; +} -  // read the middle of pulses -  _delay_us(SERIAL_DELAY/2); +inline static +void change_sender2reciver(void) { +    sync_send();          //0 +    serial_delay_half1(); //1 +    serial_low();         //2 +    serial_input_with_pullup(); //2 +    serial_delay_half1(); //3 +} -  uint8_t checksum_computed = 0; -  for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) { -    serial_master_buffer[i] = serial_read_byte(); -    sync_send(); -    checksum_computed += serial_master_buffer[i]; -  } -  uint8_t checksum_received = serial_read_byte(); -  sync_send(); +inline static +void change_reciver2sender(void) { +    sync_recv();     //0 +    serial_delay();  //1 +    serial_low();    //3 +    serial_output(); //3 +    serial_delay_half1(); //4 +} -  serial_input(); // end transaction +// interrupt handle to be used by the target device +ISR(SERIAL_PIN_INTERRUPT) { -  if ( checksum_computed != checksum_received ) { -    status |= SLAVE_DATA_CORRUPT; +#ifndef SERIAL_USE_MULTI_TRANSACTION +  serial_low(); +  serial_output(); +  SSTD_t *trans = Transaction_table; +#else +  // recive transaction table index +  uint8_t tid; +  uint8_t pecount = 0; +  sync_recv(); +  tid = serial_read_chunk(&pecount,4); +  if(pecount> 0) +      return; +  serial_delay_half1(); + +  serial_high(); // response step1 low->high +  serial_output(); +  _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH); +  SSTD_t *trans = &Transaction_table[tid]; +  serial_low(); // response step2 ack high->low +#endif + +  // target send phase +  if( trans->target2initiator_buffer_size > 0 ) +      serial_send_packet((uint8_t *)trans->target2initiator_buffer, +			 trans->target2initiator_buffer_size); +  // target switch to input +  change_sender2reciver(); + +  // target recive phase +  if( trans->initiator2target_buffer_size > 0 ) { +      if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, +			       trans->initiator2target_buffer_size) ) { +	  *trans->status = TRANSACTION_ACCEPTED; +      } else { +	  *trans->status = TRANSACTION_DATA_ERROR; +      }    } else { -    status &= ~SLAVE_DATA_CORRUPT; +      *trans->status = TRANSACTION_ACCEPTED;    } -} -inline -bool serial_slave_DATA_CORRUPT(void) { -  return status & SLAVE_DATA_CORRUPT; +  sync_recv(); //weit initiator output to high  } -// Copies the serial_slave_buffer to the master and sends the -// serial_master_buffer to the slave. +///////// +//  start transaction by initiator +// +// int  soft_serial_transaction(int sstd_index)  //  // Returns: -// 0 => no error -// 1 => slave did not respond -int serial_update_buffers(void) { -  // this code is very time dependent, so we need to disable interrupts +//    TRANSACTION_END +//    TRANSACTION_NO_RESPONSE +//    TRANSACTION_DATA_ERROR +// this code is very time dependent, so we need to disable interrupts +#ifndef SERIAL_USE_MULTI_TRANSACTION +int  soft_serial_transaction(void) { +  SSTD_t *trans = Transaction_table; +#else +int  soft_serial_transaction(int sstd_index) { +  SSTD_t *trans = &Transaction_table[sstd_index]; +#endif    cli(); -  // signal to the slave that we want to start a transaction +  // signal to the target that we want to start a transaction    serial_output();    serial_low(); -  _delay_us(1); +  _delay_us(SLAVE_INT_WIDTH_US); -  // wait for the slaves response -  serial_input(); -  serial_high(); -  _delay_us(SERIAL_DELAY); +#ifndef SERIAL_USE_MULTI_TRANSACTION +  // wait for the target response +  serial_input_with_pullup(); +  _delay_us(SLAVE_INT_RESPONSE_TIME); -  // check if the slave is present +  // check if the target is present    if (serial_read_pin()) { -    // slave failed to pull the line low, assume not present +    // target failed to pull the line low, assume not present +    serial_output(); +    serial_high(); +    *trans->status = TRANSACTION_NO_RESPONSE;      sei(); -    return 1; +    return TRANSACTION_NO_RESPONSE;    } -  // if the slave is present syncronize with it -  sync_recv(); - -  uint8_t checksum_computed = 0; -  // receive data from the slave -  for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) { -    serial_slave_buffer[i] = serial_read_byte(); -    sync_recv(); -    checksum_computed += serial_slave_buffer[i]; +#else +  // send transaction table index +  sync_send(); +  _delay_sub_us(TID_SEND_ADJUST); +  serial_write_chunk(sstd_index, 4); +  serial_delay_half1(); + +  // wait for the target response (step1 low->high) +  serial_input_with_pullup(); +  while( !serial_read_pin() ) { +      _delay_sub_us(2);    } -  uint8_t checksum_received = serial_read_byte(); -  sync_recv(); -  if (checksum_computed != checksum_received) { -    sei(); -    return 2; +  // check if the target is present (step2 high->low) +  for( int i = 0; serial_read_pin(); i++ ) { +      if (i > SLAVE_INT_ACK_WIDTH + 1) { +	  // slave failed to pull the line low, assume not present +	  serial_output(); +	  serial_high(); +	  *trans->status = TRANSACTION_NO_RESPONSE; +	  sei(); +	  return TRANSACTION_NO_RESPONSE; +      } +      _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);    } +#endif -  uint8_t checksum = 0; -  // send data to the slave -  for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) { -    serial_write_byte(serial_master_buffer[i]); -    sync_recv(); -    checksum += serial_master_buffer[i]; +  // initiator recive phase +  // if the target is present syncronize with it +  if( trans->target2initiator_buffer_size > 0 ) { +      if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, +				trans->target2initiator_buffer_size) ) { +	  serial_output(); +	  serial_high(); +	  *trans->status = TRANSACTION_DATA_ERROR; +	  sei(); +	  return TRANSACTION_DATA_ERROR; +      } +   } + +  // initiator switch to output +  change_reciver2sender(); + +  // initiator send phase +  if( trans->initiator2target_buffer_size > 0 ) { +      serial_send_packet((uint8_t *)trans->initiator2target_buffer, +			 trans->initiator2target_buffer_size);    } -  serial_write_byte(checksum); -  sync_recv();    // always, release the line when not in use -  serial_output(); -  serial_high(); +  sync_send(); +  *trans->status = TRANSACTION_END;    sei(); -  return 0; +  return TRANSACTION_END;  } +#ifdef SERIAL_USE_MULTI_TRANSACTION +int soft_serial_get_and_clean_status(int sstd_index) { +    SSTD_t *trans = &Transaction_table[sstd_index]; +    cli(); +    int retval = *trans->status; +    *trans->status = 0;; +    sei(); +    return retval; +} +#endif +  #endif diff --git a/keyboards/crkbd/serial.h b/keyboards/crkbd/serial.h index 43e51f7fa..76c6aaa04 100644 --- a/keyboards/crkbd/serial.h +++ b/keyboards/crkbd/serial.h @@ -1,32 +1,77 @@ -#ifndef MY_SERIAL_H -#define MY_SERIAL_H +#pragma once -#include "config.h"  #include <stdbool.h> -/* TODO:  some defines for interrupt setup */ -#define SERIAL_PIN_DDR DDRD -#define SERIAL_PIN_PORT PORTD -#define SERIAL_PIN_INPUT PIND +// ///////////////////////////////////////////////////////////////// +// Need Soft Serial defines in serial_config.h +// ///////////////////////////////////////////////////////////////// +// ex. +//  #define SERIAL_PIN_DDR DDRD +//  #define SERIAL_PIN_PORT PORTD +//  #define SERIAL_PIN_INPUT PIND +//  #define SERIAL_PIN_MASK _BV(PD?)   ?=0,2 +//  #define SERIAL_PIN_INTERRUPT INT?_vect  ?=0,2 +// +// //// USE Simple API (OLD API, compatible with let's split serial.c) +// ex. +//  #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 +//  #define SERIAL_MASTER_BUFFER_LENGTH 1 +// +// //// USE flexible API (using multi-type transaction function) +//  #define SERIAL_USE_MULTI_TRANSACTION +// +// ///////////////////////////////////////////////////////////////// -#ifndef USE_SERIAL_PD2 -#define SERIAL_PIN_MASK _BV(PD0) -#define SERIAL_PIN_INTERRUPT INT0_vect -#else -#define SERIAL_PIN_MASK _BV(PD2) -#define SERIAL_PIN_INTERRUPT INT2_vect -#endif - -#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 -#define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2 -// Buffers for master - slave communication +#ifndef SERIAL_USE_MULTI_TRANSACTION +/* --- USE Simple API (OLD API, compatible with let's split serial.c) */ +#if SERIAL_SLAVE_BUFFER_LENGTH > 0  extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH]; +#endif +#if SERIAL_MASTER_BUFFER_LENGTH > 0  extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH]; +#endif  void serial_master_init(void);  void serial_slave_init(void);  int serial_update_buffers(void); -bool serial_slave_data_corrupt(void); +#endif // USE Simple API + +// Soft Serial Transaction Descriptor +typedef struct _SSTD_t  { +    uint8_t *status; +    uint8_t initiator2target_buffer_size; +    uint8_t *initiator2target_buffer; +    uint8_t target2initiator_buffer_size; +    uint8_t *target2initiator_buffer; +} SSTD_t; + +// initiator is transaction start side +void soft_serial_initiator_init(SSTD_t *sstd_table); +// target is interrupt accept side +void soft_serial_target_init(SSTD_t *sstd_table); + +// initiator resullt +#define TRANSACTION_END 0 +#define TRANSACTION_NO_RESPONSE 0x1 +#define TRANSACTION_DATA_ERROR  0x2 +#ifndef SERIAL_USE_MULTI_TRANSACTION +int  soft_serial_transaction(void); +#else +int  soft_serial_transaction(int sstd_index); +#endif + +// target status +// *SSTD_t.status has +//   initiator: +//       TRANSACTION_END +//    or TRANSACTION_NO_RESPONSE +//    or TRANSACTION_DATA_ERROR +//   target: +//       TRANSACTION_DATA_ERROR +//    or TRANSACTION_ACCEPTED +#define TRANSACTION_ACCEPTED 0x4 +#ifdef SERIAL_USE_MULTI_TRANSACTION +int  soft_serial_get_and_clean_status(int sstd_index);  #endif diff --git a/keyboards/crkbd/ssd1306.c b/keyboards/crkbd/ssd1306.c index d07900119..b8f9512e3 100644 --- a/keyboards/crkbd/ssd1306.c +++ b/keyboards/crkbd/ssd1306.c @@ -123,6 +123,7 @@ static int8_t capture_sendchar(uint8_t c) {  bool iota_gfx_init(bool rotate) {    bool success = false; +  i2c_master_init();    send_cmd1(DisplayOff);    send_cmd2(SetDisplayClockDiv, 0x80);    send_cmd2(SetMultiPlex, DisplayHeight - 1); diff --git a/keyboards/crkbd/ssd1306.h b/keyboards/crkbd/ssd1306.h index 59d31c9f3..76dd6a2a7 100644 --- a/keyboards/crkbd/ssd1306.h +++ b/keyboards/crkbd/ssd1306.h @@ -1,10 +1,8 @@ -#ifndef SSD1306_H -#define SSD1306_H +#pragma once  #include <stdbool.h>  #include <stdio.h>  #include "pincontrol.h" -#include "config.h"  enum ssd1306_cmds {    DisplayOff = 0xAE, @@ -88,7 +86,3 @@ void matrix_write(struct CharacterMatrix *matrix, const char *data);  void matrix_write_ln(struct CharacterMatrix *matrix, const char *data);  void matrix_write_P(struct CharacterMatrix *matrix, const char *data);  void matrix_render(struct CharacterMatrix *matrix); - - - -#endif | 
