adds i2c slave implementation
This commit is contained in:
parent
b075df1c87
commit
be81cd8c98
@ -20,6 +20,12 @@ SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
|
|||||||
SERIAL_DEFS += -DSERIAL_LINK_ENABLE
|
SERIAL_DEFS += -DSERIAL_LINK_ENABLE
|
||||||
COMMON_VPATH += $(SERIAL_PATH)
|
COMMON_VPATH += $(SERIAL_PATH)
|
||||||
|
|
||||||
|
ifeq ($(PLATFORM),AVR)
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/avr
|
||||||
|
else
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/arm
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
|
ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
|
||||||
OPT_DEFS += -DAPI_SYSEX_ENABLE
|
OPT_DEFS += -DAPI_SYSEX_ENABLE
|
||||||
SRC += $(QUANTUM_DIR)/api/api_sysex.c
|
SRC += $(QUANTUM_DIR)/api/api_sysex.c
|
||||||
@ -184,6 +190,11 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes)
|
|||||||
include $(TMK_DIR)/protocol/usb_hid.mk
|
include $(TMK_DIR)/protocol/usb_hid.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(I2C_SLAVE_ENABLE)), yes)
|
||||||
|
SRC += twi2c.c
|
||||||
|
OPT_DEFS += -DI2C_SLAVE_ENABLE
|
||||||
|
endif
|
||||||
|
|
||||||
QUANTUM_SRC:= \
|
QUANTUM_SRC:= \
|
||||||
$(QUANTUM_DIR)/quantum.c \
|
$(QUANTUM_DIR)/quantum.c \
|
||||||
$(QUANTUM_DIR)/keymap_common.c \
|
$(QUANTUM_DIR)/keymap_common.c \
|
||||||
|
@ -15,19 +15,203 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "twi2c.h"
|
#include "twi2c.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <hal.h>
|
||||||
|
#include "hal_i2cslave.h"
|
||||||
|
#include "chprintf.h"
|
||||||
|
#include "memstreams.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
#ifndef I2C_DRIVER
|
#ifndef I2C_DRIVER
|
||||||
#define I2C_DRIVER &I2CD1
|
#define I2C_DRIVER I2CD1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const I2CConfig i2cconfig = {
|
/**
|
||||||
|
* I2C slave test routine.
|
||||||
|
*
|
||||||
|
* To use: Add file to a project, call startComms() with the address of a serial stream
|
||||||
|
*
|
||||||
|
* There are two different responses:
|
||||||
|
* a) A read-only transaction - returns the "Initial Reply" message
|
||||||
|
* b) A write then read transaction - calls a message processor and returns the generated reply.
|
||||||
|
* Stretches clock until reply available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */
|
||||||
|
//#define myOtherI2Caddress 0x19
|
||||||
|
|
||||||
|
I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend;
|
||||||
|
|
||||||
|
static const I2CConfig slaveI2Cconfig = {
|
||||||
STM32_TIMINGR_PRESC(15U) |
|
STM32_TIMINGR_PRESC(15U) |
|
||||||
STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) |
|
STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) |
|
||||||
STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),
|
STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),
|
||||||
0,
|
0,
|
||||||
0
|
0,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void twi2c_init(void) {
|
char initialReplyBody[50] = "Initial reply"; // 'Status' response if read without preceding write
|
||||||
i2cStart(I2C_DRIVER, &i2cconfig);
|
|
||||||
}
|
|
||||||
|
uint32_t messageCounter = 0; /* Counts number of messages received to return as part of response */
|
||||||
|
|
||||||
|
uint8_t rxBody[240]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */
|
||||||
|
uint8_t txBody[256]; /* Return message buffer for computed replies */
|
||||||
|
|
||||||
|
BaseSequentialStream *chp = NULL; // Used for serial logging
|
||||||
|
|
||||||
|
// Handler when something sent to us
|
||||||
|
const I2CSlaveMsg echoRx =
|
||||||
|
{
|
||||||
|
sizeof(rxBody), /* max sizeof received msg body */
|
||||||
|
rxBody, /* body of received msg */
|
||||||
|
NULL, /* do nothing on address match */
|
||||||
|
twi2c_slave_message_process, /* Routine to process received messages */
|
||||||
|
catchError /* Error hook */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 'Empty' reply when nothing to say, and no message received. In RAM, to allow update
|
||||||
|
I2CSlaveMsg initialReply =
|
||||||
|
{
|
||||||
|
sizeof(initialReplyBody), /* trailing zero byte will be repeated as needed */
|
||||||
|
(uint8_t *)initialReplyBody,
|
||||||
|
NULL, /* do nothing on address match */
|
||||||
|
NULL, /* do nothing after reply sent */
|
||||||
|
catchError /* Error hook */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Response to received messages
|
||||||
|
I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */
|
||||||
|
0, /* filled in with the length of the message to send */
|
||||||
|
txBody, /* Response message */
|
||||||
|
NULL, /* do nothing special on address match */
|
||||||
|
clearAfterSend, /* Clear receive buffer once replied */
|
||||||
|
catchError /* Error hook */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track I2C errors
|
||||||
|
*/
|
||||||
|
uint8_t gotI2cError = 0;
|
||||||
|
uint32_t lastI2cErrorFlags = 0;
|
||||||
|
|
||||||
|
// Called from ISR to log error
|
||||||
|
void noteI2cError(uint32_t flags)
|
||||||
|
{
|
||||||
|
lastI2cErrorFlags = flags;
|
||||||
|
gotI2cError = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic error handler
|
||||||
|
*
|
||||||
|
* Called in interrupt context, so need to watch what we do
|
||||||
|
*/
|
||||||
|
void catchError(I2CDriver *i2cp)
|
||||||
|
{
|
||||||
|
noteI2cError(i2cp->errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char hexString[16] = "0123456789abcdef";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message processor - looks at received message, determines reply as quickly as possible
|
||||||
|
*
|
||||||
|
* Responds with the value of the messageCounter (in hex), followed by the received message in [..]
|
||||||
|
*
|
||||||
|
* Note: Called in interrupt context, so need to be quick!
|
||||||
|
*/
|
||||||
|
void twi2c_slave_message_process(I2CDriver *i2cp) {
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t *txPtr = txBody + 8;
|
||||||
|
uint8_t txLen;
|
||||||
|
uint32_t curCount;
|
||||||
|
|
||||||
|
size_t len = i2cSlaveBytes(i2cp); // Number of bytes received
|
||||||
|
if (len >= sizeof(rxBody))
|
||||||
|
len = sizeof(rxBody)-1;
|
||||||
|
rxBody[len]=0; // String termination sometimes useful
|
||||||
|
|
||||||
|
/* A real-world application would read and decode the message in rxBody, then generate an appropriate reply in txBody */
|
||||||
|
|
||||||
|
curCount = ++messageCounter;
|
||||||
|
txLen = len + 11; // Add in the overhead
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
*--txPtr = hexString[curCount & 0xf];
|
||||||
|
curCount = curCount >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
txPtr = txBody + 8;
|
||||||
|
*txPtr++ = ' ';
|
||||||
|
*txPtr++ = '[';
|
||||||
|
memcpy(txPtr, rxBody, len); // Echo received message
|
||||||
|
txPtr += len;
|
||||||
|
*txPtr++ = ']';
|
||||||
|
*txPtr = '\0';
|
||||||
|
|
||||||
|
/** Message ready to go here */
|
||||||
|
echoReply.size = txLen;
|
||||||
|
i2cSlaveReplyI(i2cp, &echoReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback after sending of response complete - restores default reply in case polled
|
||||||
|
*/
|
||||||
|
void clearAfterSend(I2CDriver *i2cp)
|
||||||
|
{
|
||||||
|
echoReply.size = 0; // Clear receive message
|
||||||
|
i2cSlaveReplyI(i2cp, &initialReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the I2C Slave port to accept comms from master CPU
|
||||||
|
*
|
||||||
|
* We then go into a loop checking for errors, and never return
|
||||||
|
*/
|
||||||
|
|
||||||
|
void twi2c_slave_init(void) {
|
||||||
|
|
||||||
|
palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
|
/* I2C1 SCL on PF1, SDA on PF0 */
|
||||||
|
palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP);
|
||||||
|
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP);
|
||||||
|
|
||||||
|
|
||||||
|
i2cStart(&I2C_DRIVER, &slaveI2Cconfig);
|
||||||
|
#if HAL_USE_I2C_SLAVE
|
||||||
|
I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message
|
||||||
|
#endif
|
||||||
|
|
||||||
|
i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply);
|
||||||
|
|
||||||
|
// Enable match address after everything else set up
|
||||||
|
i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2);
|
||||||
|
// i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2);
|
||||||
|
// i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */
|
||||||
|
|
||||||
|
printf("Slave I2C started\n\r");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void twi2c_slave_task(void) {
|
||||||
|
if (gotI2cError) {
|
||||||
|
gotI2cError = 0;
|
||||||
|
printf("I2cError: %04x\r\n", lastI2cErrorFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -539,7 +539,7 @@
|
|||||||
PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
|
PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
|
||||||
PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
|
PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
|
||||||
PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
|
PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
|
||||||
PIN_PUPDR_PULLUP(GPIOC_PIN13) | \
|
PIN_PUPDR_FLOATING(GPIOC_PIN13) | \
|
||||||
PIN_PUPDR_FLOATING(GPIOC_PIN14) | \
|
PIN_PUPDR_FLOATING(GPIOC_PIN14) | \
|
||||||
PIN_PUPDR_FLOATING(GPIOC_PIN15))
|
PIN_PUPDR_FLOATING(GPIOC_PIN15))
|
||||||
#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
|
#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
|
||||||
@ -1164,7 +1164,7 @@
|
|||||||
/*
|
/*
|
||||||
* USB bus activation macro, required by the USB driver.
|
* USB bus activation macro, required by the USB driver.
|
||||||
*/
|
*/
|
||||||
// #define usb_lld_connect_bus(usbp)
|
// #define usb_lld_connect_bus(usbp)
|
||||||
#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)))
|
#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)))
|
||||||
// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT)
|
// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT)
|
||||||
/*
|
/*
|
||||||
|
@ -126,8 +126,11 @@
|
|||||||
/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
|
/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
|
||||||
//#define MIDI_TONE_KEYCODE_OCTAVES 1
|
//#define MIDI_TONE_KEYCODE_OCTAVES 1
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Backlight configuration
|
/* Backlight configuration
|
||||||
*/
|
*/
|
||||||
#define BACKLIGHT_LEVELS 1
|
#define BACKLIGHT_LEVELS 1
|
||||||
|
|
||||||
|
#define NO_USB_STARTUP_CHECK
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -79,6 +79,13 @@
|
|||||||
#define HAL_USE_I2C TRUE
|
#define HAL_USE_I2C TRUE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the I2C Slave subsystem.
|
||||||
|
*/
|
||||||
|
#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__)
|
||||||
|
#define HAL_USE_I2C_SLAVE TRUE
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the I2S subsystem.
|
* @brief Enables the I2S subsystem.
|
||||||
*/
|
*/
|
||||||
|
@ -34,18 +34,18 @@ enum custom_keycodes {
|
|||||||
|
|
||||||
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
[0] = KEYMAP(
|
[0] = KEYMAP(
|
||||||
KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL,
|
||||||
KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL,
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_HOME,
|
||||||
KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT,
|
KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_END,
|
||||||
KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N,
|
||||||
KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
|
KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_LGUI,
|
||||||
MO(2), MO(1), KC_SPC,
|
KC_SPC, MO(2), MO(1),
|
||||||
|
|
||||||
KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
|
KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
|
||||||
KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL,
|
KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL,
|
||||||
KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT,
|
KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT,
|
||||||
KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
|
KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
|
||||||
KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
|
KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
|
||||||
MO(2), MO(1), KC_SPC
|
MO(2), MO(1), KC_SPC
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "backlight.h"
|
#include "backlight.h"
|
||||||
#include "matrix.h"
|
#include "matrix.h"
|
||||||
|
|
||||||
|
#include "usb_main.h"
|
||||||
|
|
||||||
/* QMK Handwire
|
/* QMK Handwire
|
||||||
*
|
*
|
||||||
@ -24,6 +25,9 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS];
|
|||||||
static bool debouncing = false;
|
static bool debouncing = false;
|
||||||
static uint16_t debouncing_time = 0;
|
static uint16_t debouncing_time = 0;
|
||||||
|
|
||||||
|
static bool master = false;
|
||||||
|
static bool right_hand = false;
|
||||||
|
|
||||||
__attribute__ ((weak))
|
__attribute__ ((weak))
|
||||||
void matrix_init_user(void) {}
|
void matrix_init_user(void) {}
|
||||||
|
|
||||||
@ -44,6 +48,14 @@ void matrix_init(void) {
|
|||||||
printf("matrix init\n");
|
printf("matrix init\n");
|
||||||
//debug_matrix = true;
|
//debug_matrix = true;
|
||||||
|
|
||||||
|
// C13 is connected to VCC on the right hand
|
||||||
|
palSetPadMode(GPIOC, 13, PAL_MODE_INPUT);
|
||||||
|
wait_us(20);
|
||||||
|
right_hand = palReadPad(GPIOC, 13);
|
||||||
|
|
||||||
|
// if USB is active, this is the master
|
||||||
|
master = (USB_DRIVER.state == USB_ACTIVE);
|
||||||
|
|
||||||
/* Column(sense) */
|
/* Column(sense) */
|
||||||
palSetPadMode(GPIOA, 13, PAL_MODE_INPUT_PULLDOWN);
|
palSetPadMode(GPIOA, 13, PAL_MODE_INPUT_PULLDOWN);
|
||||||
palSetPadMode(GPIOA, 14, PAL_MODE_INPUT_PULLDOWN);
|
palSetPadMode(GPIOA, 14, PAL_MODE_INPUT_PULLDOWN);
|
||||||
@ -68,42 +80,60 @@ void matrix_init(void) {
|
|||||||
matrix_init_quantum();
|
matrix_init_quantum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matrix_row_t matrix_scan_common(uint8_t row) {
|
||||||
|
matrix_row_t data;
|
||||||
|
|
||||||
|
// strobe row { A6, A7, B0, B1, B2, B10 }
|
||||||
|
switch (row) {
|
||||||
|
case 5: palSetPad(GPIOA, 6); break;
|
||||||
|
case 4: palSetPad(GPIOA, 7); break;
|
||||||
|
case 3: palSetPad(GPIOB, 0); break;
|
||||||
|
case 2: palSetPad(GPIOB, 1); break;
|
||||||
|
case 1: palSetPad(GPIOB, 2); break;
|
||||||
|
case 0: palSetPad(GPIOB, 10); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need wait to settle pin state
|
||||||
|
wait_us(20);
|
||||||
|
|
||||||
|
// read col data { B6, B5, B4, B3, A15, A14, A13 }
|
||||||
|
data = (
|
||||||
|
(palReadPad(GPIOB, 6) << 6 ) |
|
||||||
|
(palReadPad(GPIOB, 5) << 5 ) |
|
||||||
|
(palReadPad(GPIOB, 4) << 4 ) |
|
||||||
|
(palReadPad(GPIOB, 3) << 3 ) |
|
||||||
|
(palReadPad(GPIOA, 15) << 2 ) |
|
||||||
|
(palReadPad(GPIOA, 14) << 1 ) |
|
||||||
|
(palReadPad(GPIOA, 13) << 0 )
|
||||||
|
);
|
||||||
|
|
||||||
|
// unstrobe row { A6, A7, B0, B1, B2, B10 }
|
||||||
|
switch (row) {
|
||||||
|
case 5: palClearPad(GPIOA, 6); break;
|
||||||
|
case 4: palClearPad(GPIOA, 7); break;
|
||||||
|
case 3: palClearPad(GPIOB, 0); break;
|
||||||
|
case 2: palClearPad(GPIOB, 1); break;
|
||||||
|
case 1: palClearPad(GPIOB, 2); break;
|
||||||
|
case 0: palClearPad(GPIOB, 10); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t matrix_scan_master(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t matrix_scan_slave(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t matrix_scan(void) {
|
uint8_t matrix_scan(void) {
|
||||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
for (int row = 0; row < MATRIX_ROWS; row++) {
|
||||||
matrix_row_t data = 0;
|
matrix_row_t data = 0;
|
||||||
|
|
||||||
// strobe row { A6, A7, B0, B1, B2, B10 }
|
if (right_hand && row >= 6) {
|
||||||
switch (row) {
|
data = matrix_scan_common(row % 6);
|
||||||
case 5: palSetPad(GPIOA, 6); break;
|
|
||||||
case 4: palSetPad(GPIOA, 7); break;
|
|
||||||
case 3: palSetPad(GPIOB, 0); break;
|
|
||||||
case 2: palSetPad(GPIOB, 1); break;
|
|
||||||
case 1: palSetPad(GPIOB, 2); break;
|
|
||||||
case 0: palSetPad(GPIOB, 10); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need wait to settle pin state
|
|
||||||
wait_us(20);
|
|
||||||
|
|
||||||
// read col data { B6, B5, B4, B3, A15, A14, A13 }
|
|
||||||
data = (
|
|
||||||
(palReadPad(GPIOB, 6) << 6 ) |
|
|
||||||
(palReadPad(GPIOB, 5) << 5 ) |
|
|
||||||
(palReadPad(GPIOB, 4) << 4 ) |
|
|
||||||
(palReadPad(GPIOB, 3) << 3 ) |
|
|
||||||
(palReadPad(GPIOA, 15) << 2 ) |
|
|
||||||
(palReadPad(GPIOA, 14) << 1 ) |
|
|
||||||
(palReadPad(GPIOA, 13) << 0 )
|
|
||||||
);
|
|
||||||
|
|
||||||
// unstrobe row { A6, A7, B0, B1, B2, B10 }
|
|
||||||
switch (row) {
|
|
||||||
case 5: palClearPad(GPIOA, 6); break;
|
|
||||||
case 4: palClearPad(GPIOA, 7); break;
|
|
||||||
case 3: palClearPad(GPIOB, 0); break;
|
|
||||||
case 2: palClearPad(GPIOB, 1); break;
|
|
||||||
case 1: palClearPad(GPIOB, 2); break;
|
|
||||||
case 0: palClearPad(GPIOB, 10); break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matrix_debouncing[row] != data) {
|
if (matrix_debouncing[row] != data) {
|
||||||
|
@ -53,3 +53,4 @@ NKRO_ENABLE = yes # USB Nkey Rollover
|
|||||||
CUSTOM_MATRIX = yes # Custom matrix file
|
CUSTOM_MATRIX = yes # Custom matrix file
|
||||||
AUDIO_ENABLE = yes
|
AUDIO_ENABLE = yes
|
||||||
# SERIAL_LINK_ENABLE = yes
|
# SERIAL_LINK_ENABLE = yes
|
||||||
|
I2C_SLAVE_ENABLE = yes
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 587968d6cbc2b0e1c7147540872f2a67e59ca18b
|
Subproject commit f9643c88ad5cd0704d57bed83fe64f45b3e6be4e
|
@ -9,11 +9,9 @@ SIZE = avr-size
|
|||||||
AR = avr-ar rcs
|
AR = avr-ar rcs
|
||||||
NM = avr-nm
|
NM = avr-nm
|
||||||
HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
|
HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
|
||||||
EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
|
EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
|
||||||
BIN =
|
BIN =
|
||||||
|
|
||||||
COMMON_VPATH += $(DRIVER_PATH)/avr
|
|
||||||
|
|
||||||
COMPILEFLAGS += -funsigned-char
|
COMPILEFLAGS += -funsigned-char
|
||||||
COMPILEFLAGS += -funsigned-bitfields
|
COMPILEFLAGS += -funsigned-bitfields
|
||||||
COMPILEFLAGS += -ffunction-sections
|
COMPILEFLAGS += -ffunction-sections
|
||||||
@ -126,14 +124,14 @@ program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep check-size
|
|||||||
|
|
||||||
teensy: $(BUILD_DIR)/$(TARGET).hex check-size
|
teensy: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||||
$(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
|
$(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
|
||||||
|
|
||||||
BATCHISP ?= batchisp
|
BATCHISP ?= batchisp
|
||||||
|
|
||||||
flip: $(BUILD_DIR)/$(TARGET).hex check-size
|
flip: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||||
$(BATCHISP) -hardware usb -device $(MCU) -operation erase f
|
$(BATCHISP) -hardware usb -device $(MCU) -operation erase f
|
||||||
$(BATCHISP) -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
|
$(BATCHISP) -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
|
||||||
$(BATCHISP) -hardware usb -device $(MCU) -operation start reset 0
|
$(BATCHISP) -hardware usb -device $(MCU) -operation start reset 0
|
||||||
|
|
||||||
DFU_PROGRAMMER ?= dfu-programmer
|
DFU_PROGRAMMER ?= dfu-programmer
|
||||||
|
|
||||||
dfu: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
|
dfu: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
|
||||||
@ -194,7 +192,7 @@ bin: $(BUILD_DIR)/$(TARGET).hex
|
|||||||
|
|
||||||
# copy bin to FLASH.bin
|
# copy bin to FLASH.bin
|
||||||
flashbin: bin
|
flashbin: bin
|
||||||
$(COPY) $(BUILD_DIR)/$(TARGET).bin FLASH.bin;
|
$(COPY) $(BUILD_DIR)/$(TARGET).bin FLASH.bin;
|
||||||
|
|
||||||
# Generate avr-gdb config/init file which does the following:
|
# Generate avr-gdb config/init file which does the following:
|
||||||
# define the reset signal, load the target file, connect to target, and set
|
# define the reset signal, load the target file, connect to target, and set
|
||||||
@ -245,7 +243,7 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf
|
|||||||
@$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof
|
@$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof
|
||||||
$(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
|
$(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
|
||||||
|
|
||||||
bootloader:
|
bootloader:
|
||||||
make -C lib/lufa/Bootloaders/DFU/ clean
|
make -C lib/lufa/Bootloaders/DFU/ clean
|
||||||
echo "#ifndef QMK_KEYBOARD\n#define QMK_KEYBOARD\n" > lib/lufa/Bootloaders/DFU/Keyboard.h
|
echo "#ifndef QMK_KEYBOARD\n#define QMK_KEYBOARD\n" > lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||||
echo `grep "MANUFACTURER" $(ALL_CONFIGS) -h | tail -1` >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
echo `grep "MANUFACTURER" $(ALL_CONFIGS) -h | tail -1` >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||||
|
@ -135,7 +135,10 @@ int main(void) {
|
|||||||
|
|
||||||
/* Wait until the USB or serial link is active */
|
/* Wait until the USB or serial link is active */
|
||||||
while (true) {
|
while (true) {
|
||||||
if(USB_DRIVER.state == USB_ACTIVE) {
|
#if !defined(NO_USB_STARTUP_CHECK)
|
||||||
|
if(USB_DRIVER.state == USB_ACTIVE)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
driver = &chibios_driver;
|
driver = &chibios_driver;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user