diff options
46 files changed, 2224 insertions, 266 deletions
diff --git a/.gitignore b/.gitignore index ffa7662bd7..e40308193c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ quantum/version.h CMakeLists.txt .DS_STORE /util/wsl_downloaded +/util/win_downloaded # Eclipse/PyCharm/Other IDE Settings .cproject diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c index f9312d2dc1..bb8938bba3 100644 --- a/drivers/avr/ssd1306.c +++ b/drivers/avr/ssd1306.c @@ -1,11 +1,9 @@ #ifdef SSD1306OLED #include "ssd1306.h" -#include "config.h" #include "i2c.h" #include <string.h> #include "print.h" -#include "lets_split.h" #include "glcdfont.c" #ifdef ADAFRUIT_BLE_ENABLE #include "adafruit_ble.h" @@ -14,18 +12,7 @@ #include "lufa.h" #endif #include "sendchar.h" -#include "pincontrol.h" - -//assign the right code to your layers -#define _BASE 0 -#define _LOWER 8 -#define _RAISE 16 -#define _FNLAYER 64 -#define _NUMLAY 128 -#define _NLOWER 136 -#define _NFNLAYER 192 -#define _MOUSECURSOR 256 -#define _ADJUST 65560 +#include "timer.h" // Set this to 1 to help diagnose early startup problems // when testing power-on with ble. Turn it off otherwise, @@ -33,26 +20,6 @@ // with the matrix scan, causing keys to drop. #define DEBUG_TO_SCREEN 0 -// Controls the SSD1306 128x32 OLED display via i2c - -#define i2cAddress 0x3C - -#define DisplayHeight 32 -#define DisplayWidth 128 - -#define FontHeight 8 -#define FontWidth 6 - -#define MatrixRows (DisplayHeight / FontHeight) -#define MatrixCols (DisplayWidth / FontWidth) - -struct CharacterMatrix { - uint8_t display[MatrixRows][MatrixCols]; - uint8_t *cursor; - bool dirty; -}; - -static struct CharacterMatrix display; //static uint16_t last_battery_update; //static uint32_t vbat; //#define BatteryUpdateInterval 10000 /* milliseconds */ @@ -62,54 +29,13 @@ static uint8_t displaying; #endif static uint16_t last_flush; -enum ssd1306_cmds { - DisplayOff = 0xAE, - DisplayOn = 0xAF, - - SetContrast = 0x81, - DisplayAllOnResume = 0xA4, - - DisplayAllOn = 0xA5, - NormalDisplay = 0xA6, - InvertDisplay = 0xA7, - SetDisplayOffset = 0xD3, - SetComPins = 0xda, - SetVComDetect = 0xdb, - SetDisplayClockDiv = 0xD5, - SetPreCharge = 0xd9, - SetMultiPlex = 0xa8, - SetLowColumn = 0x00, - SetHighColumn = 0x10, - SetStartLine = 0x40, - - SetMemoryMode = 0x20, - ColumnAddr = 0x21, - PageAddr = 0x22, - - ComScanInc = 0xc0, - ComScanDec = 0xc8, - SegRemap = 0xa0, - SetChargePump = 0x8d, - ExternalVcc = 0x01, - SwitchCapVcc = 0x02, - - ActivateScroll = 0x2f, - DeActivateScroll = 0x2e, - SetVerticalScrollArea = 0xa3, - RightHorizontalScroll = 0x26, - LeftHorizontalScroll = 0x27, - VerticalAndRightHorizontalScroll = 0x29, - VerticalAndLeftHorizontalScroll = 0x2a, -}; - - // Write command sequence. // Returns true on success. static inline bool _send_cmd1(uint8_t cmd) { bool res = false; - if (i2c_start_write(i2cAddress)) { - xprintf("failed to start write to %d\n", i2cAddress); + if (i2c_start_write(SSD1306_ADDRESS)) { + xprintf("failed to start write to %d\n", SSD1306_ADDRESS); goto done; } @@ -154,8 +80,6 @@ static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { #define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} #define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} -static void matrix_clear(struct CharacterMatrix *matrix); - static void clear_display(void) { matrix_clear(&display); @@ -164,7 +88,7 @@ static void clear_display(void) { send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); send_cmd3(ColumnAddr, 0, DisplayWidth - 1); - if (i2c_start_write(i2cAddress)) { + if (i2c_start_write(SSD1306_ADDRESS)) { goto done; } if (i2c_master_write(0x40)) { @@ -210,14 +134,17 @@ bool iota_gfx_init(void) { send_cmd2(SetChargePump, 0x14 /* Enable */); send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); -/// Flips the display orientation 0 degrees - send_cmd1(SegRemap | 0x1); - send_cmd1(ComScanDec); -/* +#ifdef OLED_ROTATE180 // the following Flip the display orientation 180 degrees send_cmd1(SegRemap); send_cmd1(ComScanInc); -// end flip */ +#endif +#ifndef OLED_ROTATE180 +// Flips the display orientation 0 degrees + send_cmd1(SegRemap | 0x1); + send_cmd1(ComScanDec); +#endif + send_cmd2(SetComPins, 0x2); send_cmd2(SetContrast, 0x8f); send_cmd2(SetPreCharge, 0xf1); @@ -263,7 +190,7 @@ done: return success; } -static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { +void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { *matrix->cursor = c; ++matrix->cursor; @@ -276,7 +203,7 @@ static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { } } -static void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { matrix->dirty = true; if (c == '\n') { @@ -297,7 +224,7 @@ void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } -static void matrix_write(struct CharacterMatrix *matrix, const char *data) { +void matrix_write(struct CharacterMatrix *matrix, const char *data) { const char *end = data + strlen(data); while (data < end) { matrix_write_char(matrix, *data); @@ -309,7 +236,7 @@ void iota_gfx_write(const char *data) { matrix_write(&display, data); } -static void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { +void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { while (true) { uint8_t c = pgm_read_byte(data); if (c == 0) { @@ -324,7 +251,7 @@ void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } -static void matrix_clear(struct CharacterMatrix *matrix) { +void matrix_clear(struct CharacterMatrix *matrix) { memset(matrix->display, ' ', sizeof(matrix->display)); matrix->cursor = &matrix->display[0][0]; matrix->dirty = true; @@ -334,7 +261,7 @@ void iota_gfx_clear_screen(void) { matrix_clear(&display); } -static void matrix_render(struct CharacterMatrix *matrix) { +void matrix_render(struct CharacterMatrix *matrix) { last_flush = timer_read(); iota_gfx_on(); #if DEBUG_TO_SCREEN @@ -345,7 +272,7 @@ static void matrix_render(struct CharacterMatrix *matrix) { send_cmd3(PageAddr, 0, MatrixRows - 1); send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); - if (i2c_start_write(i2cAddress)) { + if (i2c_start_write(SSD1306_ADDRESS)) { goto done; } if (i2c_master_write(0x40)) { @@ -380,84 +307,12 @@ void iota_gfx_flush(void) { matrix_render(&display); } -static void matrix_update(struct CharacterMatrix *dest, - const struct CharacterMatrix *source) { - if (memcmp(dest->display, source->display, sizeof(dest->display))) { - memcpy(dest->display, source->display, sizeof(dest->display)); - dest->dirty = true; - } -} - -static void render_status_info(void) { -#if DEBUG_TO_SCREEN - if (debug_enable) { - return; - } -#endif - - struct CharacterMatrix matrix; - - matrix_clear(&matrix); - matrix_write_P(&matrix, PSTR("USB: ")); -#ifdef PROTOCOL_LUFA - switch (USB_DeviceState) { - case DEVICE_STATE_Unattached: - matrix_write_P(&matrix, PSTR("Unattached")); - break; - case DEVICE_STATE_Suspended: - matrix_write_P(&matrix, PSTR("Suspended")); - break; - case DEVICE_STATE_Configured: - matrix_write_P(&matrix, PSTR("Connected")); - break; - case DEVICE_STATE_Powered: - matrix_write_P(&matrix, PSTR("Powered")); - break; - case DEVICE_STATE_Default: - matrix_write_P(&matrix, PSTR("Default")); - break; - case DEVICE_STATE_Addressed: - matrix_write_P(&matrix, PSTR("Addressed")); - break; - default: - matrix_write_P(&matrix, PSTR("Invalid")); - } -#endif - -// Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below - - char buf[40]; - snprintf(buf,sizeof(buf), "Undef-%ld", layer_state); - matrix_write_P(&matrix, PSTR("\n\nLayer: ")); - switch (layer_state) { - case _BASE: - matrix_write_P(&matrix, PSTR("Default")); - break; - case _RAISE: - matrix_write_P(&matrix, PSTR("Raise")); - break; - case _LOWER: - matrix_write_P(&matrix, PSTR("Lower")); - break; - case _ADJUST: - matrix_write_P(&matrix, PSTR("ADJUST")); - break; - default: - matrix_write(&matrix, buf); - } - - // Host Keyboard LED Status - char led[40]; - snprintf(led, sizeof(led), "\n%s %s %s", - (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : " ", - (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : " ", - (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : " "); - matrix_write(&matrix, led); - matrix_update(&display, &matrix); +__attribute__ ((weak)) +void iota_gfx_task_user(void) { } void iota_gfx_task(void) { - render_status_info(); + iota_gfx_task_user(); if (display.dirty) { iota_gfx_flush(); diff --git a/drivers/avr/ssd1306.h b/drivers/avr/ssd1306.h index b0c74f987e..df6a75359f 100644 --- a/drivers/avr/ssd1306.h +++ b/drivers/avr/ssd1306.h @@ -3,6 +3,71 @@ #include <stdbool.h> #include <stdio.h> +#include "pincontrol.h" +#include "config.h" + +enum ssd1306_cmds { + DisplayOff = 0xAE, + DisplayOn = 0xAF, + + SetContrast = 0x81, + DisplayAllOnResume = 0xA4, + + DisplayAllOn = 0xA5, + NormalDisplay = 0xA6, + InvertDisplay = 0xA7, + SetDisplayOffset = 0xD3, + SetComPins = 0xda, + SetVComDetect = 0xdb, + SetDisplayClockDiv = 0xD5, + SetPreCharge = 0xd9, + SetMultiPlex = 0xa8, + SetLowColumn = 0x00, + SetHighColumn = 0x10, + SetStartLine = 0x40, + + SetMemoryMode = 0x20, + ColumnAddr = 0x21, + PageAddr = 0x22, + + ComScanInc = 0xc0, + ComScanDec = 0xc8, + SegRemap = 0xa0, + SetChargePump = 0x8d, + ExternalVcc = 0x01, + SwitchCapVcc = 0x02, + + ActivateScroll = 0x2f, + DeActivateScroll = 0x2e, + SetVerticalScrollArea = 0xa3, + RightHorizontalScroll = 0x26, + LeftHorizontalScroll = 0x27, + VerticalAndRightHorizontalScroll = 0x29, + VerticalAndLeftHorizontalScroll = 0x2a, +}; + +// Controls the SSD1306 128x32 OLED display via i2c + +#ifndef SSD1306_ADDRESS +#define SSD1306_ADDRESS 0x3C +#endif + +#define DisplayHeight 32 +#define DisplayWidth 128 + +#define FontHeight 8 +#define FontWidth 6 + +#define MatrixRows (DisplayHeight / FontHeight) +#define MatrixCols (DisplayWidth / FontWidth) + +struct CharacterMatrix { + uint8_t display[MatrixRows][MatrixCols]; + uint8_t *cursor; + bool dirty; +}; + +struct CharacterMatrix display; bool iota_gfx_init(void); void iota_gfx_task(void); @@ -14,4 +79,15 @@ void iota_gfx_write(const char *data); void iota_gfx_write_P(const char *data); void iota_gfx_clear_screen(void); +void iota_gfx_task_user(void); + +void matrix_clear(struct CharacterMatrix *matrix); +void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write(struct CharacterMatrix *matrix, const char *data); +void matrix_write_P(struct CharacterMatrix *matrix, const char *data); +void matrix_render(struct CharacterMatrix *matrix); + + + #endif diff --git a/keyboards/hadron/Makefile b/keyboards/hadron/Makefile new file mode 100644 index 0000000000..e0e1cc6fb6 --- /dev/null +++ b/keyboards/hadron/Makefile @@ -0,0 +1,5 @@ +SUBPROJECT_DEFAULT = ver2 + +ifndef MAKEFILE_INCLUDED + include ../../Makefile +endif
\ No newline at end of file diff --git a/keyboards/hadron/config.h b/keyboards/hadron/config.h new file mode 100644 index 0000000000..0c19d6c791 --- /dev/null +++ b/keyboards/hadron/config.h @@ -0,0 +1,83 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +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/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6060 +#define MANUFACTURER ishtob +#define PRODUCT Hadron Keyboard +#define DESCRIPTION A cherry ML ortholinear keyboard + + + + +//#define AUDIO_VOICES + +//#define BACKLIGHT_PIN B7 + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* number of backlight levels */ +//#define BACKLIGHT_LEVELS 3 + +/* Set 0 if debouncing isn't needed */ +#define DEBOUNCING_DELAY 5 + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +#define LOCKING_RESYNC_ENABLE + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION +#ifdef SUBPROJECT_ver0 + #include "ver0/config.h" +#endif +#ifdef SUBPROJECT_ver2 + #include "ver2/config.h" +#endif + +#endif diff --git a/keyboards/hadron/hadron.c b/keyboards/hadron/hadron.c new file mode 100644 index 0000000000..ca5b20e894 --- /dev/null +++ b/keyboards/hadron/hadron.c @@ -0,0 +1,26 @@ +#include "hadron.h" + + +void matrix_init_kb(void) { + + matrix_init_user(); +} + +void matrix_scan_kb(void) { + // put your looping keyboard code here + // runs every cycle (a lot) + matrix_scan_user(); +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + // put your per-action keyboard code here + // runs for every action, just before processing by the firmware + + return process_record_user(keycode, record); +} + +void led_set_kb(uint8_t usb_led) { + // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here + + led_set_user(usb_led); +}
\ No newline at end of file diff --git a/keyboards/hadron/hadron.h b/keyboards/hadron/hadron.h new file mode 100644 index 0000000000..fceae50d9a --- /dev/null +++ b/keyboards/hadron/hadron.h @@ -0,0 +1,30 @@ +#ifndef HADRON_H +#define HADRON_H + +#ifdef SUBPROJECT_ver0 + #include "ver0.h" +#endif +#ifdef SUBPROJECT_ver2 + #include "ver2.h" +#endif + +#include "quantum.h" + + +#define KEYMAP( \ + K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \ + K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \ + K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2E, \ + K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, K3E, \ + K40, K41, K42, K43, K44, K45, K46, K47, K48, K49, K4A, K4B, K4C, K4D, K4E \ + ) \ +{ \ + { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, KC_NO, KC_NO, KC_NO }, \ + { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \ + { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2E }, \ + { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, K3E }, \ + { K40, K41, K42, K43, K44, K45, K46, K47, K48, K49, K4A, K4B, K4C, K4D, K4E } \ +} + + +#endif diff --git a/keyboards/hadron/i2c.c b/keyboards/hadron/i2c.c new file mode 100644 index 0000000000..cd2b835d50 --- /dev/null +++ b/keyboards/hadron/i2c.c @@ -0,0 +1,166 @@ +#include <util/twi.h> +#include <avr/io.h> +#include <stdlib.h> +#include <avr/interrupt.h> +#include <util/twi.h> +#include <stdbool.h> +#include "i2c.h" + +#ifdef USE_I2C + +// Limits the amount of we wait for any one i2c transaction. +// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is +// 9 bits, a single transaction will take around 90μs to complete. +// +// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit +// poll loop takes at least 8 clock cycles to execute +#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8 + +#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE) + +volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; + +static volatile uint8_t slave_buffer_pos; +static volatile bool slave_has_register_set = false; + +// Wait for an i2c operation to finish +inline static +void i2c_delay(void) { + uint16_t lim = 0; + while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT) + lim++; + + // easier way, but will wait slightly longer + // _delay_us(100); +} + +// Setup twi to run at 100kHz +void i2c_master_init(void) { + // no prescaler + TWSR = 0; + // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10. + // Check datasheets for more info. + TWBR = ((F_CPU/SCL_CLOCK)-16)/2; +} + +// Start a transaction with the given i2c slave address. The direction of the +// transfer is set with I2C_READ and I2C_WRITE. +// returns: 0 => success +// 1 => error +uint8_t i2c_master_start(uint8_t address) { + TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); + + i2c_delay(); + + // check that we started successfully + if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)) + return 1; + + // send device address + TWDR = address; + TWCR = (1<<TWINT) | (1<<TWEN); + + i2c_delay(); + + if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) ) + return 1; // slave did not acknowledge + else + return 0; // success +} + + +// Finish the i2c transaction. +void i2c_master_stop(void) { + TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); + + uint16_t lim = 0; + while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT) + lim++; +} + +// Write one byte to the i2c slave. +// returns 0 => slave ACK +// 1 => slave NACK +uint8_t i2c_master_write(uint8_t data) { + TWDR = data; + TWCR = (1<<TWINT) | (1<<TWEN); + + i2c_delay(); + + // check if the slave acknowledged us + return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1; +} + +// Read one byte from the i2c slave. If ack=1 the slave is acknowledged, +// if ack=0 the acknowledge bit is not set. +// returns: byte read from i2c device +uint8_t i2c_master_read(int ack) { + TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA); + + i2c_delay(); + return TWDR; +} + +void i2c_reset_state(void) { + TWCR = 0; +} + +void i2c_slave_init(uint8_t address) { + TWAR = address << 0; // slave i2c address + // TWEN - twi enable + // TWEA - enable address acknowledgement + // TWINT - twi interrupt flag + // TWIE - enable the twi interrupt + TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN); +} + +ISR(TWI_vect); + +ISR(TWI_vect) { + uint8_t ack = 1; + switch(TW_STATUS) { + case TW_SR_SLA_ACK: + // this device has been addressed as a slave receiver + slave_has_register_set = false; + break; + + case TW_SR_DATA_ACK: + // this device has received data as a slave receiver + // The first byte that we receive in this transaction sets the location + // of the read/write location of the slaves memory that it exposes over + // i2c. After that, bytes will be written at slave_buffer_pos, incrementing + // slave_buffer_pos after each write. + if(!slave_has_register_set) { + slave_buffer_pos = TWDR; + // don't acknowledge the master if this memory loctaion is out of bounds + if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) { + ack = 0; + slave_buffer_pos = 0; + } + slave_has_register_set = true; + } else { + i2c_slave_buffer[slave_buffer_pos] = TWDR; + BUFFER_POS_INC(); + } + break; + + case TW_ST_SLA_ACK: + case TW_ST_DATA_ACK: + // master has addressed this device as a slave transmitter and is + // requesting data. + TWDR = i2c_slave_buffer[slave_buffer_pos]; + BUFFER_POS_INC(); + break; + + case TW_BUS_ERROR: // something went wrong, reset twi state + TWCR = 0; + default: + break; + } + // Reset everything, so we are ready for the next TWI interrupt + TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN); +} + + + +#endif diff --git a/keyboards/hadron/i2c.h b/keyboards/hadron/i2c.h new file mode 100644 index 0000000000..2bd7f40968 --- /dev/null +++ b/keyboards/hadron/i2c.h @@ -0,0 +1,49 @@ +#ifndef I2C_H +#define I2C_H + +#include <stdint.h> + +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +#define I2C_READ 1 +#define I2C_WRITE 0 + +#define I2C_ACK 1 +#define I2C_NACK 0 + +#define SLAVE_BUFFER_SIZE 0x10 + +// i2c SCL clock frequency +#define SCL_CLOCK 800000L + +extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; + +void i2c_master_init(void); +uint8_t i2c_master_start(uint8_t address); +void i2c_master_stop(void); +uint8_t i2c_master_write(uint8_t data); +uint8_t i2c_master_read(int); +void i2c_reset_state(void); +void i2c_slave_init(uint8_t address); + + +static inline unsigned char i2c_start_read(unsigned char addr) { + return i2c_master_start((addr << 1) | I2C_READ); +} + +static inline unsigned char i2c_start_write(unsigned char addr) { + return i2c_master_start((addr << 1) | I2C_WRITE); +} + +// from SSD1306 scrips +extern unsigned char i2c_rep_start(unsigned char addr); +extern void i2c_start_wait(unsigned char addr); +extern unsigned char i2c_readAck(void); +extern unsigned char i2c_readNak(void); +extern unsigned char i2c_read(unsigned char ack); + +#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); + +#endif |