diff options
| -rw-r--r-- | keyboards/lily58/rev1/config.h | 2 | ||||
| -rwxr-xr-x | keyboards/lily58/rev1/matrix.c | 357 | ||||
| -rwxr-xr-x | keyboards/lily58/rev1/serial_config.h | 4 | ||||
| -rwxr-xr-x | keyboards/lily58/rev1/split_util.c | 100 | ||||
| -rwxr-xr-x | keyboards/lily58/serial.c | 589 | 
5 files changed, 2 insertions, 1050 deletions
| diff --git a/keyboards/lily58/rev1/config.h b/keyboards/lily58/rev1/config.h index 39b15fc5b6..24dc41151f 100644 --- a/keyboards/lily58/rev1/config.h +++ b/keyboards/lily58/rev1/config.h @@ -35,6 +35,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define MATRIX_ROW_PINS { C6, D7, E6, B4, B5 }  #define MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 } +#define SOFT_SERIAL_PIN D2 +#define SERIAL_USE_MULTI_TRANSACTION  /* define if matrix has ghost */  //#define MATRIX_HAS_GHOST diff --git a/keyboards/lily58/rev1/matrix.c b/keyboards/lily58/rev1/matrix.c deleted file mode 100755 index d3ba1c924e..0000000000 --- a/keyboards/lily58/rev1/matrix.c +++ /dev/null @@ -1,357 +0,0 @@ -/* -Copyright 2012 Jun Wako <[email protected]> - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program.  If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * scan matrix - */ -#include <stdint.h> -#include <stdbool.h> -#include <string.h> -#include <avr/io.h> -#include <avr/wdt.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "print.h" -#include "debug.h" -#include "util.h" -#include "matrix.h" -#include "split_util.h" -#include "quantum.h" - -#ifdef USE_MATRIX_I2C -#  include "i2c.h" -#else // USE_SERIAL -#  include "split_scomm.h" -#endif - -#ifndef DEBOUNCE -#  define DEBOUNCE	5 -#endif - -#define ERROR_DISCONNECT_COUNT 5 - -static uint8_t debouncing = DEBOUNCE; -static const int ROWS_PER_HAND = MATRIX_ROWS/2; -static uint8_t error_count = 0; -uint8_t is_master = 0 ; - -static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; - -/* matrix state(1:on, 0:off) */ -static matrix_row_t matrix[MATRIX_ROWS]; -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; - -static matrix_row_t read_cols(void); -static void init_cols(void); -static void unselect_rows(void); -static void select_row(uint8_t row); -static uint8_t matrix_master_scan(void); - - -__attribute__ ((weak)) -void matrix_init_kb(void) { -    matrix_init_user(); -} - -__attribute__ ((weak)) -void matrix_scan_kb(void) { -    matrix_scan_user(); -} - -__attribute__ ((weak)) -void matrix_init_user(void) { -} - -__attribute__ ((weak)) -void matrix_scan_user(void) { -} - -inline -uint8_t matrix_rows(void) -{ -    return MATRIX_ROWS; -} - -inline -uint8_t matrix_cols(void) -{ -    return MATRIX_COLS; -} - -void matrix_init(void) -{ -    split_keyboard_setup(); - -    // initialize row and col -    unselect_rows(); -    init_cols(); - -    setPinOutput(B0); -    setPinOutput(D5); -    writePinHigh(B0); -    writePinHigh(D5); - -    // initialize matrix state: all keys off -    for (uint8_t i=0; i < MATRIX_ROWS; i++) { -        matrix[i] = 0; -        matrix_debouncing[i] = 0; -    } - -    is_master = has_usb(); - -    matrix_init_quantum(); -} - -uint8_t _matrix_scan(void) -{ -    // Right hand is stored after the left in the matirx so, we need to offset it -    int offset = isLeftHand ? 0 : (ROWS_PER_HAND); - -    for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { -        select_row(i); -        _delay_us(30);  // without this wait read unstable value. -        matrix_row_t cols = read_cols(); -        if (matrix_debouncing[i+offset] != cols) { -            matrix_debouncing[i+offset] = cols; -            debouncing = DEBOUNCE; -        } -        unselect_rows(); -    } - -    if (debouncing) { -        if (--debouncing) { -            _delay_ms(1); -        } else { -            for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { -                matrix[i+offset] = matrix_debouncing[i+offset]; -            } -        } -    } - -    return 1; -} - -#ifdef USE_MATRIX_I2C - -// Get rows from other half over i2c -int i2c_transaction(void) { -    int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; - -    int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); -    if (err) goto i2c_error; - -    // start of matrix stored at 0x00 -    err = i2c_master_write(0x00); -    if (err) goto i2c_error; - -    // Start read -    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); -    if (err) goto i2c_error; - -    if (!err) { -        int i; -        for (i = 0; i < ROWS_PER_HAND-1; ++i) { -            matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); -        } -        matrix[slaveOffset+i] = i2c_master_read(I2C_NACK); -        i2c_master_stop(); -    } else { -i2c_error: // the cable is disconnceted, or something else went wrong -        i2c_reset_state(); -        return err; -    } - -    return 0; -} - -#else // USE_SERIAL - -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) writePinLow(B0); -        return 1; -    } -    writePinHigh(B0); -    memcpy(&matrix[slaveOffset], -        (void *)serial_slave_buffer, SERIAL_SLAVE_BUFFER_LENGTH); -    return 0; -} -#endif - -uint8_t matrix_scan(void) -{ -    if (is_master) { -        matrix_master_scan(); -    }else{ -        matrix_slave_scan(); -        int offset = (isLeftHand) ? ROWS_PER_HAND : 0; -        memcpy(&matrix[offset], -               (void *)serial_master_buffer, SERIAL_MASTER_BUFFER_LENGTH); -        matrix_scan_quantum(); -    } -    return 1; -} - - -uint8_t matrix_master_scan(void) { - -    int ret = _matrix_scan(); -    int mchanged = 1; - -    int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; - -#ifdef USE_MATRIX_I2C -//    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        /* i2c_slave_buffer[i] = matrix[offset+i]; */ -//        i2c_slave_buffer[i] = matrix[offset+i]; -//    } -#else // USE_SERIAL -  #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(mchanged) ) { -#endif -        // turn on the indicator led when halves are disconnected -        writePinLow(D5); - -        error_count++; - -        if (error_count > ERROR_DISCONNECT_COUNT) { -            // reset other half if disconnected -            int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; -            for (int i = 0; i < ROWS_PER_HAND; ++i) { -                matrix[slaveOffset+i] = 0; -            } -        } -    } else { -        // turn off the indicator led on no error -        writePinHigh(D5); -        error_count = 0; -    } -    matrix_scan_quantum(); -    return ret; -} - -void matrix_slave_scan(void) { -    _matrix_scan(); - -    int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; - -#ifdef USE_MATRIX_I2C -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        /* i2c_slave_buffer[i] = matrix[offset+i]; */ -        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 -} - -bool matrix_is_modified(void) -{ -    if (debouncing) return false; -    return true; -} - -inline -bool matrix_is_on(uint8_t row, uint8_t col) -{ -    return (matrix[row] & ((matrix_row_t)1<<col)); -} - -inline -matrix_row_t matrix_get_row(uint8_t row) -{ -    return matrix[row]; -} - -void matrix_print(void) -{ -    print("\nr/c 0123456789ABCDEF\n"); -    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { -        print_hex8(row); print(": "); -        print_bin_reverse16(matrix_get_row(row)); -        print("\n"); -    } -} - -uint8_t matrix_key_count(void) -{ -    uint8_t count = 0; -    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { -        count += bitpop16(matrix[i]); -    } -    return count; -} - -static void  init_cols(void) -{ -    for(int x = 0; x < MATRIX_COLS; x++) { -        _SFR_IO8((col_pins[x] >> 4) + 1) &=  ~_BV(col_pins[x] & 0xF); -        _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF); -    } -} - -static matrix_row_t read_cols(void) -{ -    matrix_row_t result = 0; -    for(int x = 0; x < MATRIX_COLS; x++) { -        result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x); -    } -    return result; -} - -static void unselect_rows(void) -{ -    for(int x = 0; x < ROWS_PER_HAND; x++) { -        _SFR_IO8((row_pins[x] >> 4) + 1) &=  ~_BV(row_pins[x] & 0xF); -        _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF); -    } -} - -static void select_row(uint8_t row) -{ -    _SFR_IO8((row_pins[row] >> 4) + 1) |=  _BV(row_pins[row] & 0xF); -    _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF); -} diff --git a/keyboards/lily58/rev1/serial_config.h b/keyboards/lily58/rev1/serial_config.h deleted file mode 100755 index 4fab8e8ddf..0000000000 --- a/keyboards/lily58/rev1/serial_config.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef SOFT_SERIAL_PIN -#define SOFT_SERIAL_PIN D2 -#define SERIAL_USE_MULTI_TRANSACTION -#endif diff --git a/keyboards/lily58/rev1/split_util.c b/keyboards/lily58/rev1/split_util.c deleted file mode 100755 index 316c1c389e..0000000000 --- a/keyboards/lily58/rev1/split_util.c +++ /dev/null @@ -1,100 +0,0 @@ -#include <avr/io.h> -#include <avr/wdt.h> -#include <avr/power.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include <avr/eeprom.h> -#include "split_util.h" -#include "matrix.h" -#include "keyboard.h" -#include "wait.h" - -#ifdef USE_MATRIX_I2C -#  include "i2c.h" -#else -#  include "split_scomm.h" -#endif - -#ifndef SPLIT_USB_TIMEOUT -#    define SPLIT_USB_TIMEOUT 2500 -#endif - -volatile bool isLeftHand = true; - -bool waitForUsb(void) { -    for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / 100); i++) { -        // This will return true of a USB connection has been established -        if (UDADDR & _BV(ADDEN)) { -            return true; -        } -        wait_ms(100); -    } - -    // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow -    (USBCON &= ~(_BV(USBE) | _BV(OTGPADE))); - -    return false; -} - -__attribute__((weak)) bool is_keyboard_left(void) { -#if defined(SPLIT_HAND_PIN) -    // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand -    setPinInput(SPLIT_HAND_PIN); -    return readPin(SPLIT_HAND_PIN); -#elif defined(EE_HANDS) -    return eeconfig_read_handedness(); -#elif defined(MASTER_RIGHT) -    return !has_usb(); -#endif - -    return has_usb(); -} - -__attribute__((weak)) bool has_usb(void) { -    static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN; - -    // only check once, as this is called often -    if (usbstate == UNKNOWN) { -#if defined(SPLIT_USB_DETECT) -        usbstate = waitForUsb() ? MASTER : SLAVE; -#elif defined(__AVR__) -        USBCON |= (1 << OTGPADE);  // enables VBUS pad -        wait_us(5); - -        usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE;  // checks state of VBUS -#else -        usbstate = MASTER; -#endif -    } - -    return (usbstate == MASTER); -} - -static void keyboard_master_setup(void) { - -#ifdef USE_MATRIX_I2C -    i2c_master_init(); -#else -    serial_master_init(); -#endif -} - -static void keyboard_slave_setup(void) { - -#ifdef USE_MATRIX_I2C -    i2c_slave_init(SLAVE_I2C_ADDRESS); -#else -    serial_slave_init(); -#endif -} - -void split_keyboard_setup(void) { -   isLeftHand = is_keyboard_left(); - -   if (has_usb()) { -      keyboard_master_setup(); -   } else { -      keyboard_slave_setup(); -   } -   sei(); -} diff --git a/keyboards/lily58/serial.c b/keyboards/lily58/serial.c deleted file mode 100755 index f6293c3dc2..0000000000 --- a/keyboards/lily58/serial.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * WARNING: be careful changing this code, it is very timing dependent - * - * 2018-10-28 checked - *  avr-gcc 4.9.2 - *  avr-gcc 5.4.0 - *  avr-gcc 7.3.0 - */ - -#ifndef F_CPU -#define F_CPU 16000000 -#endif - -#include <avr/io.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include <stddef.h> -#include <stdbool.h> -#include "serial.h" - -#ifdef SOFT_SERIAL_PIN - -#ifdef __AVR_ATmega32U4__ -  // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. -  #ifdef USE_I2C -    #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 -      #error Using ATmega32U4 I2C, so can not use PD0, PD1 -    #endif -  #endif - -  #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 -    #define SERIAL_PIN_DDR   DDRD -    #define SERIAL_PIN_PORT  PORTD -    #define SERIAL_PIN_INPUT PIND -    #if SOFT_SERIAL_PIN == D0 -      #define SERIAL_PIN_MASK _BV(PD0) -      #define EIMSK_BIT       _BV(INT0) -      #define EICRx_BIT       (~(_BV(ISC00) | _BV(ISC01))) -      #define SERIAL_PIN_INTERRUPT INT0_vect -    #elif  SOFT_SERIAL_PIN == D1 -      #define SERIAL_PIN_MASK _BV(PD1) -      #define EIMSK_BIT       _BV(INT1) -      #define EICRx_BIT       (~(_BV(ISC10) | _BV(ISC11))) -      #define SERIAL_PIN_INTERRUPT INT1_vect -    #elif  SOFT_SERIAL_PIN == D2 -      #define SERIAL_PIN_MASK _BV(PD2) -      #define EIMSK_BIT       _BV(INT2) -      #define EICRx_BIT       (~(_BV(ISC20) | _BV(ISC21))) -      #define SERIAL_PIN_INTERRUPT INT2_vect -    #elif  SOFT_SERIAL_PIN == D3 -      #define SERIAL_PIN_MASK _BV(PD3) -      #define EIMSK_BIT       _BV(INT3) -      #define EICRx_BIT       (~(_BV(ISC30) | _BV(ISC31))) -      #define SERIAL_PIN_INTERRUPT INT3_vect -    #endif -  #elif  SOFT_SERIAL_PIN == E6 -    #define SERIAL_PIN_DDR   DDRE -    #define SERIAL_PIN_PORT  PORTE -    #define SERIAL_PIN_INPUT PINE -    #define SERIAL_PIN_MASK  _BV(PE6) -    #define EIMSK_BIT        _BV(INT6) -    #define EICRx_BIT        (~(_BV(ISC60) | _BV(ISC61))) -    #define SERIAL_PIN_INTERRUPT INT6_vect -  #else -  #error invalid SOFT_SERIAL_PIN value -  #endif - -#else - #error serial.c now support ATmega32U4 only -#endif - -//////////////// for backward compatibility //////////////////////////////// -#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, TID_LIMIT(transactions)); } - -void serial_slave_init(void) -{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); } - -// 0 => no error -// 1 => slave did not respond -// 2 => checksum error -int serial_update_buffers() -{ -    int result; -    result = soft_serial_transaction(); -    return result; -} - -#endif // end of 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) - -// parity check -#define ODD_PARITY 1 -#define EVEN_PARITY 0 -#define PARITY EVEN_PARITY - -#ifdef SERIAL_DELAY -  // custom setup in config.h -  // #define TID_SEND_ADJUST 2 -  // #define SERIAL_DELAY 6             // micro sec -  // #define READ_WRITE_START_ADJUST 30 // cycles -  // #define READ_WRITE_WIDTH_ADJUST 8 // cycles -#else -// ============ Standard setups ============ - -#ifndef SELECT_SOFT_SERIAL_SPEED -#define SELECT_SOFT_SERIAL_SPEED 1 -//  0: about 189kbps -//  1: about 137kbps (default) -//  2: about 75kbps -//  3: about 39kbps -//  4: about 26kbps -//  5: about 20kbps -#endif - -#if __GNUC__ < 6 -  #define TID_SEND_ADJUST 14 -#else -  #define TID_SEND_ADJUST 2 -#endif - -#if SELECT_SOFT_SERIAL_SPEED == 0 -  // Very High speed -  #define SERIAL_DELAY 4             // micro sec -  #if __GNUC__ < 6 -    #define READ_WRITE_START_ADJUST 33 // cycles -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_START_ADJUST 34 // cycles -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#elif SELECT_SOFT_SERIAL_SPEED == 1 -  // High speed -  #define SERIAL_DELAY 6             // micro sec -  #if __GNUC__ < 6 -    #define READ_WRITE_START_ADJUST 30 // cycles -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_START_ADJUST 33 // cycles -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#elif SELECT_SOFT_SERIAL_SPEED == 2 -  // Middle speed -  #define SERIAL_DELAY 12            // micro sec -  #define READ_WRITE_START_ADJUST 30 // cycles -  #if __GNUC__ < 6 -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#elif SELECT_SOFT_SERIAL_SPEED == 3 -  // Low speed -  #define SERIAL_DELAY 24            // micro sec -  #define READ_WRITE_START_ADJUST 30 // cycles -  #if __GNUC__ < 6 -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#elif SELECT_SOFT_SERIAL_SPEED == 4 -  // Very Low speed -  #define SERIAL_DELAY 36            // micro sec -  #define READ_WRITE_START_ADJUST 30 // cycles -  #if __GNUC__ < 6 -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#elif SELECT_SOFT_SERIAL_SPEED == 5 -  // Ultra Low speed -  #define SERIAL_DELAY 48            // micro sec -  #define READ_WRITE_START_ADJUST 30 // cycles -  #if __GNUC__ < 6 -    #define READ_WRITE_WIDTH_ADJUST 3 // cycles -  #else -    #define READ_WRITE_WIDTH_ADJUST 7 // cycles -  #endif -#else -#error invalid SELECT_SOFT_SERIAL_SPEED value -#endif /* SELECT_SOFT_SERIAL_SPEED */ -#endif /* SERIAL_DELAY */ - -#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; -static uint8_t Transaction_table_size = 0; - -inline static void serial_delay(void) ALWAYS_INLINE; -inline static -void serial_delay(void) { -  _delay_us(SERIAL_DELAY); -} - -inline static void serial_delay_half1(void) ALWAYS_INLINE; -inline static -void serial_delay_half1(void) { -  _delay_us(SERIAL_DELAY_HALF1); -} - -inline static void serial_delay_half2(void) ALWAYS_INLINE; -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_with_pullup(void) { -  SERIAL_PIN_DDR  &= ~SERIAL_PIN_MASK; -  SERIAL_PIN_PORT |= SERIAL_PIN_MASK; -} - -inline static uint8_t serial_read_pin(void) ALWAYS_INLINE; -inline static -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 soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) -{ -    Transaction_table = sstd_table; -    Transaction_table_size = (uint8_t)sstd_table_size; -    serial_output(); -    serial_high(); -} - -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) -{ -    Transaction_table = sstd_table; -    Transaction_table_size = (uint8_t)sstd_table_size; -    serial_input_with_pullup(); - -    // Enable INT0-INT3,INT6 -    EIMSK |= EIMSK_BIT; -#if SERIAL_PIN_MASK == _BV(PE6) -    // Trigger on falling edge of INT6 -    EICRB &= EICRx_BIT; -#else -    // Trigger on falling edge of INT0-INT3 -    EICRA &= EICRx_BIT; -#endif -} - -// Used by the sender to synchronize timing with the reciver. -static void sync_recv(void) NO_INLINE; -static -void sync_recv(void) { -  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()); -} - -// 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_low(); -  serial_delay(); -  serial_high(); -} - -// Reads a byte from the serial line -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 = PARITY; 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 -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 = PARITY, 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(); - -    serial_low(); // sync_send() / senc_recv() need raise edge -} - -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(); -    serial_write_chunk(data,8); -  } -} - -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; -} - -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 -} - -inline static -void change_reciver2sender(void) { -    sync_recv();     //0 -    serial_delay();  //1 -    serial_low();    //3 -    serial_output(); //3 -    serial_delay_half1(); //4 -} - -static inline uint8_t nibble_bits_count(uint8_t bits) -{ -    bits = (bits & 0x5) + (bits >> 1 & 0x5); -    bits = (bits & 0x3) + (bits >> 2 & 0x3); -    return bits; -} - -// interrupt handle to be used by the target device -ISR(SERIAL_PIN_INTERRUPT) { - -#ifndef SERIAL_USE_MULTI_TRANSACTION -  serial_low(); -  serial_output(); -  SSTD_t *trans = Transaction_table; -#else -  // recive transaction table index -  uint8_t tid, bits; -  uint8_t pecount = 0; -  sync_recv(); -  bits = serial_read_chunk(&pecount,7); -  tid = bits>>3; -  bits = (bits&7) != nibble_bits_count(tid); -  if( bits || pecount> 0 || tid > Transaction_table_size ) { -      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 { -      *trans->status = TRANSACTION_ACCEPTED; -  } - -  sync_recv(); //weit initiator output to high -} - -///////// -//  start transaction by initiator -// -// int  soft_serial_transaction(int sstd_index) -// -// Returns: -//    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) { -  if( sstd_index > Transaction_table_size ) -      return TRANSACTION_TYPE_ERROR; -  SSTD_t *trans = &Transaction_table[sstd_index]; -#endif -  cli(); - -  // signal to the target that we want to start a transaction -  serial_output(); -  serial_low(); -  _delay_us(SLAVE_INT_WIDTH_US); - -#ifndef SERIAL_USE_MULTI_TRANSACTION -  // wait for the target response -  serial_input_with_pullup(); -  _delay_us(SLAVE_INT_RESPONSE_TIME); - -  // check if the target is present -  if (serial_read_pin()) { -    // target failed to pull the line low, assume not present -    serial_output(); -    serial_high(); -    *trans->status = TRANSACTION_NO_RESPONSE; -    sei(); -    return TRANSACTION_NO_RESPONSE; -  } - -#else -  // send transaction table index -  int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index)); -  sync_send(); -  _delay_sub_us(TID_SEND_ADJUST); -  serial_write_chunk(tid, 7); -  serial_delay_half1(); - -  // wait for the target response (step1 low->high) -  serial_input_with_pullup(); -  while( !serial_read_pin() ) { -      _delay_sub_us(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 - -  // 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); -  } - -  // always, release the line when not in use -  sync_send(); - -  *trans->status = TRANSACTION_END; -  sei(); -  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 - -// Helix serial.c history -//   2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc) -//   2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4) -//             (adjusted with avr-gcc 4.9.2) -//   2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78) -//             (adjusted with avr-gcc 4.9.2) -//   2018-8-11 add support multi-type transaction (#3608, feb5e4aae) -//             (adjusted with avr-gcc 4.9.2) -//   2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff) -//             (adjusted with avr-gcc 7.3.0) -//   2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66) -//             (adjusted with avr-gcc 5.4.0, 7.3.0) | 
