aboutsummaryrefslogtreecommitdiff
path: root/keyboards
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards')
-rw-r--r--keyboards/handwired/frenchdev/Makefile3
-rw-r--r--keyboards/handwired/frenchdev/config.h85
-rw-r--r--keyboards/handwired/frenchdev/frenchdev.c87
-rw-r--r--keyboards/handwired/frenchdev/frenchdev.h115
-rw-r--r--keyboards/handwired/frenchdev/i2cmaster.h178
-rw-r--r--keyboards/handwired/frenchdev/keymaps/default/keymap.c409
-rw-r--r--keyboards/handwired/frenchdev/keymaps/default/readme.md13
-rw-r--r--keyboards/handwired/frenchdev/matrix.c396
-rw-r--r--keyboards/handwired/frenchdev/readme.md102
-rw-r--r--keyboards/handwired/frenchdev/rules.mk92
-rw-r--r--keyboards/handwired/frenchdev/twimaster.c208
11 files changed, 1688 insertions, 0 deletions
diff --git a/keyboards/handwired/frenchdev/Makefile b/keyboards/handwired/frenchdev/Makefile
new file mode 100644
index 000000000..57b2ef62e
--- /dev/null
+++ b/keyboards/handwired/frenchdev/Makefile
@@ -0,0 +1,3 @@
1ifndef MAKEFILE_INCLUDED
2 include ../../Makefile
3endif
diff --git a/keyboards/handwired/frenchdev/config.h b/keyboards/handwired/frenchdev/config.h
new file mode 100644
index 000000000..dd386402c
--- /dev/null
+++ b/keyboards/handwired/frenchdev/config.h
@@ -0,0 +1,85 @@
1/*
2Copyright 201 Nicolas Poirey <nicolas.poirey@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef FRENCHDEV_V1_CONFIG_H
19#define FRENCHDEV_V1_CONFIG_H
20
21#include "config_common.h"
22
23/* USB Device descriptor parameter */
24#define VENDOR_ID 0xFEED
25#define PRODUCT_ID 0x1307
26#define DEVICE_VER 0x0001
27#define MANUFACTURER Nicolas Poirey
28#define PRODUCT Frenchdev V1
29#define DESCRIPTION QMK keyboard firmware for Frenchdev
30
31/* key matrix size */
32#define MATRIX_ROWS 16
33#define MATRIX_COLS 6
34
35/* number of backlight levels */
36#define BACKLIGHT_LEVELS 3
37
38#define LED_BRIGHTNESS_LO 15
39#define LED_BRIGHTNESS_HI 255
40
41/* Set 0 if debouncing isn't needed */
42#define DEBOUNCE 5
43
44#define USB_MAX_POWER_CONSUMPTION 500
45
46#define MOUSEKEY_INTERVAL 20
47#define MOUSEKEY_DELAY 0
48#define MOUSEKEY_TIME_TO_MAX 5
49#define MOUSEKEY_MAX_SPEED 2
50#define MOUSEKEY_WHEEL_DELAY 0
51
52#define TAPPING_TOGGLE 1
53
54/* define if matrix has ghost */
55//#define MATRIX_HAS_GHOST
56
57#define TAPPING_TERM 200
58#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
59
60/* key combination for command */
61#define IS_COMMAND() ( \
62 keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
63 keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
64)
65
66/*
67 * Feature disable options
68 * These options are also useful to firmware size reduction.
69 */
70
71/* disable debug print */
72// #define NO_DEBUG
73
74/* disable print */
75// #define NO_PRINT
76
77/* disable action features */
78//#define NO_ACTION_LAYER
79//#define NO_ACTION_TAPPING
80//#define NO_ACTION_ONESHOT
81//#define NO_ACTION_MACRO
82//#define NO_ACTION_FUNCTION
83//#define DEBUG_MATRIX_SCAN_RATE
84
85#endif //FRENCHDEV_V1_CONFIG_H
diff --git a/keyboards/handwired/frenchdev/frenchdev.c b/keyboards/handwired/frenchdev/frenchdev.c
new file mode 100644
index 000000000..6d5883a3a
--- /dev/null
+++ b/keyboards/handwired/frenchdev/frenchdev.c
@@ -0,0 +1,87 @@
1#include "frenchdev.h"
2#include "i2cmaster.h"
3
4bool i2c_initialized = 0;
5uint8_t mcp23018_status = 0x20;
6
7void matrix_init_kb(void) {
8 // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
9 TCCR1A = 0b10101001; // set and configure fast PWM
10 TCCR1B = 0b00001001; // set and configure fast PWM
11
12
13
14 // unused pins - D4, D5, D7, E6
15 // set as input with internal pull-ip enabled
16 DDRD &= ~(1<<5 | 1<<4);
17 DDRE &= ~(1<<6);
18 PORTD |= (1<<5 | 1<<4);
19 PORTE |= (1<<6);
20
21 frenchdev_blink_all_leds();
22 frenchdev_blink_all_leds();
23 frenchdev_blink_all_leds();
24 frenchdev_blink_all_leds();
25
26 matrix_init_user();
27}
28
29void frenchdev_blink_all_leds(void)
30{
31 frenchdev_led_all_off();
32 frenchdev_led_all_set(LED_BRIGHTNESS_HI);
33 frenchdev_led_1_on();
34 _delay_ms(50);
35 frenchdev_led_2_on();
36 _delay_ms(50);
37 frenchdev_led_3_on();
38 _delay_ms(50);
39 frenchdev_led_1_off();
40 _delay_ms(50);
41 frenchdev_led_2_off();
42 _delay_ms(50);
43 frenchdev_led_3_off();
44 frenchdev_led_all_off();
45}
46
47uint8_t init_mcp23018(void) {
48 mcp23018_status = 0x20;
49
50 // I2C subsystem
51
52 // uint8_t sreg_prev;
53 // sreg_prev=SREG;
54 // cli();
55 if (i2c_initialized == 0) {
56 i2c_init(); // on pins D(1,0)
57 i2c_initialized++;
58 _delay_ms(1000);
59 }
60
61 // set pin direction
62 // - unused : input : 1
63 // - input : input : 1
64 // - driving : output : 0
65 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
66 mcp23018_status = i2c_write(IODIRA); if (mcp23018_status) goto out;
67 mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
68 mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
69 i2c_stop();
70
71 // set pull-up
72 // - unused : on : 1
73 // - input : on : 1
74 // - driving : off : 0
75 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
76 mcp23018_status = i2c_write(GPPUA); if (mcp23018_status) goto out;
77 mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
78 mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
79
80out:
81 i2c_stop();
82
83 // SREG=sreg_prev;
84
85 return mcp23018_status;
86}
87
diff --git a/keyboards/handwired/frenchdev/frenchdev.h b/keyboards/handwired/frenchdev/frenchdev.h
new file mode 100644
index 000000000..82121e044
--- /dev/null
+++ b/keyboards/handwired/frenchdev/frenchdev.h
@@ -0,0 +1,115 @@
1#ifndef FRENCHDEV_V1_H
2#define FRENCHDEV_V1_H
3
4#include "quantum.h"
5#include <stdint.h>
6#include <stdbool.h>
7#include "i2cmaster.h"
8#include <util/delay.h>
9
10#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
11#define CPU_16MHz 0x00
12
13// I2C aliases and register addresses (see "mcp23018.md" on tmk repository)
14#define I2C_ADDR 0b0100000
15#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
16#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
17#define IODIRA 0x00 // i/o direction register
18#define IODIRB 0x01
19#define GPPUA 0x0C // GPIO pull-up resistor register
20#define GPPUB 0x0D
21#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
22#define GPIOB 0x13
23#define OLATA 0x14 // output latch register
24#define OLATB 0x15
25
26extern uint8_t mcp23018_status;
27
28void init_frenchdev(void);
29void frenchdev_blink_all_leds(void);
30uint8_t init_mcp23018(void);
31
32#define LED_BRIGHTNESS_LO 15
33#define LED_BRIGHTNESS_HI 255
34
35
36inline void frenchdev_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); }
37inline void frenchdev_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); }
38inline void frenchdev_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); }
39inline void frenchdev_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); }
40inline void frenchdev_led_on(uint8_t led) { DDRB |= (1<<(led+4)); PORTB |= (1<<(led+4)); }
41
42inline void frenchdev_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); }
43inline void frenchdev_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); }
44inline void frenchdev_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); }
45inline void frenchdev_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); }
46inline void frenchdev_led_off(uint8_t led) { DDRB &= ~(1<<(led+4)); PORTB &= ~(1<<(led+4)); }
47
48inline void frenchdev_led_all_on(void)
49{
50 frenchdev_board_led_on();
51 frenchdev_led_1_on();
52 frenchdev_led_2_on();
53 frenchdev_led_3_on();
54}
55
56inline void frenchdev_led_all_off(void)
57{
58 frenchdev_board_led_off();
59 frenchdev_led_1_off();
60 frenchdev_led_2_off();
61 frenchdev_led_3_off();
62}
63
64inline void frenchdev_led_1_set(uint8_t n) { OCR1A = n; }
65inline void frenchdev_led_2_set(uint8_t n) { OCR1B = n; }
66inline void frenchdev_led_3_set(uint8_t n) { OCR1C = n; }
67inline void frenchdev_led_set(uint8_t led, uint8_t n) {
68 (led == 1) ? (OCR1A = n) :
69 (led == 2) ? (OCR1B = n) :
70 (OCR1C = n);
71}
72
73inline void frenchdev_led_all_set(uint8_t n)
74{
75 frenchdev_led_1_set(n);
76 frenchdev_led_2_set(n);
77 frenchdev_led_3_set(n);
78}
79
80#define KEYMAP( \
81 \
82 k01, k02, k03, k04, k05, k06, k09, k0a, k0b, k0c, k0d, k0e, \
83 k10, k11, k12, k13, k14, k15, k16, k19, k1a, k1b, k1c, k1d, k1e, k1f, \
84 k20, k21, k22, k23, k24, k25, k26, k29, k2a, k2b, k2c, k2d, k2e, k2f, \
85 k30, k31, k32, k33, k34, k35, k36, k39, k3a, k3b, k3c, k3d, k3e, k3f, \
86 k40, k41, k42, k43, k44, k45, k46, k47, k37, k38, k48, k49, k4a, k4b, k4c, k4d, k4e, k4f, \
87 k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k5a, k5b, k5c, k5d, k5e, k5f, \
88 \
89 PL1, PL2, PL3, \
90 PR1, PR2, PR3 \
91 ) \
92 \
93 /* matrix positions, inverted left and right for I2C to be on row 0-7 */\
94 { \
95 \
96 { k5f, k4f, k3f, k2f, k1f, KC_NO}, \
97 { k5e, k4e, k3e, k2e, k1e, k0e }, \
98 { k5d, k4d, k3d, k2d, k1d, k0d }, \
99 { k5c, k4c, k3c, k2c, k1c, k0c }, \
100 { k5b, k4b, k3b, k2b, k1b, k0b }, \
101 { k5a, k4a, k3a, k2a, k1a, k0a }, \
102 { k59, k49, k39, k29, k19, k09 }, \
103 { k58, k48, k38, PR1, PR2, PR3 }, \
104 \
105 { k57, k47, k37, PL1, PL2, PL3 }, \
106 { k56, k46, k36, k26, k16, k06 }, \
107 { k55, k45, k35, k25, k15, k05 }, \
108 { k54, k44, k34, k24, k14, k04 }, \
109 { k53, k43, k33, k23, k13, k03 }, \
110 { k52, k42, k32, k22, k12, k02 }, \
111 { k51, k41, k31, k21, k11, k01 }, \
112 { k50, k40, k30, k20, k10, KC_NO } \
113 }
114
115#endif
diff --git a/keyboards/handwired/frenchdev/i2cmaster.h b/keyboards/handwired/frenchdev/i2cmaster.h
new file mode 100644
index 000000000..3917b9e6c
--- /dev/null
+++ b/keyboards/handwired/frenchdev/i2cmaster.h
@@ -0,0 +1,178 @@
1#ifndef _I2CMASTER_H
2#define _I2CMASTER_H 1
3/*************************************************************************
4* Title: C include file for the I2C master interface
5* (i2cmaster.S or twimaster.c)
6* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
7* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
8* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
9* Target: any AVR device
10* Usage: see Doxygen manual
11**************************************************************************/
12
13#ifdef DOXYGEN
14/**
15 @defgroup pfleury_ic2master I2C Master library
16 @code #include <i2cmaster.h> @endcode
17
18 @brief I2C (TWI) Master Software Library
19
20 Basic routines for communicating with I2C slave devices. This single master
21 implementation is limited to one bus master on the I2C bus.
22
23 This I2c library is implemented as a compact assembler software implementation of the I2C protocol
24 which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
25 Since the API for these two implementations is exactly the same, an application can be linked either against the
26 software I2C implementation or the hardware I2C implementation.
27
28 Use 4.7k pull-up resistor on the SDA and SCL pin.
29
30 Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
31 i2cmaster.S to your target when using the software I2C implementation !
32
33 Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
34
35 @note
36 The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
37 to GNU assembler and AVR-GCC C call interface.
38 Replaced the incorrect quarter period delays found in AVR300 with
39 half period delays.
40
41 @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
42
43 @par API Usage Example
44 The following code shows typical usage of this library, see example test_i2cmaster.c
45
46 @code
47
48 #include <i2cmaster.h>
49
50
51 #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
52
53 int main(void)
54 {
55 unsigned char ret;
56
57 i2c_init(); // initialize I2C library
58
59 // write 0x75 to EEPROM address 5 (Byte Write)
60 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
61 i2c_write(0x05); // write address = 5
62 i2c_write(0x75); // write value 0x75 to EEPROM
63 i2c_stop(); // set stop conditon = release bus
64
65
66 // read previously written value back from EEPROM address 5
67 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
68
69 i2c_write(0x05); // write address = 5
70 i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
71
72 ret = i2c_readNak(); // read one byte from EEPROM
73 i2c_stop();
74
75 for(;;);
76 }
77 @endcode
78
79*/
80#endif /* DOXYGEN */
81
82/**@{*/
83
84#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
85#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
86#endif
87
88#include <avr/io.h>
89
90/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
91#define I2C_READ 1
92
93/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
94#define I2C_WRITE 0
95
96
97/**
98 @brief initialize the I2C master interace. Need to be called only once
99 @param void
100 @return none
101 */
102extern void i2c_init(void);
103
104
105/**
106 @brief Terminates the data transfer and releases the I2C bus
107 @param void
108 @return none
109 */
110extern void i2c_stop(void);
111
112
113/**
114 @brief Issues a start condition and sends address and transfer direction
115
116 @param addr address and transfer direction of I2C device
117 @retval 0 device accessible
118 @retval 1 failed to access device
119 */
120extern unsigned char i2c_start(unsigned char addr);
121
122
123/**
124 @brief Issues a repeated start condition and sends address and transfer direction
125
126 @param addr address and transfer direction of I2C device
127 @retval 0 device accessible
128 @retval 1 failed to access device
129 */
130extern unsigned char i2c_rep_start(unsigned char addr);
131
132
133/**
134 @brief Issues a start condition and sends address and transfer direction
135
136 If device is busy, use ack polling to wait until device ready
137 @param addr address and transfer direction of I2C device
138 @return none
139 */
140extern void i2c_start_wait(unsigned char addr);
141
142
143/**
144 @brief Send one byte to I2C device
145 @param data byte to be transfered
146 @retval 0 write successful
147 @retval 1 write failed
148 */
149extern unsigned char i2c_write(unsigned char data);
150
151
152/**
153 @brief read one byte from the I2C device, request more data from device
154 @return byte read from I2C device
155 */
156extern unsigned char i2c_readAck(void);
157
158/**
159 @brief read one byte from the I2C device, read is followed by a stop condition
160 @return byte read from I2C device
161 */
162extern unsigned char i2c_readNak(void);
163
164/**
165 @brief read one byte from the I2C device
166
167 Implemented as a macro, which calls either i2c_readAck or i2c_readNak
168
169 @param ack 1 send ack, request more data from device<br>
170 0 send nak, read is followed by a stop condition
171 @return byte read from I2C device
172 */
173extern unsigned char i2c_read(unsigned char ack);
174#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
175
176
177/**@}*/
178#endif
diff --git a/keyboards/handwired/frenchdev/keymaps/default/keymap.c b/keyboards/handwired/frenchdev/keymaps/default/keymap.c
new file mode 100644
index 000000000..e6d72d013
--- /dev/null
+++ b/keyboards/handwired/frenchdev/keymaps/default/keymap.c
@@ -0,0 +1,409 @@
1#include "frenchdev.h"
2#include "mousekey.h"
3#include "action.h"
4#include "action_layer.h"
5#include "keymap_extras/keymap_bepo.h"
6
7
8// Each layer gets a name for readability, which is then used in the keymap matrix below.
9// The underscores don't mean anything - you can have a layer called STUFF or any other name.
10#define _BASE 0
11#define _SYMBOLS 1
12#define _MEDIA 2
13#define _TRNS 8
14
15#define PEDAL_DELAY 250
16#define KEY_DELAY 130
17
18enum macros {
19 M_LP, // left pedal
20 M_RP, // right pedal
21 M_SF, // shift
22 M_SFS, // shift and space
23 M_L1E, // L1 and space
24 L2INS, // L2 and insert
25 L2LOC, // Lock L2
26 M_UN, // undo
27 M_CUT, // cut
28 M_CP, // copy
29 M_PS, // paste
30 M_SE, // search
31 M_SFU, // shift and underscore
32};
33
34static uint16_t key_timer_left_pedal;
35static uint16_t key_timer_right_pedal;
36static uint16_t key_timer_shift;
37static uint16_t key_timer_1;
38static uint16_t key_timer_2;
39
40static uint16_t shift_count = 0; //this is used to keep track of shift state and avoid inserting non breakable space
41static uint16_t l2_locked = 0; //this indicate wether L2 is locked
42
43#define BP_CBSP CTL_T(KC_BSPC)
44#define BP_CDEL CTL_T(KC_DEL)
45
46//layout : http://www.keyboard-layout-editor.com/#/gists/4480e3ab8026eb7c710a7e22203ef4aa
47const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
48/* base
49 * left foot clicked is right click
50 * left foot pressed is layer 2
51 * right foot clicked is left click
52 * right foot pressed is layer 1 + scroll lock (used with autohotkey for easier scrolling with trackballs)
53 * ,------. .. ,------. *
54 * ,------| F3 |-------------. .. ,-------------| F10 |------. *
55 * ,------| F2 |------| F4 | F5 |------. .. ,------| F8 | F9 |------| F11 |------. *
56 * | F1 |------| »/3 |------|------| F6 | .. | F7 |------|------| -/8 |------| F12 | *
57 * ,------+------| «/2 |------| (/4 | )/5 |------| .. |------| @/6 | +/7 |------| //9 |------+------. *
58 * | ESC | "/1 |------| O |------|------| ¨ | .. | ^ |------|------| D |------| * /0 |BCKSP | *
59 * |------+------| É |------| P | È |------| .. |------| K | V |------| L |------+------| *
60 * | TAB | B |------| E |------|------| _ | .. | =/° |------|------| S |------| J |ENTER | *
61 * |------+------| U |------| I | F |------| .. |------| C | T |------| R |------+------| *
62 * | ` | A |------| Y |------|------| ; | .. | ! |------|------| UP |------| N | '/? | *
63 * |------+------| À |------| X | W |------|-------------. .. .-------------|------| M | G |------| H |------+------| *
64 * | SHIFT| Z |------| . |------|------|sp/sh |bsp/ct|L2/ins| .. |L2lock|del/CT|sp/sh |------|------| DOWN |------| Q |SHIFT | *
65 * |------+------| / |------| , | space|------|------|------ .. ------|------|------| L1/sp| LEFT |------| UP |------+------| *
66 * | CTRL | win |------/ \-------------| L1 | alt | .. | CAPS | L1 |-------------/ \------| : | CTRL | *
67 * `-------------/ \-------------/ .. \-------------/ \-------------/ *
68 *M(M_LP)
69 */
70[_BASE] = KEYMAP(
71 KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \
72 KC_ESC, BP_DQOT, BP_LGIL, BP_RGIL, BP_LPRN, BP_RPRN, BP_DTRM, BP_DCRC, BP_AT, BP_PLUS, BP_MINS, BP_SLSH, BP_ASTR, KC_BSPC, \
73 KC_TAB, BP_B, BP_ECUT, BP_O, BP_P, BP_EGRV, BP_UNDS, BP_EQL, BP_K, BP_V, BP_D, BP_L, BP_J, KC_ENT, \
74 BP_GRV, BP_A, BP_U, BP_E, BP_I, BP_F, BP_SCLN, BP_EXLM, BP_C, BP_T, BP_S, BP_R, BP_N, BP_APOS, \
75 M(M_SF), BP_Z, BP_AGRV, BP_Y, BP_X, KC_RBRACKET, M(M_SFS), BP_CBSP, M(L2INS), M(L2LOC), BP_CDEL, M(M_SFS),BP_M, BP_G, KC_UP, BP_H, BP_Q, M(M_SF), \
76 KC_LCTL, KC_LGUI, KC_PSLS, BP_DOT, BP_COMM, KC_SPACE,M(M_L1E), KC_LALT, KC_CAPS, M(M_L1E),KC_SPACE,KC_LEFT, KC_DOWN, KC_RIGHT,BP_COLN, KC_RCTL, \
77 //left pedals
78 M(M_LP), M(M_RP), KC_TRNS, \
79 //right pedals
80 M(M_LP), M(M_RP), KC_TRNS \
81),
82
83 /* Larer 1 for symbols.
84 * left foot is middle click
85 * ,------. .. ,------. *
86 * ,------| |-------------. .. ,-------------| |------. *
87 * ,------| |------| | |------. .. ,------| | |------| |------. *
88 * | |------| § |------|------| | .. | |------|------| ± |------| | *
89 * ,------+------| ¶ |------| µ | |------| .. |------| ≤ | ≥ |------| ÷ |------+------. *
90 * | | ¤ |------| { |------|------| ~ | .. | ˇ |------|------| ] |------| × | | *
91 * |------+------| * |------| } | ` |------| .. |------| # | [ |------| % |------+------| *
92 * | | \ |------| ( |------|------| | .. | ≠ |------|------| > |------| ‰ | | *
93 * |------+------| Ù |------| ) | + |------| .. |------| Ç | < |------| & |------+------| *
94 * | | = |------| copy |------|------| : | .. | ? |------|------| PGUP |------| _ | | *
95 * |------+------| cut |------| paste|search|------|-------------. .. .-------------|------| $ | = |------| | |------+------| *
96 * | | undo |------| \ |------|------| | | | .. | | | |------|------| PGDN |------| / | | *
97 * |------+------| |------| | |------|------|------ .. ------|------|------| | HOME |------| PGDN |------+------| *
98 * | | |------/ \-------------| | | .. | | |-------------/ \------| | | *
99 * `-------------/ \-------------/ .. \-------------/ \-------------/ *
100 *
101 */
102[_SYMBOLS] = KEYMAP(
103 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
104 KC_TRNS, BP_DCUR, BP_PARG, BP_SECT, BP_DGRK, KC_TRNS, BP_TILD, BP_DCAR, BP_LEQL, BP_GEQL, BP_PSMS, BP_OBEL, BP_TIMS, KC_TRNS, \
105 KC_TRNS, BP_BSLS, BP_ASTR, BP_LCBR, BP_RCBR, BP_GRV, KC_TRNS, BP_DIFF, BP_HASH, BP_LBRC, BP_RBRC, BP_PERC, BP_PMIL, KC_TRNS, \
106 KC_TRNS, BP_EQL, BP_UGRV, BP_LPRN, BP_RPRN, BP_PLUS, BP_COLN, BP_QEST, BP_CCED, BP_LESS, BP_GRTR, BP_AMPR, BP_UNDS, KC_TRNS, \
107 KC_TRNS, M(M_UN), M(M_CUT),M(M_CP), M(M_PS), M(M_SE), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, BP_DLR, BP_EQL, KC_PGUP, BP_PIPE, BP_SLSH, KC_TRNS, \
108 KC_TRNS, KC_TRNS, BP_BSLS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_END, KC_TRNS, KC_TRNS, \
109 //left pedals
110 KC_TRNS, KC_BTN1, KC_TRNS, \
111 //right pedals
112 KC_TRNS, KC_BTN1, KC_TRNS \
113),
114
115 /* MEDIA, mouse and numpad.
116 * right pedal is left clic
117 * ,------. .. ,------. *
118 * ,------|PAUSE |-------------. .. ,-------------| PRINT|------. *
119 * ,------|SCROLL|------|MUTE |VOLUD |------. .. ,------| pre | next |------| calc |------. *
120 * |RESET |------| stop |------|------|VOLDU | .. | play |------|------| stop |------| num | *
121 * ,------+------| |------| pre | next |------| .. |------| pre | next |------| |------+------. *
122 * | | |------|scrolu|------|------| play | .. | play |------|------| 8 |------| - | | *
123 * |------+------| |------| | bt4 |------| .. |------| next | 7 |------| 9 |------+------| *
124 * | | |------|scrold|------|------| bt5 | .. | pre |------|------| 5 |------| + | | *
125 * |------+------| |------|mclic | rclic|------| .. |------| rclic| 4 |------| 6 |------+------| *
126 * | | |------| |------|------| lclic| .. | lclic|------|------| 2 |------| * | | *
127 * |------+------| |------| | mclck|------|-------------. .. .-------------|------| mclic| 1 |------| 3 |------+------| *
128 * | | |------| |------|------| | | | .. | | | |------|------| num. |------| / | | *
129 * |------+------| |------| | |------|------|------ .. ------|------|------| | 0 |------| . |------+------| *
130 * | | |------/ \-------------| | | .. | | |-------------/ \------| , | | *
131 * `-------------/ \-------------/ .. \-------------/ \-------------/ *
132 *
133 */
134[_MEDIA] = KEYMAP(
135 RESET, KC_SLCK, KC_PAUS, KC_MUTE, KC_VOLD, KC_VOLU, KC_MUTE, KC_VOLD, KC_VOLU, KC_PSCR, KC_CALC, KC_NLCK, \
136 KC_TRNS, KC_TRNS, KC_TRNS, KC_MSTP, KC_MPRV, KC_MNXT, KC_MPLY, KC_MPLY, KC_MPRV, KC_MNXT, KC_MSTP, KC_TRNS, KC_PMNS, KC_TRNS, \
137 KC_TRNS, KC_TRNS, KC_TRNS, KC_WH_U, KC_TRNS, KC_BTN4, KC_BTN5, KC_BTN4, KC_BTN5, KC_KP_7, KC_KP_8, KC_KP_9, KC_PPLS, KC_TRNS, \
138 KC_TRNS, KC_TRNS, KC_TRNS, KC_WH_D, KC_BTN3, KC_BTN2, KC_BTN1, KC_BTN1, KC_BTN2, KC_KP_4, KC_KP_5, KC_KP_6, KC_PAST, KC_TRNS, \
139 KC_TRNS, M(M_UN), M(M_CUT),M(M_CP), M(M_PS), KC_BTN3, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN3, KC_KP_1, KC_KP_2, KC_KP_3, KC_PSLS, KC_TRNS, \
140 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_KP_0, KC_PDOT, BP_DOT, BP_COMM, KC_TRNS, \
141 //left pedals
142 KC_BTN3, M(M_RP), KC_TRNS, \
143 //right pedals
144 KC_BTN3, M(M_RP), KC_TRNS \
145),
146
147/* TRNS - skeleton for laters
148 * ,------. .. ,------. *
149 * ,------| |-------------. .. ,-------------| |------. *
150 * ,------| |------| | |------. .. ,------| | |------| |------. *
151 * | |------| |------|------| | .. | |------|------| |------| | *
152 * ,------+------| |------| | |------| .. |------| | |------| |------+------. *
153 * | | |------| |------|------| | .. | |------|------| |------| | | *
154 * |------+------| |------| | |------| .. |------| | |------| |------+------| *
155 * | | |------| |------|------| | .. | |------|------| |------| | | *
156 * |------+------| |------| | |------| .. |------| | |------| |------+------| *
157 * | | |------| |------|------| | .. | |------|------| |------| | | *
158 * |------+------| |------| | |------|-------------. .. .-------------|------| | |------| |------+------| *
159 * | | |------| |------|------| | | | .. | | | |------|------| |------| | | *
160 * |------+------| |------| | |------|------|------ .. ------|------|------| | |------| |------+------| *
161 * | | |------/ \-------------| | | .. | | |-------------/ \------| | | *
162 * `-------------/ \-------------/ .. \-------------/ \-------------/ *
163 *
164 */
165
166[_TRNS] = KEYMAP(
167 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
168 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
169 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
170 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
171 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
172 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
173 //left pedals
174 KC_BTN3, M(M_RP), KC_TRNS, \
175 //right pedals
176 KC_BTN3, M(M_RP), KC_TRNS \
177),
178
179};
180
181
182const uint16_t PROGMEM fn_actions[] = {
183
184};
185
186void hold_shift(void) {
187 shift_count = shift_count + 1;
188 register_code(KC_LSHIFT);
189}
190
191void release_shift(void) {
192 shift_count = shift_count - 1;
193 if(shift_count <= 0){
194 unregister_code(KC_LSHIFT);
195 shift_count = 0;
196 }
197}
198
199void press_space(void) {
200 if(shift_count > 0) unregister_code (KC_LSHIFT);
201 register_code (KC_SPACE);
202 unregister_code (KC_SPACE);
203 if(shift_count > 0) register_code (KC_LSHIFT);
204}
205
206void press_enter(void) {
207 if(shift_count > 0) unregister_code (KC_LSHIFT);
208 register_code (KC_ENT);
209 unregister_code (KC_ENT);
210 if(shift_count > 0) register_code (KC_LSHIFT);
211}
212
213void press_underscore(void) {
214 if(shift_count > 0) unregister_code (KC_LSHIFT);
215 register_code ((unsigned char) BP_UNDS);
216 unregister_code ((unsigned char) BP_UNDS);
217 if(shift_count > 0) register_code (KC_LSHIFT);
218}
219
220const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
221{
222 switch(id) {
223 case M_LP: //left pedal
224 if (record->event.pressed) {
225 layer_on(1);
226 register_code (KC_SLCK);
227 key_timer_left_pedal = timer_read(); // if the key is being pressed, we start the timer.
228 } else {
229 if (timer_elapsed(key_timer_left_pedal) < KEY_DELAY) {
230 mousekey_on (KC_BTN2);
231 mousekey_send();
232 mousekey_off (KC_BTN2);
233 mousekey_send();
234 }
235 unregister_code (KC_SLCK);
236 layer_off(1);
237 }
238 break;
239 case M_RP: //right pedal
240 if (record->event.pressed) {
241 layer_on(2);
242 key_timer_right_pedal = timer_read(); // if the key is being pressed, we start the timer.
243 } else {
244 if (timer_elapsed(key_timer_right_pedal) < PEDAL_DELAY) {
245 mousekey_on (KC_BTN1);
246 mousekey_send();
247 mousekey_off (KC_BTN1);
248 mousekey_send();
249 }
250 layer_off(2);
251 }
252 break;
253 case M_SF: // shift, using macro to keep track of shift state and avoid inserting nbsp by mistake
254 if (record->event.pressed) {
255 hold_shift();
256 } else {
257 release_shift();
258 }
259 break;
260 case M_SFS: // shift when held, space when tapped
261 if (record->event.pressed) {
262 hold_shift();
263 key_timer_shift = timer_read(); // if the key is being pressed, we start the timer.
264 } else {
265 if (timer_elapsed(key_timer_shift) < KEY_DELAY) {
266 press_space();
267 }
268 release_shift();
269 }
270 break;
271 case M_SFU: // shift when held, _ when tapped
272 if (record->event.pressed) {
273 hold_shift();
274 key_timer_shift = timer_read(); // if the key is being pressed, we start the timer.
275 } else {
276 if (timer_elapsed(key_timer_shift) < KEY_DELAY) {
277 press_space();
278 }
279 release_shift();
280 }
281 break;
282 case M_L1E: // L1 when held, space when tapped
283 if (record->event.pressed) {
284 layer_on(1);
285 key_timer_1 = timer_read(); // if the key is being pressed, we start the timer.
286 } else {
287 if (timer_elapsed(key_timer_1) < KEY_DELAY) {
288 press_enter();
289 }
290 layer_off(1);
291 }
292 break;
293 case L2INS: //activate layer 2, if released before 100ms trigger INS. basicaly equivalent to LT(2, KC_INS) but without delay for activation of layer 2
294 if (record->event.pressed) {
295 layer_on(2);
296 key_timer_2 = timer_read(); // if the key is being pressed, we start the timer.
297 } else {
298 if (timer_elapsed(key_timer_2) < KEY_DELAY) {
299 register_code (KC_INS);
300 unregister_code (KC_INS);
301 }
302 l2_locked = 0;
303 layer_off(2);
304 }
305 break;
306 case L2LOC: //lock L2
307 if (record->event.pressed) {
308 key_timer_2 = timer_read(); // if the key is being pressed, we start the timer.
309 layer_on(2);
310 } else {
311 if (timer_elapsed(key_timer_2) < KEY_DELAY && l2_locked == 0) {
312 l2_locked = 1;
313 layer_on(2);
314 } else {
315 l2_locked = 0;
316 layer_off(2);
317 }
318 }
319 break;
320 case M_UN: // undo
321 if (record->event.pressed) {
322 register_code(KC_LCTL);
323 register_code(BP_Z);
324 unregister_code(BP_Z);
325 unregister_code(KC_LCTL);
326 }
327 break;
328 case M_CUT: // cut
329 if (record->event.pressed) {
330 register_code(KC_LCTL);
331 register_code(BP_X);
332 unregister_code(BP_X);
333 unregister_code(KC_LCTL);
334 }
335 break;
336 case M_CP: // copy
337 if (record->event.pressed) {
338 register_code(KC_LCTL);
339 register_code(BP_C);
340 unregister_code(BP_C);
341 unregister_code(KC_LCTL);
342 }
343 break;
344 case M_PS: // paste
345 if (record->event.pressed) {
346 register_code(KC_LCTL);
347 register_code(BP_V);
348 unregister_code(BP_V);
349 unregister_code(KC_LCTL);
350 }
351 break;
352 case M_SE: // search
353 if (record->event.pressed) {
354 register_code(KC_LCTL);
355 register_code(BP_F);
356 unregister_code(BP_F);
357 unregister_code(KC_LCTL);
358 }
359 break;
360 }
361 return MACRO_NONE;
362};
363
364void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
365
366}
367
368void matrix_init_user(void) {
369}
370
371// Bleah globals need to be initialized.
372uint8_t old_layer=_BASE;
373
374void matrix_scan_user(void) {
375 uint8_t layer = biton32(layer_state);
376
377 frenchdev_led_1_off();
378 frenchdev_led_2_off();
379 switch (layer) {
380 case _BASE:
381 frenchdev_led_2_on();
382 break;
383 case _SYMBOLS:
384 frenchdev_led_1_on();
385 break;
386 case _MEDIA:
387 frenchdev_led_1_on();
388 frenchdev_led_2_on();
389 default:
390 // none
391 break;
392 }
393}
394
395
396bool process_record_user(uint16_t keycode, keyrecord_t *record) {
397 return true;
398}
399
400void led_set_user(uint8_t usb_led) {
401 if (usb_led & (1<<USB_LED_CAPS_LOCK)){
402 frenchdev_led_3_on();
403 } else {
404 frenchdev_led_3_off();
405 }
406 return ;
407}
408
409
diff --git a/keyboards/handwired/frenchdev/keymaps/default/readme.md b/keyboards/handwired/frenchdev/keymaps/default/readme.md
new file mode 100644
index 000000000..1a81d1779
--- /dev/null
+++ b/keyboards/handwired/frenchdev/keymaps/default/readme.md
@@ -0,0 +1,13 @@
1layout :
2
3[default layout](http://i.imgur.com/r2Nvr4p.png)
4
5the thing when finished :
6http://imgur.com/a/6FY8v
7
8concept and mockup:
9http://imgur.com/a/R0vvs
10
11to build :
12
13 docker run --rm -e keymap=default -e keyboard=frenchdev --rm -v D:/Repositories/qmk:/qmk:rw edasque/qmk_firmware
diff --git a/keyboards/handwired/frenchdev/matrix.c b/keyboards/handwired/frenchdev/matrix.c
new file mode 100644
index 000000000..7fe3d0bbf
--- /dev/null
+++ b/keyboards/handwired/frenchdev/matrix.c
@@ -0,0 +1,396 @@
1/*
2
3Note to self: adapted from ergodox EZ matrix
4The "column" and "row" in here actually refers to the opposite on the keyboard
5see definition of KEYMAP in v1.h, the grid is transposed so that a "row" in here is actually a "column" on the physical keyboard
6Nicolas
7
8Note for ErgoDox EZ customizers: Here be dragons!
9This is not a file you want to be messing with.
10All of the interesting stuff for you is under keymaps/ :)
11Love, Erez
12
13Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
14Copyright 2013 Nicolas Poirey <nicolas.poirey@gmail.com>
15
16This program is free software: you can redistribute it and/or modify
17it under the terms of the GNU General Public License as published by
18the Free Software Foundation, either version 2 of the License, or
19(at your option) any later version.
20
21This program is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30/*
31 * scan matrix
32 */
33#include <stdint.h>
34#include <stdbool.h>
35#include <avr/io.h>
36#include "wait.h"
37#include "action_layer.h"
38#include "print.h"
39#include "debug.h"
40#include "util.h"
41#include "matrix.h"
42#include "frenchdev.h"
43#include "i2cmaster.h"
44#ifdef DEBUG_MATRIX_SCAN_RATE
45#include "timer.h"
46#endif
47
48/*
49 * This constant define not debouncing time in msecs, but amount of matrix
50 * scan loops which should be made to get stable debounced results.
51 *
52 * On Ergodox matrix scan rate is relatively low, because of slow I2C.
53 * Now it's only 317 scans/second, or about 3.15 msec/scan.
54 * According to Cherry specs, debouncing time is 5 msec.
55 *
56 * And so, there is no sense to have DEBOUNCE higher than 2.
57 */
58
59#ifndef DEBOUNCE
60# define DEBOUNCE 5
61#endif
62static uint8_t debouncing = DEBOUNCE;
63
64/* matrix state(1:on, 0:off) */
65static matrix_row_t matrix[MATRIX_ROWS];
66static matrix_row_t matrix_debouncing[MATRIX_ROWS];
67
68static matrix_row_t read_cols(uint8_t row);
69static void init_cols(void);
70static void unselect_rows(void);
71static void select_row(uint8_t row);
72
73static uint8_t mcp23018_reset_loop;
74
75#ifdef DEBUG_MATRIX_SCAN_RATE
76uint32_t matrix_timer;
77uint32_t matrix_scan_count;
78#endif
79
80
81__attribute__ ((weak))
82void matrix_init_user(void) {}
83
84__attribute__ ((weak))
85void matrix_scan_user(void) {}
86
87__attribute__ ((weak))
88void matrix_init_kb(void) {
89 matrix_init_user();
90}
91
92__attribute__ ((weak))
93void matrix_scan_kb(void) {
94 matrix_scan_user();
95}
96
97inline
98uint8_t matrix_rows(void)
99{
100 return MATRIX_ROWS;
101}
102
103inline
104uint8_t matrix_cols(void)
105{
106 return MATRIX_COLS;
107}
108
109void matrix_init(void)
110{
111 // initialize row and col
112 debug_enable = true;
113 debug_matrix = true;
114 debug_keyboard = true;
115 debug_mouse = true;
116
117 mcp23018_status = init_mcp23018();
118
119
120 unselect_rows();
121 init_cols();
122
123 // initialize matrix state: all keys off
124 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
125 matrix[i] = 0;
126 matrix_debouncing[i] = 0;
127 }
128
129#ifdef DEBUG_MATRIX_SCAN_RATE
130 matrix_timer = timer_read32();
131 matrix_scan_count = 0;
132#endif
133
134 matrix_init_quantum();
135
136}
137
138void matrix_power_up(void) {
139 mcp23018_status = init_mcp23018();
140
141 unselect_rows();
142 init_cols();
143
144 // initialize matrix state: all keys off
145 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
146 matrix[i] = 0;
147 matrix_debouncing[i] = 0;
148 }
149
150#ifdef DEBUG_MATRIX_SCAN_RATE
151 matrix_timer = timer_read32();
152 matrix_scan_count = 0;
153#endif
154
155}
156
157uint8_t matrix_scan(void)
158{
159 if (mcp23018_status) { // if there was an error
160 if (++mcp23018_reset_loop == 0) {
161 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
162 // this will be approx bit more frequent than once per second
163 print("trying to reset mcp23018\n");
164 mcp23018_status = init_mcp23018();
165 if (mcp23018_status) {
166 print("left side not responding\n");
167 } else {
168 print("left side attached\n");
169 frenchdev_blink_all_leds();
170 }
171 }
172 }
173
174#ifdef DEBUG_MATRIX_SCAN_RATE
175 matrix_scan_count++;
176
177 uint32_t timer_now = timer_read32();
178 if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
179 print("matrix scan frequency: ");
180 pdec(matrix_scan_count);
181 print("\n");
182
183 matrix_timer = timer_now;
184 matrix_scan_count = 0;
185 }
186#endif
187
188 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
189 select_row(i);
190 wait_us(30); // without this wait read unstable value.
191 matrix_row_t cols = read_cols(i);
192 if (matrix_debouncing[i] != cols) {
193 matrix_debouncing[i] = cols;
194 if (debouncing) {
195 debug("bounce!: "); debug_hex(debouncing); debug("\n");
196 }
197 debouncing = DEBOUNCE;
198 }
199 unselect_rows();
200 }
201
202 if (debouncing) {
203 if (--debouncing) {
204 wait_us(1);
205 // this should be wait_ms(1) but has been left as-is at EZ's request
206 } else {
207 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
208 matrix[i] = matrix_debouncing[i];
209 }
210 }
211 }
212
213 matrix_scan_quantum();
214
215 return 1;
216}
217
218bool matrix_is_modified(void)
219{
220 if (debouncing) return false;
221 return true;
222}
223
224inline
225bool matrix_is_on(uint8_t row, uint8_t col)
226{
227 return (matrix[row] & ((matrix_row_t)1<<col));
228}
229
230inline
231matrix_row_t matrix_get_row(uint8_t row)
232{
233 return matrix[row];
234}
235
236void matrix_print(void)
237{
238 print("\nr/c 0123456789ABCDEF\n");
239 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
240 phex(row); print(": ");
241 pbin_reverse16(matrix_get_row(row));
242 print("\n");
243 }
244}
245
246uint8_t matrix_key_count(void)
247{
248 uint8_t count = 0;
249 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
250 count += bitpop16(matrix[i]);
251 }
252 return count;
253}
254
255/* Column pin configuration
256 *
257 * Teensy
258 * col: 0 1 2 3 4 5
259 * pin: F0 F1 F4 F5 F6 F7
260 *
261 * MCP23018
262 * col: 0 1 2 3 4 5
263 * pin: B5 B4 B3 B2 B1 B0
264 */
265static void init_cols(void)
266{
267 // init on mcp23018
268 // not needed, already done as part of init_mcp23018()
269
270 // init on teensy
271 // Input with pull-up(DDR:0, PORT:1)
272 DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
273 PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
274}
275
276static matrix_row_t read_cols(uint8_t row)
277{
278 if (row < 8) {
279 if (mcp23018_status) { // if there was an error
280 return 0;
281 } else {
282 uint8_t data = 0;
283 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
284 mcp23018_status = i2c_write(GPIOB); if (mcp23018_status) goto out;
285 mcp23018_status = i2c_start(I2C_ADDR_READ); if (mcp23018_status) goto out;
286 data = i2c_readNak();
287 data = ~data;
288 out:
289 i2c_stop();
290 return data;
291 }
292 } else {
293 // read from teensy
294 return
295 (PINF&(1<<0) ? 0 : (1<<0)) |
296 (PINF&(1<<1) ? 0 : (1<<1)) |
297 (PINF&(1<<4) ? 0 : (1<<2)) |
298 (PINF&(1<<5) ? 0 : (1<<3)) |
299 (PINF&(1<<6) ? 0 : (1<<4)) |
300 (PINF&(1<<7) ? 0 : (1<<5)) ;
301 }
302}
303
304/* Row pin configuration
305 *
306 * Teensy
307 * row: 7 8 9 10 11 12 13
308 * pin: B0 B1 B2 B3 D2 D3 C6
309 *
310 * MCP23018
311 * row: 0 1 2 3 4 5 6
312 * pin: A0 A1 A2 A3 A4 A5 A6
313 */
314static void unselect_rows(void)
315{
316 // unselect on mcp23018
317 if (mcp23018_status) { // if there was an error
318 // do nothing
319 } else {
320 // set all rows hi-Z : 1
321 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
322 mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
323 mcp23018_status = i2c_write( 0xFF
324 & ~(0<<8)
325 ); if (mcp23018_status) goto out;
326 out:
327 i2c_stop();
328 }
329
330 // unselect on teensy
331 // Hi-Z(DDR:0, PORT:0) to unselect
332 DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
333 PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
334 DDRD &= ~(1<<2 | 1<<3);
335 PORTD &= ~(1<<2 | 1<<3);
336 DDRC &= ~(1<<6 | 1<<7);
337 PORTC &= ~(1<<6 | 1<<7);
338}
339
340static void select_row(uint8_t row)
341{
342 if (row < 8) {
343 // select on mcp23018
344 if (mcp23018_status) { // if there was an error
345 // do nothing
346 } else {
347 // set active row low : 0
348 // set other rows hi-Z : 1
349 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
350 mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
351 mcp23018_status = i2c_write( 0xFF & ~(1<<row)
352 & ~(0<<8)
353 ); if (mcp23018_status) goto out;
354 out:
355 i2c_stop();
356 }
357 } else {
358 // select on teensy
359 // Output low(DDR:1, PORT:0) to select
360 switch (row) {
361 case 8:
362 DDRB |= (1<<0);
363 PORTB &= ~(1<<0);
364 break;
365 case 9:
366 DDRB |= (1<<1);
367 PORTB &= ~(1<<1);
368 break;
369 case 10:
370 DDRB |= (1<<2);
371 PORTB &= ~(1<<2);
372 break;
373 case 11:
374 DDRB |= (1<<3);
375 PORTB &= ~(1<<3);
376 break;
377 case 12:
378 DDRD |= (1<<2);
379 PORTD &= ~(1<<3);
380 break;
381 case 13:
382 DDRD |= (1<<3);
383 PORTD &= ~(1<<3);
384 break;
385 case 14:
386 DDRC |= (1<<6);
387 PORTC &= ~(1<<6);
388 break;
389 case 15:
390 DDRC |= (1<<7);
391 PORTC &= ~(1<<7);
392 break;
393 }
394 }
395}
396
diff --git a/keyboards/handwired/frenchdev/readme.md b/keyboards/handwired/frenchdev/readme.md
new file mode 100644
index 000000000..698b4befb
--- /dev/null
+++ b/keyboards/handwired/frenchdev/readme.md
@@ -0,0 +1,102 @@
1# Frenchdev : My take on a splitted keyboard for dev and french language
2Concept based on
3 - [ergodox](https://ergodox-ez.com/)
4 - [katy](https://deskthority.net/workshop-f7/katy-keyboard-or-k80cs-key80-contoured-split-t8524.html)
5
6with the added possibility to connect up to 6 external switches like pedals,
7 and somewhat like the katy, not all keys are on the same level for easier reach.
8
9###Photos
10- [default layout](http://i.imgur.com/r2Nvr4p.png)
11- [editable layout on keyboard layout editor](http://www.keyboard-layout-editor.com/#/gists/4480e3ab8026eb7c710a7e22203ef4aa) (keys placement is NOT precise on this)
12- [the thing when finished](http://imgur.com/a/6FY8v)
13- [concept and cardboard mockup](http://imgur.com/a/R0vvs)
14
15##Build instructions
16
17 docker run --rm -e keymap=default -e keyboard=frenchdev --rm -v D:/Repositories/qmk:/qmk:rw edasque/qmk_firmware
18
19##Laser-cuttable file
20There is intentionnaly no hole for the TRRS connector, you are supposed to use a drill for it.
21This way if you don't want to use the pedals you don't have a useless hole. Plus it's cleaner.
22http://qmk.fm/frenchdev/frenchdev_v1_lasercut_template.svg
23
24##Side stickers
25You can find my original file here : http://qmk.fm/frenchdev/example_printable_stickers.svg
26
27I used it when training but now I use blanks and the layout is different.
28I still uploaded it because I think it can be a good jumpstart for any temporary stickers on the
29side of keycaps.
30
31##List of parts
32- I2C mcp23018
33- [teensy 2](https://www.pjrc.com/store/teensy.html)
34- 3 LED, 5mm tall with flat head
35- 3 330 ohm resistor
36- 2 470 ohm resistor
37- 2 TRRS connectors
38- 1 [micro usb breakout board](http://www.ebay.com/itm/-/201387922085?)
39- 88 cherry/gateron switchs
40- 94 4148 diodes
41- 34 R4 keys
42- 14 R3 keys
43- 20 R2 keys
44- 22 R1 keys
45
46if you fancy adding pedals :
47[these are good enough and cheap](https://www.amazon.fr/gp/product/B00V7WITKI/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1). You also need a RCA connector for each of those to replace the included cable
48
49If you (or your coworkers) find them too loud you can replace the switch inside them.
50For once we don't really care about what's inside :)
51
52##Various indications
53
54The PHYSICAL rows and columns are connected as such :
55
56on right hand (slave) :
57
58 I2C mcp23018
59 .------- --------.
60 GND -| 1 VSS \_/ NC 28 |
61 | 2 NC A7 27 |- C15
62 R5 -| 3 B0 A6 26 |- C14
63 R4 -| 4 B1 A5 25 |- C13
64 R3 -| 5 B2 A4 24 |- C12
65 R2 -| 6 B3 A3 23 |- C11
66 R1 -| 7 B4 A2 22 |- C10
67 R0 -| 8 B5 A1 21 |- C9
68 | 9 B6 A0 20 |- C8
69 | 10 B7 INTA 19 |
70 VCC -| 11 VDD INTB 18 |
71 SCL -| 12 SCL NC 17 |
72 SDA -| 13 SDA RST 16 |- VCC
73 | 14 NC ADDR 15 |- GND
74 `------------------'
75
76and on left hand (main) :
77
78 TEENSY
79 .------------------.
80 | GND VCC |
81 C7 -| B0 F0 |- R5
82 C6 -| B1 F1 |- R4
83 C5 -| B2 F4 |- R3
84 C4 -| B3 F5 |- R2
85 LEDC -| B7 F6 |- R1
86 SCL -| D0 F7 |- R0
87 SDA -| D1 B6 |- LEDB
88 C3 -| D2 B5 |- LEDA
89 C2 -| D3 B4 |
90 C1 -| C6 D7 |
91 C0 -| C7 D6 |- GND
92 | D5 D4 |
93 | VCC RST |
94 | E6 GND |
95 `------------------'
96
97We use pull up resistor for SCL and VDA, see https://github.com/ErgoDox-EZ/docs/blob/master/ErgoDox%20EZ%20Schematic.pdf for example
98
99the connector is a standard TRRS (jack with audio + mic)
100
101Diode direction is row to column
102
diff --git a/keyboards/handwired/frenchdev/rules.mk b/keyboards/handwired/frenchdev/rules.mk
new file mode 100644
index 000000000..16203a5f5
--- /dev/null
+++ b/keyboards/handwired/frenchdev/rules.mk
@@ -0,0 +1,92 @@
1#----------------------------------------------------------------------------
2# On command line:
3#
4# make = Make software.
5#
6# make clean = Clean out built project files.
7#
8# That's pretty much all you need. To compile, always go make clean,
9# followed by make.
10#
11# For advanced users only:
12# make teensy = Download the hex file to the device, using teensy_loader_cli.
13# (must have teensy_loader_cli installed).
14#
15#----------------------------------------------------------------------------
16
17# # project specific files
18SRC = twimaster.c \
19 matrix.c
20
21# MCU name
22MCU = atmega32u4
23
24# Processor frequency.
25# This will define a symbol, F_CPU, in all source code files equal to the
26# processor frequency in Hz. You can then use this symbol in your source code to
27# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
28# automatically to create a 32-bit value in your source code.
29#
30# This will be an integer division of F_USB below, as it is sourced by
31# F_USB after it has run through any CPU prescalers. Note that this value
32# does not *change* the processor frequency - it should merely be updated to
33# reflect the processor speed set externally so that the code can use accurate
34# software delays.
35F_CPU = 16000000
36
37
38#
39# LUFA specific
40#
41# Target architecture (see library "Board Types" documentation).
42ARCH = AVR8
43
44# Input clock frequency.
45# This will define a symbol, F_USB, in all source code files equal to the
46# input clock frequency (before any prescaling is performed) in Hz. This value may
47# differ from F_CPU if prescaling is used on the latter, and is required as the
48# raw input clock is fed directly to the PLL sections of the AVR for high speed
49# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
50# at the end, this will be done automatically to create a 32-bit value in your
51# source code.
52#
53# If no clock division is performed on the input clock inside the AVR (via the
54# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
55F_USB = $(F_CPU)
56
57# Interrupt driven control endpoint task(+60)
58OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
59
60
61# Boot Section Size in *bytes*
62# Teensy halfKay 512
63# Teensy++ halfKay 1024
64# Atmel DFU loader 4096
65# LUFA bootloader 4096
66# USBaspLoader 2048
67OPT_DEFS += -DBOOTLOADER_SIZE=512
68
69
70# Build Options
71# comment out to disable the options.
72#
73BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
74MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
75EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
76CONSOLE_ENABLE ?= yes # Console for debug(+400)
77COMMAND_ENABLE ?= yes # Commands for debug and configuration
78CUSTOM_MATRIX ?= yes # Custom matrix file (taken and adapted from the ErgoDox EZ to handle custom number of columns)
79SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
80NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
81UNICODE_ENABLE ?= yes # Unicode
82BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
83MIDI_ENABLE ?= no # MIDI controls
84UNICODE_ENABLE ?= no # Unicode
85BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
86AUDIO_ENABLE ?= no # Audio output on port C6
87RGBLIGHT_ENABLE = no
88API_SYSEX_ENABLE ?= no
89
90#ifndef QUANTUM_DIR
91# include ../../../Makefile
92#endif
diff --git a/keyboards/handwired/frenchdev/twimaster.c b/keyboards/handwired/frenchdev/twimaster.c
new file mode 100644
index 000000000..f91c08e6e
--- /dev/null
+++ b/keyboards/handwired/frenchdev/twimaster.c
@@ -0,0 +1,208 @@
1/*************************************************************************
2* Title: I2C master library using hardware TWI interface
3* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
4* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6* Target: any AVR device with hardware TWI
7* Usage: API compatible with I2C Software Library i2cmaster.h
8**************************************************************************/
9#include <inttypes.h>
10#include <compat/twi.h>
11
12#include <i2cmaster.h>
13
14
15/* define CPU frequency in Mhz here if not defined in Makefile */
16#ifndef F_CPU
17#define F_CPU 16000000UL
18#endif
19
20/* I2C clock in Hz */
21#define SCL_CLOCK 400000L
22
23
24/*************************************************************************
25 Initialization of the I2C bus interface. Need to be called only once
26*************************************************************************/
27void i2c_init(void)
28{
29 /* initialize TWI clock
30 * minimal values in Bit Rate Register (TWBR) and minimal Prescaler
31 * bits in the TWI Status Register should give us maximal possible
32 * I2C bus speed - about 444 kHz
33 *
34 * for more details, see 20.5.2 in ATmega16/32 secification
35 */
36
37 TWSR = 0; /* no prescaler */
38 TWBR = 10; /* must be >= 10 for stable operation */
39
40}/* i2c_init */
41
42
43/*************************************************************************
44 Issues a start condition and sends address and transfer direction.
45 return 0 = device accessible, 1= failed to access device
46*************************************************************************/
47unsigned char i2c_start(unsigned char address)
48{
49 uint8_t twst;
50
51 // send START condition
52 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
53
54 // wait until transmission completed
55 while(!(TWCR & (1<<TWINT)));
56
57 // check value of TWI Status Register. Mask prescaler bits.
58 twst = TW_STATUS & 0xF8;
59 if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
60
61 // send device address
62 TWDR = address;
63 TWCR = (1<<TWINT) | (1<<TWEN);
64
65 // wail until transmission completed and ACK/NACK has been received
66 while(!(TWCR & (1<<TWINT)));
67
68 // check value of TWI Status Register. Mask prescaler bits.
69 twst = TW_STATUS & 0xF8;
70 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
71
72 return 0;
73
74}/* i2c_start */
75
76
77/*************************************************************************
78 Issues a start condition and sends address and transfer direction.
79 If device is busy, use ack polling to wait until device is ready
80
81 Input: address and transfer direction of I2C device
82*************************************************************************/
83void i2c_start_wait(unsigned char address)
84{
85 uint8_t twst;
86
87
88 while ( 1 )
89 {
90 // send START condition
91 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
92
93 // wait until transmission completed
94 while(!(TWCR & (1<<TWINT)));
95
96 // check value of TWI Status Register. Mask prescaler bits.
97 twst = TW_STATUS & 0xF8;
98 if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
99
100 // send device address
101 TWDR = address;
102 TWCR = (1<<TWINT) | (1<<TWEN);
103
104 // wail until transmission completed
105 while(!(TWCR & (1<<TWINT)));
106
107 // check value of TWI Status Register. Mask prescaler bits.
108 twst = TW_STATUS & 0xF8;
109 if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
110 {
111 /* device busy, send stop condition to terminate write operation */
112 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
113
114 // wait until stop condition is executed and bus released
115 while(TWCR & (1<<TWSTO));
116
117 continue;
118 }
119 //if( twst != TW_MT_SLA_ACK) return 1;
120 break;
121 }
122
123}/* i2c_start_wait */
124
125
126/*************************************************************************
127 Issues a repeated start condition and sends address and transfer direction
128
129 Input: address and transfer direction of I2C device
130
131 Return: 0 device accessible
132 1 failed to access device
133*************************************************************************/
134unsigned char i2c_rep_start(unsigned char address)
135{
136 return i2c_start( address );
137
138}/* i2c_rep_start */
139
140
141/*************************************************************************
142 Terminates the data transfer and releases the I2C bus
143*************************************************************************/
144void i2c_stop(void)
145{
146 /* send stop condition */
147 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
148
149 // wait until stop condition is executed and bus released
150 while(TWCR & (1<<TWSTO));
151
152}/* i2c_stop */
153
154
155/*************************************************************************
156 Send one byte to I2C device
157
158 Input: byte to be transfered
159 Return: 0 write successful
160 1 write failed
161*************************************************************************/
162unsigned char i2c_write( unsigned char data )
163{
164 uint8_t twst;
165
166 // send data to the previously addressed device
167 TWDR = data;
168 TWCR = (1<<TWINT) | (1<<TWEN);
169
170 // wait until transmission completed
171 while(!(TWCR & (1<<TWINT)));
172
173 // check value of TWI Status Register. Mask prescaler bits
174 twst = TW_STATUS & 0xF8;
175 if( twst != TW_MT_DATA_ACK) return 1;
176 return 0;
177
178}/* i2c_write */
179
180
181/*************************************************************************
182 Read one byte from the I2C device, request more data from device
183
184 Return: byte read from I2C device
185*************************************************************************/
186unsigned char i2c_readAck(void)
187{
188 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
189 while(!(TWCR & (1<<TWINT)));
190
191 return TWDR;
192
193}/* i2c_readAck */
194
195
196/*************************************************************************
197 Read one byte from the I2C device, read is followed by a stop condition
198
199 Return: byte read from I2C device
200*************************************************************************/
201unsigned char i2c_readNak(void)
202{
203 TWCR = (1<<TWINT) | (1<<TWEN);
204 while(!(TWCR & (1<<TWINT)));
205
206 return TWDR;
207
208}/* i2c_readNak */